Skip to content

Commit

Permalink
Refactor ActivityCallbacks (#478)
Browse files Browse the repository at this point in the history
* move AnchoredClock to top level

* move AppStartupTimer and create RumConstants. Add `clockNow()` to `AppStartupTimer` for delegation.

* move activity instrumentation to rum package

* move pre29 visible binding

* move fragment instrumentation

* spotless

* address todos/inject activespan

* add builder to activitytracer

* add builder

* update volley test

* builder setters

* builder setters

* keep COMPONENT_KEY within splunk namespace (for now)

* keep COMPONENT_KEY within splunk namespace (for now)

* keep COMPONENT_KEY within splunk namespace (for now)

* import

* fix javadoc

* code review comments
  • Loading branch information
breedx-splk authored Feb 22, 2023
1 parent e63ac4c commit 64a9e4a
Show file tree
Hide file tree
Showing 43 changed files with 607 additions and 410 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.splunk.rum;

import static com.splunk.rum.SplunkRum.COMPONENT_KEY;
import static com.splunk.rum.SplunkRum.LINK_SPAN_ID_KEY;
import static com.splunk.rum.SplunkRum.LINK_TRACE_ID_KEY;

Expand All @@ -38,7 +39,7 @@ public VolleyResponseAttributesExtractor(ServerTimingHeaderParser serverTimingHe
@Override
public void onStart(
AttributesBuilder attributes, Context parentContext, RequestWrapper requestWrapper) {
attributes.put(SplunkRum.COMPONENT_KEY, "http");
attributes.put(COMPONENT_KEY, "http");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.splunk.rum;

import static com.splunk.rum.SplunkRum.COMPONENT_KEY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -51,7 +52,7 @@ public void spanDecoration() {
attributesExtractor.onEnd(attributesBuilder, null, fakeRequest, response, null);
Attributes attributes = attributesBuilder.build();

assertEquals("http", attributes.get(SplunkRum.COMPONENT_KEY));
assertEquals("http", attributes.get(COMPONENT_KEY));
assertEquals(
"9499195c502eb217c448a68bfe0f967c", attributes.get(SplunkRum.LINK_TRACE_ID_KEY));
assertEquals("fe16eca542cd5d86", attributes.get(SplunkRum.LINK_SPAN_ID_KEY));
Expand All @@ -73,7 +74,7 @@ public void spanDecoration_noLinkingHeader() {
attributesExtractor.onStart(attributesBuilder, null, fakeRequest);
Attributes attributes = attributesBuilder.build();

assertEquals("http", attributes.get(SplunkRum.COMPONENT_KEY));
assertEquals("http", attributes.get(COMPONENT_KEY));
assertNull(attributes.get(SplunkRum.LINK_TRACE_ID_KEY));
assertNull(attributes.get(SplunkRum.LINK_SPAN_ID_KEY));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.splunk.rum;

import static com.splunk.rum.SplunkRum.COMPONENT_KEY;

import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
Expand All @@ -38,7 +40,7 @@ public void onStart(
crashHappened.compareAndSet(false, true)
? SplunkRum.COMPONENT_CRASH
: SplunkRum.COMPONENT_ERROR;
attributes.put(SplunkRum.COMPONENT_KEY, component);
attributes.put(COMPONENT_KEY, component);
}

@Override
Expand Down
107 changes: 61 additions & 46 deletions splunk-otel-android/src/main/java/com/splunk/rum/RumInitializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
package com.splunk.rum;

import static com.splunk.rum.SplunkRum.APP_NAME_KEY;
import static com.splunk.rum.SplunkRum.COMPONENT_APPSTART;
import static com.splunk.rum.SplunkRum.COMPONENT_ERROR;
import static com.splunk.rum.SplunkRum.COMPONENT_KEY;
import static com.splunk.rum.SplunkRum.COMPONENT_UI;
import static com.splunk.rum.SplunkRum.RUM_TRACER_NAME;
import static com.splunk.rum.SplunkRum.RUM_VERSION_KEY;
import static io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor.constant;
import static io.opentelemetry.rum.internal.RumConstants.APP_START_SPAN_NAME;
import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.DEPLOYMENT_ENVIRONMENT;
import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.DEVICE_MODEL_IDENTIFIER;
import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.DEVICE_MODEL_NAME;
Expand All @@ -46,14 +49,21 @@
import io.opentelemetry.rum.internal.OpenTelemetryRum;
import io.opentelemetry.rum.internal.OpenTelemetryRumBuilder;
import io.opentelemetry.rum.internal.instrumentation.InstrumentedApplication;
import io.opentelemetry.rum.internal.instrumentation.activity.ActivityCallbacks;
import io.opentelemetry.rum.internal.instrumentation.activity.ActivityTracerCache;
import io.opentelemetry.rum.internal.instrumentation.activity.Pre29ActivityCallbacks;
import io.opentelemetry.rum.internal.instrumentation.activity.Pre29VisibleScreenLifecycleBinding;
import io.opentelemetry.rum.internal.instrumentation.activity.RumFragmentActivityRegisterer;
import io.opentelemetry.rum.internal.instrumentation.activity.VisibleScreenLifecycleBinding;
import io.opentelemetry.rum.internal.instrumentation.activity.VisibleScreenTracker;
import io.opentelemetry.rum.internal.instrumentation.anr.AnrDetector;
import io.opentelemetry.rum.internal.instrumentation.crash.CrashReporter;
import io.opentelemetry.rum.internal.instrumentation.fragment.RumFragmentLifecycleCallbacks;
import io.opentelemetry.rum.internal.instrumentation.network.CurrentNetworkProvider;
import io.opentelemetry.rum.internal.instrumentation.network.NetworkAttributesSpanAppender;
import io.opentelemetry.rum.internal.instrumentation.network.NetworkChangeMonitor;
import io.opentelemetry.rum.internal.instrumentation.slowrendering.SlowRenderingDetector;
import io.opentelemetry.sdk.common.Clock;
import io.opentelemetry.rum.internal.instrumentation.startup.AppStartupTimer;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.resources.ResourceBuilder;
Expand Down Expand Up @@ -85,32 +95,31 @@ class RumInitializer {
private final Application application;
private final AppStartupTimer startupTimer;
private final List<RumInitializer.InitializationEvent> initializationEvents = new ArrayList<>();
private final AnchoredClock timingClock;

RumInitializer(
SplunkRumBuilder builder, Application application, AppStartupTimer startupTimer) {
this.builder = builder;
this.application = application;
this.startupTimer = startupTimer;
this.timingClock = startupTimer.startupClock;
}

SplunkRum initialize(
Function<Application, CurrentNetworkProvider> currentNetworkProviderFactory,
Looper mainLooper) {
VisibleScreenTracker visibleScreenTracker = new VisibleScreenTracker();

long startTimeNanos = timingClock.now();
long startTimeNanos = startupTimer.clockNow();
OpenTelemetryRumBuilder otelRumBuilder = OpenTelemetryRum.builder();

otelRumBuilder.setResource(createResource());
initializationEvents.add(
new RumInitializer.InitializationEvent("resourceInitialized", timingClock.now()));
new RumInitializer.InitializationEvent(
"resourceInitialized", startupTimer.clockNow()));

CurrentNetworkProvider currentNetworkProvider =
currentNetworkProviderFactory.apply(application);
initializationEvents.add(
new InitializationEvent("connectionUtilInitialized", timingClock.now()));
new InitializationEvent("connectionUtilInitialized", startupTimer.clockNow()));

GlobalAttributesSpanAppender globalAttributesSpanAppender =
GlobalAttributesSpanAppender.create(builder.globalAttributes);
Expand All @@ -122,18 +131,18 @@ SplunkRum initialize(
new ScreenAttributesAppender(visibleScreenTracker);
initializationEvents.add(
new RumInitializer.InitializationEvent(
"attributeAppenderInitialized", timingClock.now()));
"attributeAppenderInitialized", startupTimer.clockNow()));

SpanExporter zipkinExporter = buildFilteringExporter(currentNetworkProvider);
initializationEvents.add(
new RumInitializer.InitializationEvent(
"exporterInitialized", timingClock.now()));
"exporterInitialized", startupTimer.clockNow()));

BatchSpanProcessor batchSpanProcessor =
BatchSpanProcessor.builder(zipkinExporter).build();
initializationEvents.add(
new RumInitializer.InitializationEvent(
"batchSpanProcessorInitialized", timingClock.now()));
"batchSpanProcessorInitialized", startupTimer.clockNow()));

