Skip to content

Commit

Permalink
Merge pull request #121 from breedx-splk/introduce-config
Browse files Browse the repository at this point in the history
Introduce configuration for instrumentation components (phase 1)
  • Loading branch information
breedx-splk authored Oct 27, 2023
2 parents 5db424c + 6b659ad commit f73395e
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,32 @@
public interface OpenTelemetryRum {

/**
* Returns a new {@link OpenTelemetryRumBuilder} for {@link OpenTelemetryRum}. Use this version
* if you would like to configure individual aspects of the OpenTelemetry SDK but would still
* prefer to allow OpenTelemetry RUM to create the SDK for you. If you would like to "bring your
* own" SDK, call the two-argument version.
* Returns a new {@link OpenTelemetryRumBuilder} for {@link OpenTelemetryRum} with a default
* configuration. Use this version if you would like to configure individual aspects of the
* OpenTelemetry SDK but would still prefer to allow OpenTelemetry RUM to create the SDK for
* you. For additional configuration, call the two-argument version of build and pass it your
* {@link OtelRumConfig} instance. If you would like to "bring your own" SDK, call the
* two-argument version that takes the SDK as a parameter.
*
* @param application The {@link Application} that is being instrumented.
*/
static OpenTelemetryRumBuilder builder(Application application) {
return new OpenTelemetryRumBuilder(application);
return builder(application, new OtelRumConfig());
}

/**
* Returns a new {@link OpenTelemetryRumBuilder} for {@link OpenTelemetryRum} with the given
* configuration. Use this version if you would like to configure individual aspects of the
* OpenTelemetry SDK but would still prefer to allow OpenTelemetry RUM to create the SDK for
* you. If you would like to "bring your own" SDK, call the two-argument version that takes the
* SDK as a parameter.
*
* @param application
* @param config
* @return
*/
static OpenTelemetryRumBuilder builder(Application application, OtelRumConfig config) {
return new OpenTelemetryRumBuilder(application, config);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

import android.app.Application;
import io.opentelemetry.android.instrumentation.InstrumentedApplication;
import io.opentelemetry.android.instrumentation.activity.VisibleScreenTracker;
import io.opentelemetry.android.instrumentation.network.CurrentNetworkProvider;
import io.opentelemetry.android.instrumentation.network.NetworkAttributesSpanAppender;
import io.opentelemetry.android.instrumentation.startup.InitializationEvents;
import io.opentelemetry.android.instrumentation.startup.SdkInitializationEvents;
import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.propagation.ContextPropagators;
Expand All @@ -22,6 +27,7 @@
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
import io.opentelemetry.sdk.trace.SpanProcessor;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.ArrayList;
Expand All @@ -47,6 +53,8 @@ public final class OpenTelemetryRumBuilder {
meterProviderCustomizers = new ArrayList<>();
private final List<BiFunction<SdkLoggerProviderBuilder, Application, SdkLoggerProviderBuilder>>
loggerProviderCustomizers = new ArrayList<>();
private final OtelRumConfig config;
private final VisibleScreenTracker visibleScreenTracker = new VisibleScreenTracker();

private Function<? super SpanExporter, ? extends SpanExporter> spanExporterCustomizer = a -> a;
private final List<Consumer<InstrumentedApplication>> instrumentationInstallers =
Expand All @@ -56,17 +64,19 @@ public final class OpenTelemetryRumBuilder {
(a) -> a;

private Resource resource;
private InitializationEvents initializationEvents = InitializationEvents.NO_OP;

private static TextMapPropagator buildDefaultPropagator() {
return TextMapPropagator.composite(
W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance());
}

OpenTelemetryRumBuilder(Application application) {
OpenTelemetryRumBuilder(Application application, OtelRumConfig config) {
this.application = application;
SessionIdTimeoutHandler timeoutHandler = new SessionIdTimeoutHandler();
this.sessionId = new SessionId(timeoutHandler);
this.resource = AndroidResource.createDefault(application);
this.config = config;
}

/**
Expand Down Expand Up @@ -216,6 +226,9 @@ public SessionId getSessionId() {
* @return A new {@link OpenTelemetryRum} instance.
*/
public OpenTelemetryRum build() {

applyConfiguration();

OpenTelemetrySdk sdk =
OpenTelemetrySdk.builder()
.setTracerProvider(buildTracerProvider(sessionId, application))
Expand All @@ -230,6 +243,50 @@ public OpenTelemetryRum build() {
return delegate.build();
}

/** Leverage the configuration to wire up various instrumentation components. */
private void applyConfiguration() {
if (config.shouldGenerateSdkInitializationEvents()) {
initializationEvents = new SdkInitializationEvents();
initializationEvents.recordConfiguration(config);
}
initializationEvents.sdkInitializationStarted();

// Global attributes
if (config.hasGlobalAttributes()) {
// Add span processor that appends global attributes.
GlobalAttributesSpanAppender appender =
GlobalAttributesSpanAppender.create(config.getGlobalAttributes());
addTracerProviderCustomizer(
(tracerProviderBuilder, app) ->
tracerProviderBuilder.addSpanProcessor(appender));
}

// Network specific attributes
if (config.shouldIncludeNetworkAttributes()) {
// Add span processor that appends network attributes.
CurrentNetworkProvider currentNetworkProvider =
CurrentNetworkProvider.createAndStart(application);
addTracerProviderCustomizer(
(tracerProviderBuilder, app) -> {
SpanProcessor networkAttributesSpanAppender =
NetworkAttributesSpanAppender.create(currentNetworkProvider);
return tracerProviderBuilder.addSpanProcessor(
networkAttributesSpanAppender);
});
initializationEvents.currentNetworkProviderInitialized();
}

// Add span processor that appends screen attribute(s)
if (config.shouldIncludeScreenAttributes()) {
addTracerProviderCustomizer(
(tracerProviderBuilder, app) -> {
SpanProcessor screenAttributesAppender =
new ScreenAttributesSpanProcessor(visibleScreenTracker);
return tracerProviderBuilder.addSpanProcessor(screenAttributesAppender);
});
}
}

private SdkTracerProvider buildTracerProvider(SessionId sessionId, Application application) {
SdkTracerProviderBuilder tracerProviderBuilder =
SdkTracerProvider.builder()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android;

import io.opentelemetry.android.instrumentation.network.CurrentNetworkProvider;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;

/**
* Configuration object for OpenTelemetry Android. The configuration items in this class will be
* used in the OpenTelemetryRumBuilder to wire up and enable/disable various mobile instrumentation
* components.
*/
public class OtelRumConfig {

private AttributesBuilder globalAttributes = Attributes.builder();
private boolean includeNetworkAttributes = true;
private boolean generateSdkInitializationEvents = true;
private boolean includeScreenAttributes = true;

/**
* Configures the set of global attributes to emit with every span and event. Any existing
* configured attributes will be dropped. Default = none.
*/
public OtelRumConfig setGlobalAttributes(Attributes attributes) {
globalAttributes = attributes.toBuilder();
return this;
}

boolean hasGlobalAttributes() {
return !globalAttributes.build().isEmpty();
}

Attributes getGlobalAttributes() {
return globalAttributes.build();
}

/**
* Disables the collection of runtime network attributes. See {@link CurrentNetworkProvider} for
* more information. Default = true.
*
* @return this
*/
public OtelRumConfig disableNetworkAttributes() {
includeNetworkAttributes = false;
return this;
}

/** Returns true if runtime network attributes are enabled, false otherwise. */
public boolean shouldIncludeNetworkAttributes() {
return includeNetworkAttributes;
}

/**
* Disables the collection of events related to the initialization of the OTel Android SDK
* itself. Default = true.
*
* @return this
*/
public OtelRumConfig disableSdkInitializationEvents() {
this.generateSdkInitializationEvents = false;
return this;
}

/** Returns true if the SDK is configured to generate initialization events, false otherwise. */
public boolean shouldGenerateSdkInitializationEvents() {
return generateSdkInitializationEvents;
}

/**
* Call this to disable the collection of screen attributes. See {@link
* ScreenAttributesSpanProcessor} for more information. Default = true.
*
* @return this
*/
public OtelRumConfig disableScreenAttributes() {
this.includeScreenAttributes = false;
return this;
}

/** Return true if the SDK should be configured to report screen attributes. */
public boolean shouldIncludeScreenAttributes() {
return includeScreenAttributes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android;

import static io.opentelemetry.android.RumConstants.SCREEN_NAME_KEY;

import io.opentelemetry.android.instrumentation.activity.VisibleScreenTracker;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.sdk.trace.SpanProcessor;

class ScreenAttributesSpanProcessor implements SpanProcessor {

private final VisibleScreenTracker visibleScreenTracker;

public ScreenAttributesSpanProcessor(VisibleScreenTracker visibleScreenTracker) {
this.visibleScreenTracker = visibleScreenTracker;
}

@Override
public void onStart(Context parentContext, ReadWriteSpan span) {
String currentScreen = visibleScreenTracker.getCurrentlyVisibleScreen();
span.setAttribute(SCREEN_NAME_KEY, currentScreen);
}

@Override
public boolean isStartRequired() {
return true;
}

@Override
public void onEnd(ReadableSpan span) {
// nop
}

@Override
public boolean isEndRequired() {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.instrumentation.startup;

import io.opentelemetry.android.OtelRumConfig;

public interface InitializationEvents {

void sdkInitializationStarted();

void recordConfiguration(OtelRumConfig config);

void currentNetworkProviderInitialized();

InitializationEvents NO_OP =
new InitializationEvents() {
@Override
public void sdkInitializationStarted() {}

@Override
public void recordConfiguration(OtelRumConfig config) {}

@Override
public void currentNetworkProviderInitialized() {}
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.instrumentation.startup;

import io.opentelemetry.android.OtelRumConfig;

public class SdkInitializationEvents implements InitializationEvents {

@Override
public void sdkInitializationStarted() {
// TODO: Build me
}

@Override
public void recordConfiguration(OtelRumConfig config) {
// TODO: Build me (create event containing the config params for the sdk)
}

@Override
public void currentNetworkProviderInitialized() {
// TODO: Build me
}
}
Loading

0 comments on commit f73395e

Please sign in to comment.