tracerProviderBuilder
.addSpanProcessor(globalAttributesSpanAppender)
Expand All @@ -159,12 +168,12 @@ SplunkRum initialize(
LoggingSpanExporter.create())));
initializationEvents.add(
new RumInitializer.InitializationEvent(
"debugSpanExporterInitialized", timingClock.now()));
"debugSpanExporterInitialized", startupTimer.clockNow()));
}

initializationEvents.add(
new RumInitializer.InitializationEvent(
"tracerProviderInitialized", timingClock.now()));
"tracerProviderInitialized", startupTimer.clockNow()));
return tracerProviderBuilder;
});

Expand Down Expand Up @@ -206,7 +215,8 @@ private void installLifecycleInstrumentations(
instrumentedApp -> {
initializationEvents.add(
new InitializationEvent(
"activityLifecycleCallbacksInitialized", timingClock.now()));
"activityLifecycleCallbacksInitialized",
startupTimer.clockNow()));
});
}

Expand Down Expand Up @@ -246,7 +256,12 @@ private void installFragmentLifecycleInstrumentation(
@NonNull
private Application.ActivityLifecycleCallbacks buildFragmentRegisterer(
VisibleScreenTracker visibleScreenTracker, InstrumentedApplication instrumentedApp) {
Tracer tracer = instrumentedApp.getOpenTelemetrySdk().getTracer(RUM_TRACER_NAME);
Tracer delegateTracer = instrumentedApp.getOpenTelemetrySdk().getTracer(RUM_TRACER_NAME);
Tracer tracer =
spanName ->
delegateTracer
.spanBuilder(spanName)
.setAttribute(COMPONENT_KEY, COMPONENT_UI);
RumFragmentLifecycleCallbacks fragmentLifecycle =
new RumFragmentLifecycleCallbacks(tracer, visibleScreenTracker);
if (Build.VERSION.SDK_INT < 29) {
Expand Down Expand Up @@ -280,7 +295,19 @@ private void installActivityLifecycleEventsInstrumentation(
@NonNull
private Application.ActivityLifecycleCallbacks buildActivityEventsCallback(
VisibleScreenTracker visibleScreenTracker, InstrumentedApplication instrumentedApp) {
Tracer tracer = instrumentedApp.getOpenTelemetrySdk().getTracer(RUM_TRACER_NAME);
Tracer delegateTracer = instrumentedApp.getOpenTelemetrySdk().getTracer(RUM_TRACER_NAME);
Tracer tracer =
spanName -> {
// override the component to be appstart when appstart
String component =
spanName.equals(APP_START_SPAN_NAME)
? COMPONENT_APPSTART
: COMPONENT_UI;
return delegateTracer
.spanBuilder(spanName)
.setAttribute(COMPONENT_KEY, component);
};

ActivityTracerCache tracers =
new ActivityTracerCache(tracer, visibleScreenTracker, startupTimer);
if (Build.VERSION.SDK_INT < 29) {
Expand Down Expand Up @@ -333,7 +360,8 @@ private void installAnrDetector(OpenTelemetryRumBuilder otelRumBuilder, Looper m
.installOn(instrumentedApplication);

initializationEvents.add(
new InitializationEvent("anrMonitorInitialized", timingClock.now()));
new InitializationEvent(
"anrMonitorInitialized", startupTimer.clockNow()));
});
}

Expand All @@ -345,7 +373,7 @@ private void installNetworkMonitor(
.installOn(instrumentedApplication);
initializationEvents.add(
new InitializationEvent(
"networkMonitorInitialized", timingClock.now()));
"networkMonitorInitialized", startupTimer.clockNow()));
});
}

Expand All @@ -359,7 +387,7 @@ private void installSlowRenderingDetector(OpenTelemetryRumBuilder otelRumBuilder
.installOn(instrumentedApplication);
initializationEvents.add(
new InitializationEvent(
"slowRenderingDetectorInitialized", timingClock.now()));
"slowRenderingDetectorInitialized", startupTimer.clockNow()));
});
}

Expand All @@ -378,18 +406,27 @@ private void installCrashReporter(OpenTelemetryRumBuilder otelRumBuilder) {

initializationEvents.add(
new InitializationEvent(
"crashReportingInitialized", timingClock.now()));
"crashReportingInitialized", startupTimer.clockNow()));
});
}

private void recordInitializationSpans(
long startTimeNanos, List<InitializationEvent> initializationEvents, Tracer tracer) {
long startTimeNanos,
List<InitializationEvent> initializationEvents,
Tracer delegateTracer) {

Tracer tracer =
spanName ->
delegateTracer
.spanBuilder(spanName)
.setAttribute(COMPONENT_KEY, COMPONENT_APPSTART);

Span overallAppStart = startupTimer.start(tracer);
Span span =
tracer.spanBuilder("SplunkRum.initialize")
.setParent(Context.current().with(overallAppStart))
.setStartTimestamp(startTimeNanos, TimeUnit.NANOSECONDS)
.setAttribute(SplunkRum.COMPONENT_KEY, SplunkRum.COMPONENT_APPSTART)
.setAttribute(COMPONENT_KEY, COMPONENT_APPSTART)
.startSpan();

String configSettings =
Expand All @@ -413,7 +450,7 @@ private void recordInitializationSpans(
for (RumInitializer.InitializationEvent initializationEvent : initializationEvents) {
span.addEvent(initializationEvent.name, initializationEvent.time, TimeUnit.NANOSECONDS);
}
long spanEndTime = timingClock.now();
long spanEndTime = startupTimer.clockNow();
// we only want to create SplunkRum.initialize span when there is a AppStart span so we
// register a callback that is called right before AppStart span is ended
startupTimer.setCompletionCallback(() -> span.end(spanEndTime, TimeUnit.NANOSECONDS));
Expand All @@ -426,7 +463,7 @@ SpanExporter buildFilteringExporter(CurrentNetworkProvider currentNetworkProvide
new SplunkSpanDataModifier(exporter, builder.reactNativeSupportEnabled);
SpanExporter filteredExporter = builder.decorateWithSpanFilter(splunkTranslatedExporter);
initializationEvents.add(
new InitializationEvent("zipkin exporter initialized", timingClock.now()));
new InitializationEvent("zipkin exporter initialized", startupTimer.clockNow()));
return filteredExporter;
}

Expand All @@ -436,7 +473,7 @@ private SpanExporter buildExporter(CurrentNetworkProvider currentNetworkProvider
// we'll do our best to hang on to the spans with the wrapping BufferingExporter.
ZipkinSpanExporter.baseLogger.setLevel(Level.SEVERE);
initializationEvents.add(
new InitializationEvent("logger setup complete", timingClock.now()));
new InitializationEvent("logger setup complete", startupTimer.clockNow()));
}

if (builder.diskBufferingEnabled) {
Expand Down Expand Up @@ -477,7 +514,7 @@ private SpanExporter buildMemoryBufferingThrottledExporter(
SpanExporter zipkinSpanExporter = getCoreSpanExporter(endpoint);
return ThrottlingExporter.newBuilder(
new MemoryBufferingExporter(currentNetworkProvider, zipkinSpanExporter))
.categorizeByAttribute(SplunkRum.COMPONENT_KEY)
.categorizeByAttribute(COMPONENT_KEY)
.maxSpansInWindow(100)
.windowSize(Duration.ofSeconds(30))
.build();
Expand Down Expand Up @@ -513,28 +550,6 @@ private InitializationEvent(String name, long time) {
}
}

// copied from otel-java
static final class AnchoredClock {
private final Clock clock;
private final long epochNanos;
private final long nanoTime;

private AnchoredClock(Clock clock, long epochNanos, long nanoTime) {
this.clock = clock;
this.epochNanos = epochNanos;
this.nanoTime = nanoTime;
}

public static AnchoredClock create(Clock clock) {
return new AnchoredClock(clock, clock.now(), clock.nanoTime());
}

long now() {
long deltaNanos = this.clock.nanoTime() - this.nanoTime;
return this.epochNanos + deltaNanos;
}
}

private static class LazyInitSpanExporter implements SpanExporter {
@Nullable private volatile SpanExporter delegate;
private final Supplier<SpanExporter> s;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.splunk.rum;

import static com.splunk.rum.SplunkRum.COMPONENT_KEY;
import static com.splunk.rum.SplunkRum.LINK_SPAN_ID_KEY;
import static com.splunk.rum.SplunkRum.LINK_TRACE_ID_KEY;

Expand All @@ -35,7 +36,7 @@ public RumResponseAttributesExtractor(ServerTimingHeaderParser serverTimingHeade

@Override
public void onStart(AttributesBuilder attributes, Context parentContext, Request request) {
attributes.put(SplunkRum.COMPONENT_KEY, "http");
attributes.put(COMPONENT_KEY, "http");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@

package com.splunk.rum;

import static io.opentelemetry.rum.internal.RumConstants.SCREEN_NAME_KEY;

import io.opentelemetry.context.Context;
import io.opentelemetry.rum.internal.instrumentation.activity.VisibleScreenTracker;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.sdk.trace.SpanProcessor;
Expand All @@ -32,7 +35,7 @@ class ScreenAttributesAppender implements SpanProcessor {
@Override
public void onStart(Context parentContext, ReadWriteSpan span) {
String currentScreen = visibleScreenTracker.getCurrentlyVisibleScreen();
span.setAttribute(SplunkRum.SCREEN_NAME_KEY, currentScreen);
span.setAttribute(SCREEN_NAME_KEY, currentScreen);
}

@Override
Expand Down
Loading

0 comments on commit 64a9e4a

Please sign in to comment.