From 64a9e4a41d880ed98cbf78c659dcd5b78adc39cd Mon Sep 17 00:00:00 2001 From: jason plumb <75337021+breedx-splk@users.noreply.github.com> Date: Wed, 22 Feb 2023 08:44:49 -0800 Subject: [PATCH] Refactor ActivityCallbacks (#478) * 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 --- .../VolleyResponseAttributesExtractor.java | 3 +- ...VolleyResponseAttributesExtractorTest.java | 5 +- .../splunk/rum/CrashComponentExtractor.java | 4 +- .../java/com/splunk/rum/RumInitializer.java | 107 ++++++------ .../rum/RumResponseAttributesExtractor.java | 3 +- .../splunk/rum/ScreenAttributesAppender.java | 5 +- .../main/java/com/splunk/rum/SplunkRum.java | 7 +- .../rum/internal/RumConstants.java | 36 +++++ .../activity}/ActivityCallbacks.java | 6 +- .../activity}/ActivityTracer.java | 107 +++++++++--- .../activity}/ActivityTracerCache.java | 25 +-- .../activity}/Pre29ActivityCallbacks.java | 6 +- .../Pre29VisibleScreenLifecycleBinding.java | 8 +- .../VisibleScreenLifecycleBinding.java | 6 +- .../activity}/VisibleScreenTracker.java | 16 +- .../fragment}/FragmentTracer.java | 55 ++++++- .../RumFragmentLifecycleCallbacks.java | 16 +- .../network/CurrentNetworkProvider.java | 10 +- .../slowrendering/SlowRenderListener.java | 8 +- .../slowrendering/SlowRenderingDetector.java | 6 +- .../SlowRenderingDetectorBuilder.java | 4 +- .../startup}/AppStartupTimer.java | 45 ++++-- .../rum/internal/util}/ActiveSpan.java | 26 +-- .../rum/internal/util/AnchoredClock.java | 41 +++++ .../rum/CrashComponentExtractorTest.java | 5 +- .../com/splunk/rum/RumInitializerTest.java | 6 +- .../RumResponseAttributesExtractorTest.java | 11 +- .../rum/ScreenAttributesAppenderTest.java | 9 +- .../java/com/splunk/rum/SplunkRumTest.java | 3 +- .../splunk/rum/ThrottlingExporterTest.java | 7 +- .../ActivityCallbackTestHarness.java | 2 +- .../activity}/ActivityCallbacksTest.java | 66 +++----- .../activity}/ActivityTracerCacheTest.java | 2 +- .../activity}/ActivityTracerTest.java | 153 +++++++++--------- .../Pre29ActivityCallbackTestHarness.java | 2 +- .../Pre29ActivityLifecycleCallbacksTest.java | 64 +++----- ...re29VisibleScreenLifecycleBindingTest.java | 2 +- .../VisibleScreenLifecycleBindingTest.java | 2 +- .../activity}/VisibleScreenTrackerTest.java | 2 +- .../FragmentCallbackTestHarness.java | 2 +- .../fragment}/FragmentTracerTest.java | 49 ++++-- .../RumFragmentLifecycleCallbacksTest.java | 67 +++----- .../startup}/AppStartupTimerTest.java | 8 +- 43 files changed, 607 insertions(+), 410 deletions(-) create mode 100644 splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/RumConstants.java rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/ActivityCallbacks.java (95%) rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/ActivityTracer.java (59%) rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/ActivityTracerCache.java (75%) rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/Pre29ActivityCallbacks.java (91%) rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/Pre29VisibleScreenLifecycleBinding.java (82%) rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/VisibleScreenLifecycleBinding.java (84%) rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/VisibleScreenTracker.java (89%) rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/fragment}/FragmentTracer.java (60%) rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/fragment}/RumFragmentLifecycleCallbacks.java (88%) rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/startup}/AppStartupTimer.java (80%) rename splunk-otel-android/src/main/java/{com/splunk/rum => io/opentelemetry/rum/internal/util}/ActiveSpan.java (70%) create mode 100644 splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/util/AnchoredClock.java rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/ActivityCallbackTestHarness.java (98%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/ActivityCallbacksTest.java (81%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/ActivityTracerCacheTest.java (98%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/ActivityTracerTest.java (57%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/Pre29ActivityCallbackTestHarness.java (97%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/Pre29ActivityLifecycleCallbacksTest.java (79%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/Pre29VisibleScreenLifecycleBindingTest.java (96%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/VisibleScreenLifecycleBindingTest.java (96%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/activity}/VisibleScreenTrackerTest.java (98%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/fragment}/FragmentCallbackTestHarness.java (98%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/fragment}/FragmentTracerTest.java (63%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/fragment}/RumFragmentLifecycleCallbacksTest.java (78%) rename splunk-otel-android/src/test/java/{com/splunk/rum => io/opentelemetry/rum/internal/instrumentation/startup}/AppStartupTimerTest.java (90%) diff --git a/splunk-otel-android-volley/src/main/java/com/splunk/rum/VolleyResponseAttributesExtractor.java b/splunk-otel-android-volley/src/main/java/com/splunk/rum/VolleyResponseAttributesExtractor.java index 894b022da..5266bc261 100644 --- a/splunk-otel-android-volley/src/main/java/com/splunk/rum/VolleyResponseAttributesExtractor.java +++ b/splunk-otel-android-volley/src/main/java/com/splunk/rum/VolleyResponseAttributesExtractor.java @@ -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; @@ -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 diff --git a/splunk-otel-android-volley/src/test/java/com/splunk/rum/VolleyResponseAttributesExtractorTest.java b/splunk-otel-android-volley/src/test/java/com/splunk/rum/VolleyResponseAttributesExtractorTest.java index 8669ad308..71a41a6d3 100644 --- a/splunk-otel-android-volley/src/test/java/com/splunk/rum/VolleyResponseAttributesExtractorTest.java +++ b/splunk-otel-android-volley/src/test/java/com/splunk/rum/VolleyResponseAttributesExtractorTest.java @@ -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; @@ -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)); @@ -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)); } diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/CrashComponentExtractor.java b/splunk-otel-android/src/main/java/com/splunk/rum/CrashComponentExtractor.java index f51c69bfa..baf5d9cca 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/CrashComponentExtractor.java +++ b/splunk-otel-android/src/main/java/com/splunk/rum/CrashComponentExtractor.java @@ -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; @@ -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 diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/RumInitializer.java b/splunk-otel-android/src/main/java/com/splunk/rum/RumInitializer.java index 35ebae9ae..862e0b733 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/RumInitializer.java +++ b/splunk-otel-android/src/main/java/com/splunk/rum/RumInitializer.java @@ -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; @@ -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; @@ -85,14 +95,12 @@ class RumInitializer { private final Application application; private final AppStartupTimer startupTimer; private final List 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( @@ -100,17 +108,18 @@ SplunkRum initialize( 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); @@ -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) @@ -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; }); @@ -206,7 +215,8 @@ private void installLifecycleInstrumentations( instrumentedApp -> { initializationEvents.add( new InitializationEvent( - "activityLifecycleCallbacksInitialized", timingClock.now())); + "activityLifecycleCallbacksInitialized", + startupTimer.clockNow())); }); } @@ -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) { @@ -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) { @@ -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())); }); } @@ -345,7 +373,7 @@ private void installNetworkMonitor( .installOn(instrumentedApplication); initializationEvents.add( new InitializationEvent( - "networkMonitorInitialized", timingClock.now())); + "networkMonitorInitialized", startupTimer.clockNow())); }); } @@ -359,7 +387,7 @@ private void installSlowRenderingDetector(OpenTelemetryRumBuilder otelRumBuilder .installOn(instrumentedApplication); initializationEvents.add( new InitializationEvent( - "slowRenderingDetectorInitialized", timingClock.now())); + "slowRenderingDetectorInitialized", startupTimer.clockNow())); }); } @@ -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 initializationEvents, Tracer tracer) { + long startTimeNanos, + List 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 = @@ -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)); @@ -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; } @@ -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) { @@ -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(); @@ -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 s; diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/RumResponseAttributesExtractor.java b/splunk-otel-android/src/main/java/com/splunk/rum/RumResponseAttributesExtractor.java index 76da987e7..7f8cdef4a 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/RumResponseAttributesExtractor.java +++ b/splunk-otel-android/src/main/java/com/splunk/rum/RumResponseAttributesExtractor.java @@ -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; @@ -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 diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/ScreenAttributesAppender.java b/splunk-otel-android/src/main/java/com/splunk/rum/ScreenAttributesAppender.java index ea2b0e95d..57d831a18 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/ScreenAttributesAppender.java +++ b/splunk-otel-android/src/main/java/com/splunk/rum/ScreenAttributesAppender.java @@ -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; @@ -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 diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/SplunkRum.java b/splunk-otel-android/src/main/java/com/splunk/rum/SplunkRum.java index b7365db7b..fd8cac532 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/SplunkRum.java +++ b/splunk-otel-android/src/main/java/com/splunk/rum/SplunkRum.java @@ -37,6 +37,7 @@ import io.opentelemetry.rum.internal.GlobalAttributesSpanAppender; import io.opentelemetry.rum.internal.OpenTelemetryRum; import io.opentelemetry.rum.internal.instrumentation.network.CurrentNetworkProvider; +import io.opentelemetry.rum.internal.instrumentation.startup.AppStartupTimer; import io.opentelemetry.sdk.OpenTelemetrySdk; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -51,13 +52,9 @@ public class SplunkRum { private static final AppStartupTimer startupTimer = new AppStartupTimer(); static final AttributeKey COMPONENT_KEY = AttributeKey.stringKey("component"); - static final AttributeKey SCREEN_NAME_KEY = AttributeKey.stringKey("screen.name"); - static final AttributeKey LAST_SCREEN_NAME_KEY = - AttributeKey.stringKey("last.screen.name"); static final AttributeKey ERROR_TYPE_KEY = stringKey("error.type"); static final AttributeKey ERROR_MESSAGE_KEY = stringKey("error.message"); static final AttributeKey WORKFLOW_NAME_KEY = stringKey("workflow.name"); - static final AttributeKey START_TYPE_KEY = stringKey("start.type"); static final AttributeKey LOCATION_LATITUDE_KEY = doubleKey("location.lat"); static final AttributeKey LOCATION_LONGITUDE_KEY = doubleKey("location.long"); @@ -66,9 +63,9 @@ public class SplunkRum { static final AttributeKey BATTERY_PERCENT_KEY = doubleKey("battery.percent"); static final String COMPONENT_APPSTART = "appstart"; + static final String COMPONENT_UI = "ui"; static final String COMPONENT_CRASH = "crash"; static final String COMPONENT_ERROR = "error"; - static final String COMPONENT_UI = "ui"; static final String LOG_TAG = "SplunkRum"; static final String RUM_TRACER_NAME = "SplunkRum"; diff --git a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/RumConstants.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/RumConstants.java new file mode 100644 index 000000000..caefa01ef --- /dev/null +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/RumConstants.java @@ -0,0 +1,36 @@ +/* + * Copyright Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.rum.internal; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; + +import io.opentelemetry.api.common.AttributeKey; + +public class RumConstants { + + public static final String OTEL_RUM_LOG_TAG = "OpenTelemetryRum"; + + public static final AttributeKey LAST_SCREEN_NAME_KEY = + AttributeKey.stringKey("last.screen.name"); + public static final AttributeKey SCREEN_NAME_KEY = + AttributeKey.stringKey("screen.name"); + public static final AttributeKey START_TYPE_KEY = stringKey("start.type"); + + public static final String APP_START_SPAN_NAME = "AppStart"; + + private RumConstants() {} +} diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/ActivityCallbacks.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityCallbacks.java similarity index 95% rename from splunk-otel-android/src/main/java/com/splunk/rum/ActivityCallbacks.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityCallbacks.java index 6c0ec11fc..55b1ed25b 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/ActivityCallbacks.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityCallbacks.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import android.app.Activity; import android.os.Bundle; @@ -22,11 +22,11 @@ import androidx.annotation.Nullable; import io.opentelemetry.rum.internal.DefaultingActivityLifecycleCallbacks; -class ActivityCallbacks implements DefaultingActivityLifecycleCallbacks { +public class ActivityCallbacks implements DefaultingActivityLifecycleCallbacks { private final ActivityTracerCache tracers; - ActivityCallbacks(ActivityTracerCache tracers) { + public ActivityCallbacks(ActivityTracerCache tracers) { this.tracers = tracers; } diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/ActivityTracer.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracer.java similarity index 59% rename from splunk-otel-android/src/main/java/com/splunk/rum/ActivityTracer.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracer.java index b2979e511..f552c76e5 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/ActivityTracer.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracer.java @@ -14,21 +14,27 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; + +import static io.opentelemetry.rum.internal.RumConstants.APP_START_SPAN_NAME; +import static io.opentelemetry.rum.internal.RumConstants.SCREEN_NAME_KEY; +import static io.opentelemetry.rum.internal.RumConstants.START_TYPE_KEY; import android.app.Activity; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.splunk.rum.RumScreenName; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Context; +import io.opentelemetry.rum.internal.instrumentation.startup.AppStartupTimer; +import io.opentelemetry.rum.internal.util.ActiveSpan; import java.util.concurrent.atomic.AtomicReference; -class ActivityTracer { +public class ActivityTracer { static final AttributeKey ACTIVITY_NAME_KEY = AttributeKey.stringKey("activityName"); - static final String APP_START_SPAN_NAME = "AppStart"; private final AtomicReference initialAppActivity; private final Tracer tracer; @@ -37,19 +43,14 @@ class ActivityTracer { private final AppStartupTimer appStartupTimer; private final ActiveSpan activeSpan; - ActivityTracer( - Activity activity, - AtomicReference initialAppActivity, - Tracer tracer, - VisibleScreenTracker visibleScreenTracker, - AppStartupTimer appStartupTimer) { - this.initialAppActivity = initialAppActivity; - this.tracer = tracer; - this.activityName = activity.getClass().getSimpleName(); - RumScreenName rumScreenName = activity.getClass().getAnnotation(RumScreenName.class); + private ActivityTracer(Builder builder) { + this.initialAppActivity = builder.initialAppActivity; + this.tracer = builder.tracer; + this.activityName = builder.getActivityName(); + RumScreenName rumScreenName = builder.getRumScreenName(); this.screenName = rumScreenName == null ? activityName : rumScreenName.value(); - this.appStartupTimer = appStartupTimer; - this.activeSpan = new ActiveSpan(visibleScreenTracker); + this.appStartupTimer = builder.appStartupTimer; + this.activeSpan = builder.activeSpan; } ActivityTracer startSpanIfNoneInProgress(String spanName) { @@ -101,9 +102,7 @@ private Span makeRestartSpan(boolean multiActivityApp) { private Span createAppStartSpan(String startType) { Span span = createSpan(APP_START_SPAN_NAME); - span.setAttribute(SplunkRum.START_TYPE_KEY, startType); - // override the component to be appstart - span.setAttribute(SplunkRum.COMPONENT_KEY, SplunkRum.COMPONENT_APPSTART); + span.setAttribute(START_TYPE_KEY, startType); return span; } @@ -113,40 +112,96 @@ private Span createSpan(String spanName) { private Span createSpanWithParent(String spanName, @Nullable Span parentSpan) { final SpanBuilder spanBuilder = - tracer.spanBuilder(spanName) - .setAttribute(ACTIVITY_NAME_KEY, activityName) - .setAttribute(SplunkRum.COMPONENT_KEY, SplunkRum.COMPONENT_UI); + tracer.spanBuilder(spanName).setAttribute(ACTIVITY_NAME_KEY, activityName); if (parentSpan != null) { spanBuilder.setParent(parentSpan.storeInContext(Context.current())); } Span span = spanBuilder.startSpan(); // do this after the span is started, so we can override the default screen.name set by the // RumAttributeAppender. - span.setAttribute(SplunkRum.SCREEN_NAME_KEY, screenName); + span.setAttribute(SCREEN_NAME_KEY, screenName); return span; } - void endSpanForActivityResumed() { + public void endSpanForActivityResumed() { if (initialAppActivity.get() == null) { initialAppActivity.set(activityName); } endActiveSpan(); } - void endActiveSpan() { + public void endActiveSpan() { // If we happen to be in app startup, make sure this ends it. It's harmless if we're already // out of the startup phase. appStartupTimer.end(); activeSpan.endActiveSpan(); } - ActivityTracer addPreviousScreenAttribute() { + public ActivityTracer addPreviousScreenAttribute() { activeSpan.addPreviousScreenAttribute(activityName); return this; } - ActivityTracer addEvent(String eventName) { + public ActivityTracer addEvent(String eventName) { activeSpan.addEvent(eventName); return this; } + + public static Builder builder(Activity activity) { + return new Builder(activity); + } + + static class Builder { + private final Activity activity; + private AtomicReference initialAppActivity = new AtomicReference<>(); + private Tracer tracer; + private AppStartupTimer appStartupTimer; + private ActiveSpan activeSpan; + + public Builder(Activity activity) { + this.activity = activity; + } + + public Builder setVisibleScreenTracker(VisibleScreenTracker visibleScreenTracker) { + this.activeSpan = new ActiveSpan(visibleScreenTracker::getPreviouslyVisibleScreen); + return this; + } + + public Builder setInitialAppActivity(String activityName) { + initialAppActivity.set(activityName); + return this; + } + + public Builder setInitialAppActivity(AtomicReference initialAppActivity) { + this.initialAppActivity = initialAppActivity; + return this; + } + + public Builder setTracer(Tracer tracer) { + this.tracer = tracer; + return this; + } + + public Builder setAppStartupTimer(AppStartupTimer appStartupTimer) { + this.appStartupTimer = appStartupTimer; + return this; + } + + public Builder setActiveSpan(ActiveSpan activeSpan) { + this.activeSpan = activeSpan; + return this; + } + + private String getActivityName() { + return activity.getClass().getSimpleName(); + } + + private RumScreenName getRumScreenName() { + return activity.getClass().getAnnotation(RumScreenName.class); + } + + public ActivityTracer build() { + return new ActivityTracer(this); + } + } } diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/ActivityTracerCache.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracerCache.java similarity index 75% rename from splunk-otel-android/src/main/java/com/splunk/rum/ActivityTracerCache.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracerCache.java index 6bb9c5900..2564b7301 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/ActivityTracerCache.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracerCache.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import android.app.Activity; import androidx.annotation.VisibleForTesting; import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.rum.internal.instrumentation.startup.AppStartupTimer; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; @@ -28,7 +29,7 @@ * Encapsulates the fact that we have an ActivityTracer instance per Activity class, and provides * convenience methods for adding events and starting spans. */ -class ActivityTracerCache { +public class ActivityTracerCache { private final Map tracersByActivityClassName = new HashMap<>(); @@ -49,12 +50,12 @@ public ActivityTracerCache( AppStartupTimer startupTimer) { this( activity -> - new ActivityTracer( - activity, - initialAppActivity, - tracer, - visibleScreenTracker, - startupTimer)); + ActivityTracer.builder(activity) + .setInitialAppActivity(initialAppActivity) + .setTracer(tracer) + .setAppStartupTimer(startupTimer) + .setVisibleScreenTracker(visibleScreenTracker) + .build()); } @VisibleForTesting @@ -62,20 +63,20 @@ public ActivityTracerCache( this.tracerFactory = tracerFactory; } - ActivityTracer addEvent(Activity activity, String eventName) { + public ActivityTracer addEvent(Activity activity, String eventName) { return getTracer(activity).addEvent(eventName); } - ActivityTracer startSpanIfNoneInProgress(Activity activity, String spanName) { + public ActivityTracer startSpanIfNoneInProgress(Activity activity, String spanName) { return getTracer(activity).startSpanIfNoneInProgress(spanName); } - ActivityTracer initiateRestartSpanIfNecessary(Activity activity) { + public ActivityTracer initiateRestartSpanIfNecessary(Activity activity) { boolean isMultiActivityApp = tracersByActivityClassName.size() > 1; return getTracer(activity).initiateRestartSpanIfNecessary(isMultiActivityApp); } - ActivityTracer startActivityCreation(Activity activity) { + public ActivityTracer startActivityCreation(Activity activity) { return getTracer(activity).startActivityCreation(); } diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/Pre29ActivityCallbacks.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29ActivityCallbacks.java similarity index 91% rename from splunk-otel-android/src/main/java/com/splunk/rum/Pre29ActivityCallbacks.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29ActivityCallbacks.java index 6d7ab58c1..60f033bc1 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/Pre29ActivityCallbacks.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29ActivityCallbacks.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import android.app.Activity; import android.os.Bundle; @@ -22,10 +22,10 @@ import androidx.annotation.Nullable; import io.opentelemetry.rum.internal.DefaultingActivityLifecycleCallbacks; -class Pre29ActivityCallbacks implements DefaultingActivityLifecycleCallbacks { +public class Pre29ActivityCallbacks implements DefaultingActivityLifecycleCallbacks { private final ActivityTracerCache tracers; - Pre29ActivityCallbacks(ActivityTracerCache tracers) { + public Pre29ActivityCallbacks(ActivityTracerCache tracers) { this.tracers = tracers; } diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/Pre29VisibleScreenLifecycleBinding.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29VisibleScreenLifecycleBinding.java similarity index 82% rename from splunk-otel-android/src/main/java/com/splunk/rum/Pre29VisibleScreenLifecycleBinding.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29VisibleScreenLifecycleBinding.java index b8ad95f34..4b8c0c4c4 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/Pre29VisibleScreenLifecycleBinding.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29VisibleScreenLifecycleBinding.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import android.app.Activity; import androidx.annotation.NonNull; @@ -23,13 +23,13 @@ /** * An ActivityLifecycleCallbacks that is responsible for telling the VisibleScreenTracker when an * activity has been resumed and when an activity has been paused. It's just a glue class designed - * for API level < 29. + * for API level before 29. */ -class Pre29VisibleScreenLifecycleBinding implements DefaultingActivityLifecycleCallbacks { +public class Pre29VisibleScreenLifecycleBinding implements DefaultingActivityLifecycleCallbacks { private final VisibleScreenTracker visibleScreenTracker; - Pre29VisibleScreenLifecycleBinding(VisibleScreenTracker visibleScreenTracker) { + public Pre29VisibleScreenLifecycleBinding(VisibleScreenTracker visibleScreenTracker) { this.visibleScreenTracker = visibleScreenTracker; } diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/VisibleScreenLifecycleBinding.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenLifecycleBinding.java similarity index 84% rename from splunk-otel-android/src/main/java/com/splunk/rum/VisibleScreenLifecycleBinding.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenLifecycleBinding.java index 73504d1eb..bbfa89301 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/VisibleScreenLifecycleBinding.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenLifecycleBinding.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import android.app.Activity; import androidx.annotation.NonNull; @@ -24,11 +24,11 @@ * An ActivityLifecycleCallbacks that is responsible for telling the VisibleScreenTracker when an * activity has been resumed and when an activity has been paused. It's just a glue class. */ -class VisibleScreenLifecycleBinding implements DefaultingActivityLifecycleCallbacks { +public class VisibleScreenLifecycleBinding implements DefaultingActivityLifecycleCallbacks { private final VisibleScreenTracker visibleScreenTracker; - VisibleScreenLifecycleBinding(VisibleScreenTracker visibleScreenTracker) { + public VisibleScreenLifecycleBinding(VisibleScreenTracker visibleScreenTracker) { this.visibleScreenTracker = visibleScreenTracker; } diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/VisibleScreenTracker.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenTracker.java similarity index 89% rename from splunk-otel-android/src/main/java/com/splunk/rum/VisibleScreenTracker.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenTracker.java index b1b0534ab..87fa24d30 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/VisibleScreenTracker.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenTracker.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import android.app.Activity; import androidx.annotation.Nullable; @@ -35,14 +35,14 @@ *

We have to treat DialogFragments slightly differently since they don't replace the launching * screen, and the launching screen never leaves visibility. */ -class VisibleScreenTracker { +public class VisibleScreenTracker { private final AtomicReference lastResumedActivity = new AtomicReference<>(); private final AtomicReference previouslyLastResumedActivity = new AtomicReference<>(); private final AtomicReference lastResumedFragment = new AtomicReference<>(); private final AtomicReference previouslyLastResumedFragment = new AtomicReference<>(); @Nullable - String getPreviouslyVisibleScreen() { + public String getPreviouslyVisibleScreen() { String previouslyLastFragment = previouslyLastResumedFragment.get(); if (previouslyLastFragment != null) { return previouslyLastFragment; @@ -50,7 +50,7 @@ String getPreviouslyVisibleScreen() { return previouslyLastResumedActivity.get(); } - String getCurrentlyVisibleScreen() { + public String getCurrentlyVisibleScreen() { String lastFragment = lastResumedFragment.get(); if (lastFragment != null) { return lastFragment; @@ -62,16 +62,16 @@ String getCurrentlyVisibleScreen() { return "unknown"; } - void activityResumed(Activity activity) { + public void activityResumed(Activity activity) { lastResumedActivity.set(activity.getClass().getSimpleName()); } - void activityPaused(Activity activity) { + public void activityPaused(Activity activity) { previouslyLastResumedActivity.set(activity.getClass().getSimpleName()); lastResumedActivity.compareAndSet(activity.getClass().getSimpleName(), null); } - void fragmentResumed(Fragment fragment) { + public void fragmentResumed(Fragment fragment) { // skip the NavHostFragment since it's never really "visible" by itself. if (fragment instanceof NavHostFragment) { return; @@ -83,7 +83,7 @@ void fragmentResumed(Fragment fragment) { lastResumedFragment.set(fragment.getClass().getSimpleName()); } - void fragmentPaused(Fragment fragment) { + public void fragmentPaused(Fragment fragment) { // skip the NavHostFragment since it's never really "visible" by itself. if (fragment instanceof NavHostFragment) { return; diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/FragmentTracer.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/fragment/FragmentTracer.java similarity index 60% rename from splunk-otel-android/src/main/java/com/splunk/rum/FragmentTracer.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/fragment/FragmentTracer.java index a446af527..3cd7e17f1 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/FragmentTracer.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/fragment/FragmentTracer.java @@ -14,12 +14,16 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.fragment; + +import static io.opentelemetry.rum.internal.RumConstants.SCREEN_NAME_KEY; import androidx.fragment.app.Fragment; +import com.splunk.rum.RumScreenName; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.rum.internal.util.ActiveSpan; class FragmentTracer { static final AttributeKey FRAGMENT_NAME_KEY = AttributeKey.stringKey("fragmentName"); @@ -29,12 +33,12 @@ class FragmentTracer { private final Tracer tracer; private final ActiveSpan activeSpan; - FragmentTracer(Fragment fragment, Tracer tracer, VisibleScreenTracker visibleScreenTracker) { - this.tracer = tracer; - this.fragmentName = fragment.getClass().getSimpleName(); - RumScreenName rumScreenName = fragment.getClass().getAnnotation(RumScreenName.class); + private FragmentTracer(Builder builder) { + this.tracer = builder.tracer; + this.fragmentName = builder.getFragmentName(); + RumScreenName rumScreenName = builder.getRumScreenName(); this.screenName = rumScreenName == null ? fragmentName : rumScreenName.value(); - this.activeSpan = new ActiveSpan(visibleScreenTracker); + this.activeSpan = builder.activeSpan; } FragmentTracer startSpanIfNoneInProgress(String action) { @@ -54,11 +58,10 @@ private Span createSpan(String spanName) { Span span = tracer.spanBuilder(spanName) .setAttribute(FRAGMENT_NAME_KEY, fragmentName) - .setAttribute(SplunkRum.COMPONENT_KEY, SplunkRum.COMPONENT_UI) .startSpan(); // do this after the span is started, so we can override the default screen.name set by the // RumAttributeAppender. - span.setAttribute(SplunkRum.SCREEN_NAME_KEY, screenName); + span.setAttribute(SCREEN_NAME_KEY, screenName); return span; } @@ -75,4 +78,40 @@ FragmentTracer addEvent(String eventName) { activeSpan.addEvent(eventName); return this; } + + static Builder builder(Fragment fragment) { + return new Builder(fragment); + } + + static class Builder { + private final Fragment fragment; + private Tracer tracer; + private ActiveSpan activeSpan; + + public Builder(Fragment fragment) { + this.fragment = fragment; + } + + Builder setTracer(Tracer tracer) { + this.tracer = tracer; + return this; + } + + Builder setActiveSpan(ActiveSpan activeSpan) { + this.activeSpan = activeSpan; + return this; + } + + public String getFragmentName() { + return fragment.getClass().getSimpleName(); + } + + public RumScreenName getRumScreenName() { + return fragment.getClass().getAnnotation(RumScreenName.class); + } + + FragmentTracer build() { + return new FragmentTracer(this); + } + } } diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/RumFragmentLifecycleCallbacks.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/fragment/RumFragmentLifecycleCallbacks.java similarity index 88% rename from splunk-otel-android/src/main/java/com/splunk/rum/RumFragmentLifecycleCallbacks.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/fragment/RumFragmentLifecycleCallbacks.java index d326ee28b..f5fb5d871 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/RumFragmentLifecycleCallbacks.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/fragment/RumFragmentLifecycleCallbacks.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.fragment; import android.content.Context; import android.os.Bundle; @@ -24,16 +24,18 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.rum.internal.instrumentation.activity.VisibleScreenTracker; +import io.opentelemetry.rum.internal.util.ActiveSpan; import java.util.HashMap; import java.util.Map; -class RumFragmentLifecycleCallbacks extends FragmentManager.FragmentLifecycleCallbacks { +public class RumFragmentLifecycleCallbacks extends FragmentManager.FragmentLifecycleCallbacks { private final Map tracersByFragmentClassName = new HashMap<>(); private final Tracer tracer; private final VisibleScreenTracker visibleScreenTracker; - RumFragmentLifecycleCallbacks(Tracer tracer, VisibleScreenTracker visibleScreenTracker) { + public RumFragmentLifecycleCallbacks(Tracer tracer, VisibleScreenTracker visibleScreenTracker) { this.tracer = tracer; this.visibleScreenTracker = visibleScreenTracker; } @@ -151,7 +153,13 @@ private FragmentTracer getTracer(Fragment fragment) { FragmentTracer activityTracer = tracersByFragmentClassName.get(fragment.getClass().getName()); if (activityTracer == null) { - activityTracer = new FragmentTracer(fragment, tracer, visibleScreenTracker); + activityTracer = + FragmentTracer.builder(fragment) + .setTracer(tracer) + .setActiveSpan( + new ActiveSpan( + visibleScreenTracker::getPreviouslyVisibleScreen)) + .build(); tracersByFragmentClassName.put(fragment.getClass().getName(), activityTracer); } return activityTracer; diff --git a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/network/CurrentNetworkProvider.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/network/CurrentNetworkProvider.java index ac3db2436..1c2675d0b 100644 --- a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/network/CurrentNetworkProvider.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/network/CurrentNetworkProvider.java @@ -16,6 +16,8 @@ package io.opentelemetry.rum.internal.instrumentation.network; +import static io.opentelemetry.rum.internal.RumConstants.OTEL_RUM_LOG_TAG; + import android.app.Application; import android.content.Context; import android.net.ConnectivityManager; @@ -38,8 +40,6 @@ */ public final class CurrentNetworkProvider { - private static final String OPEN_TELEMETRY_RUM_LOG_TAG = "OpenTelemetryRum"; - static final CurrentNetwork NO_NETWORK = CurrentNetwork.builder(NetworkState.NO_NETWORK_AVAILABLE).build(); static final CurrentNetwork UNKNOWN_NETWORK = @@ -79,7 +79,7 @@ void startMonitoring( } catch (Exception e) { // if this fails, we'll go without network change events. Log.w( - OPEN_TELEMETRY_RUM_LOG_TAG, + OTEL_RUM_LOG_TAG, "Failed to register network callbacks. Automatic network monitoring is disabled.", e); } @@ -138,7 +138,7 @@ private final class ConnectionMonitor extends ConnectivityManager.NetworkCallbac @Override public void onAvailable(@NonNull Network network) { CurrentNetwork activeNetwork = refreshNetworkStatus(); - Log.d(OPEN_TELEMETRY_RUM_LOG_TAG, " onAvailable: currentNetwork=" + activeNetwork); + Log.d(OTEL_RUM_LOG_TAG, " onAvailable: currentNetwork=" + activeNetwork); notifyListeners(activeNetwork); } @@ -151,7 +151,7 @@ public void onLost(@NonNull Network network) { // state at the right time during this event. CurrentNetwork currentNetwork = NO_NETWORK; CurrentNetworkProvider.this.currentNetwork = currentNetwork; - Log.d(OPEN_TELEMETRY_RUM_LOG_TAG, " onLost: currentNetwork=" + currentNetwork); + Log.d(OTEL_RUM_LOG_TAG, " onLost: currentNetwork=" + currentNetwork); notifyListeners(currentNetwork); } diff --git a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderListener.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderListener.java index 73fadd65b..fde4282d9 100644 --- a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderListener.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderListener.java @@ -18,7 +18,7 @@ import static android.view.FrameMetrics.DRAW_DURATION; import static android.view.FrameMetrics.FIRST_DRAW_FRAME; -import static io.opentelemetry.rum.internal.instrumentation.slowrendering.SlowRenderingDetector.OPEN_TELEMETRY_RUM_LOG_TAG; +import static io.opentelemetry.rum.internal.RumConstants.OTEL_RUM_LOG_TAG; import android.app.Activity; import android.os.Build; @@ -172,7 +172,7 @@ private void reportSlowRenders() { try { activities.forEach((activity, listener) -> reportSlow(listener)); } catch (Exception e) { - Log.w(OPEN_TELEMETRY_RUM_LOG_TAG, "Exception while processing frame metrics", e); + Log.w(OTEL_RUM_LOG_TAG, "Exception while processing frame metrics", e); } } @@ -185,12 +185,12 @@ private void reportSlow(PerActivityListener listener) { int count = durationToCountHistogram.get(duration); if (duration > FROZEN_THRESHOLD_MS) { Log.d( - OPEN_TELEMETRY_RUM_LOG_TAG, + OTEL_RUM_LOG_TAG, "* FROZEN RENDER DETECTED: " + duration + " ms." + count + " times"); frozenCount += count; } else if (duration > SLOW_THRESHOLD_MS) { Log.d( - OPEN_TELEMETRY_RUM_LOG_TAG, + OTEL_RUM_LOG_TAG, "* Slow render detected: " + duration + " ms. " + count + " times"); slowCount += count; } diff --git a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderingDetector.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderingDetector.java index 98ae05b20..7c4563d71 100644 --- a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderingDetector.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderingDetector.java @@ -16,6 +16,8 @@ package io.opentelemetry.rum.internal.instrumentation.slowrendering; +import static io.opentelemetry.rum.internal.RumConstants.OTEL_RUM_LOG_TAG; + import android.os.Build; import android.util.Log; import io.opentelemetry.rum.internal.instrumentation.InstrumentedApplication; @@ -29,8 +31,6 @@ */ public final class SlowRenderingDetector { - static final String OPEN_TELEMETRY_RUM_LOG_TAG = "OpenTelemetryRum"; - public static SlowRenderingDetector create() { return builder().build(); } @@ -52,7 +52,7 @@ public static SlowRenderingDetectorBuilder builder() { public void installOn(InstrumentedApplication instrumentedApplication) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { Log.w( - OPEN_TELEMETRY_RUM_LOG_TAG, + OTEL_RUM_LOG_TAG, "Slow/frozen rendering detection is not supported on platforms older than Android N (SDK version 24)."); return; } diff --git a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderingDetectorBuilder.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderingDetectorBuilder.java index 49d66657e..bb1f3e169 100644 --- a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderingDetectorBuilder.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/slowrendering/SlowRenderingDetectorBuilder.java @@ -16,7 +16,7 @@ package io.opentelemetry.rum.internal.instrumentation.slowrendering; -import static io.opentelemetry.rum.internal.instrumentation.slowrendering.SlowRenderingDetector.OPEN_TELEMETRY_RUM_LOG_TAG; +import static io.opentelemetry.rum.internal.RumConstants.OTEL_RUM_LOG_TAG; import android.util.Log; import java.time.Duration; @@ -42,7 +42,7 @@ public final class SlowRenderingDetectorBuilder { public SlowRenderingDetectorBuilder setSlowRenderingDetectionPollInterval(Duration interval) { if (interval.toMillis() <= 0) { Log.e( - OPEN_TELEMETRY_RUM_LOG_TAG, + OTEL_RUM_LOG_TAG, "Invalid slowRenderingDetectionPollInterval: " + interval + "; must be positive"); diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/AppStartupTimer.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/startup/AppStartupTimer.java similarity index 80% rename from splunk-otel-android/src/main/java/com/splunk/rum/AppStartupTimer.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/startup/AppStartupTimer.java index 48c8f8e5e..9b7d9e196 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/AppStartupTimer.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/instrumentation/startup/AppStartupTimer.java @@ -14,7 +14,10 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.startup; + +import static io.opentelemetry.rum.internal.RumConstants.OTEL_RUM_LOG_TAG; +import static io.opentelemetry.rum.internal.RumConstants.START_TYPE_KEY; import android.app.Activity; import android.app.Application; @@ -26,18 +29,18 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.rum.internal.DefaultingActivityLifecycleCallbacks; +import io.opentelemetry.rum.internal.util.AnchoredClock; import io.opentelemetry.sdk.common.Clock; import java.util.concurrent.TimeUnit; -class AppStartupTimer { +public class AppStartupTimer { // Maximum time from app start to creation of the UI. If this time is exceeded we will not // create the app start span. Long app startup could indicate that the app was really started in // background, in which case the measured startup time is misleading. private static final long MAX_TIME_TO_UI_INIT = TimeUnit.MINUTES.toNanos(1); // exposed so it can be used for the rest of the startup sequence timing. - final RumInitializer.AnchoredClock startupClock = - RumInitializer.AnchoredClock.create(Clock.getDefault()); + private final AnchoredClock startupClock = AnchoredClock.create(Clock.getDefault()); private final long firstPossibleTimestamp = startupClock.now(); @Nullable private volatile Span overallAppStartSpan = null; @Nullable private volatile Runnable completionCallback = null; @@ -50,7 +53,7 @@ class AppStartupTimer { // accessed only from UI thread private boolean isStartedFromBackground = false; - Span start(Tracer tracer) { + public Span start(Tracer tracer) { // guard against a double-start and just return what's already in flight. if (overallAppStartSpan != null) { return overallAppStartSpan; @@ -58,15 +61,25 @@ Span start(Tracer tracer) { final Span appStart = tracer.spanBuilder("AppStart") .setStartTimestamp(firstPossibleTimestamp, TimeUnit.NANOSECONDS) - .setAttribute(SplunkRum.COMPONENT_KEY, SplunkRum.COMPONENT_APPSTART) - .setAttribute(SplunkRum.START_TYPE_KEY, "cold") + .setAttribute(START_TYPE_KEY, "cold") .startSpan(); overallAppStartSpan = appStart; return appStart; } - /** Creates a lifecycle listener that starts the UI init when an activity is created. */ - Application.ActivityLifecycleCallbacks createLifecycleCallback() { + /** + * @return epoch timestamp in nanos calculated by the startupClock. + */ + public long clockNow() { + return startupClock.now(); + } + + /** + * Creates a lifecycle listener that starts the UI init when an activity is created. + * + * @return a new Application.ActivityLifecycleCallbacks instance + */ + public Application.ActivityLifecycleCallbacks createLifecycleCallback() { return new DefaultingActivityLifecycleCallbacks() { @Override public void onActivityCreated( @@ -83,17 +96,17 @@ private void startUiInit() { } uiInitStarted = true; if (firstPossibleTimestamp + MAX_TIME_TO_UI_INIT < startupClock.now()) { - Log.d(SplunkRum.LOG_TAG, "Max time to UI init exceeded"); + Log.d(OTEL_RUM_LOG_TAG, "Max time to UI init exceeded"); uiInitTooLate = true; clear(); } } - void setCompletionCallback(Runnable completionCallback) { + public void setCompletionCallback(Runnable completionCallback) { this.completionCallback = completionCallback; } - void end() { + public void end() { Span overallAppStartSpan = this.overallAppStartSpan; if (overallAppStartSpan != null && !uiInitTooLate && !isStartedFromBackground) { runCompletionCallback(); @@ -103,12 +116,12 @@ void end() { } @Nullable - Span getStartupSpan() { + public Span getStartupSpan() { return overallAppStartSpan; } // visibleForTesting - void runCompletionCallback() { + public void runCompletionCallback() { Runnable completionCallback = this.completionCallback; if (completionCallback != null) { completionCallback.run(); @@ -120,7 +133,7 @@ private void clear() { completionCallback = null; } - void detectBackgroundStart(Handler handler) { + public void detectBackgroundStart(Handler handler) { handler.post(new StartFromBackgroundRunnable(this)); } @@ -145,7 +158,7 @@ public StartFromBackgroundRunnable(AppStartupTimer startupTimer) { public void run() { // check whether an activity has been created if (!startupTimer.uiInitStarted) { - Log.d(SplunkRum.LOG_TAG, "Detected background app start"); + Log.d(OTEL_RUM_LOG_TAG, "Detected background app start"); startupTimer.isStartedFromBackground = true; } } diff --git a/splunk-otel-android/src/main/java/com/splunk/rum/ActiveSpan.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/util/ActiveSpan.java similarity index 70% rename from splunk-otel-android/src/main/java/com/splunk/rum/ActiveSpan.java rename to splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/util/ActiveSpan.java index 03fa48ca2..2e4430bfc 100644 --- a/splunk-otel-android/src/main/java/com/splunk/rum/ActiveSpan.java +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/util/ActiveSpan.java @@ -14,30 +14,32 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.util; + +import static io.opentelemetry.rum.internal.RumConstants.LAST_SCREEN_NAME_KEY; import androidx.annotation.Nullable; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Scope; import java.util.function.Supplier; -class ActiveSpan { - private final VisibleScreenTracker visibleScreenTracker; +public class ActiveSpan { + private final Supplier lastVisibleScreen; @Nullable private Span span; @Nullable private Scope scope; - ActiveSpan(VisibleScreenTracker visibleScreenTracker) { - this.visibleScreenTracker = visibleScreenTracker; + public ActiveSpan(Supplier lastVisibleScreen) { + this.lastVisibleScreen = lastVisibleScreen; } - boolean spanInProgress() { + public boolean spanInProgress() { return span != null; } // it's fine to not close the scope here, will be closed in endActiveSpan() @SuppressWarnings("MustBeClosedChecker") - void startSpan(Supplier spanCreator) { + public void startSpan(Supplier spanCreator) { // don't start one if there's already one in progress if (span != null) { return; @@ -46,7 +48,7 @@ void startSpan(Supplier spanCreator) { scope = span.makeCurrent(); } - void endActiveSpan() { + public void endActiveSpan() { if (scope != null) { scope.close(); scope = null; @@ -57,19 +59,19 @@ void endActiveSpan() { } } - void addEvent(String eventName) { + public void addEvent(String eventName) { if (span != null) { span.addEvent(eventName); } } - void addPreviousScreenAttribute(String screenName) { + public void addPreviousScreenAttribute(String screenName) { if (span == null) { return; } - String previouslyVisibleScreen = visibleScreenTracker.getPreviouslyVisibleScreen(); + String previouslyVisibleScreen = lastVisibleScreen.get(); if (previouslyVisibleScreen != null && !screenName.equals(previouslyVisibleScreen)) { - span.setAttribute(SplunkRum.LAST_SCREEN_NAME_KEY, previouslyVisibleScreen); + span.setAttribute(LAST_SCREEN_NAME_KEY, previouslyVisibleScreen); } } } diff --git a/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/util/AnchoredClock.java b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/util/AnchoredClock.java new file mode 100644 index 000000000..ce3c2260f --- /dev/null +++ b/splunk-otel-android/src/main/java/io/opentelemetry/rum/internal/util/AnchoredClock.java @@ -0,0 +1,41 @@ +/* + * Copyright Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.rum.internal.util; + +import io.opentelemetry.sdk.common.Clock; + +// copied from otel-java +public 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()); + } + + public long now() { + long deltaNanos = this.clock.nanoTime() - this.nanoTime; + return this.epochNanos + deltaNanos; + } +} diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/CrashComponentExtractorTest.java b/splunk-otel-android/src/test/java/com/splunk/rum/CrashComponentExtractorTest.java index 35e8c53a3..7885e367b 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/CrashComponentExtractorTest.java +++ b/splunk-otel-android/src/test/java/com/splunk/rum/CrashComponentExtractorTest.java @@ -16,6 +16,7 @@ package com.splunk.rum; +import static com.splunk.rum.SplunkRum.COMPONENT_KEY; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import io.opentelemetry.api.common.Attributes; @@ -33,7 +34,7 @@ void shouldSetComponentCrashOnTheFirstInvocation() { extractor.onStart(builder, null, null); assertThat(builder.build()) .hasSize(1) - .containsEntry(SplunkRum.COMPONENT_KEY, SplunkRum.COMPONENT_CRASH); + .containsEntry(COMPONENT_KEY, SplunkRum.COMPONENT_CRASH); } { @@ -41,7 +42,7 @@ void shouldSetComponentCrashOnTheFirstInvocation() { extractor.onStart(builder, null, null); assertThat(builder.build()) .hasSize(1) - .containsEntry(SplunkRum.COMPONENT_KEY, SplunkRum.COMPONENT_ERROR); + .containsEntry(COMPONENT_KEY, SplunkRum.COMPONENT_ERROR); } } } diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/RumInitializerTest.java b/splunk-otel-android/src/test/java/com/splunk/rum/RumInitializerTest.java index 308cebce3..924f1afd1 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/RumInitializerTest.java +++ b/splunk-otel-android/src/test/java/com/splunk/rum/RumInitializerTest.java @@ -16,6 +16,7 @@ package com.splunk.rum; +import static com.splunk.rum.SplunkRum.COMPONENT_KEY; import static io.opentelemetry.api.common.AttributeKey.stringKey; import static java.util.Collections.emptyList; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -36,6 +37,7 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.rum.internal.instrumentation.network.CurrentNetwork; import io.opentelemetry.rum.internal.instrumentation.network.CurrentNetworkProvider; +import io.opentelemetry.rum.internal.instrumentation.startup.AppStartupTimer; import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; import io.opentelemetry.sdk.testing.trace.TestSpanData; @@ -90,7 +92,7 @@ SpanExporter buildFilteringExporter(CurrentNetworkProvider connectionUtil) { initSpan.getParentSpanContext(), startupTimer.getStartupSpan().getSpanContext()); assertEquals("SplunkRum.initialize", initSpan.getName()); - assertEquals("appstart", initSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); + assertEquals("appstart", initSpan.getAttributes().get(COMPONENT_KEY)); assertEquals( "[debug:false,crashReporting:true,anrReporting:true,slowRenderingDetector:true,networkMonitor:true]", initSpan.getAttributes().get(stringKey("config_settings"))); @@ -257,7 +259,7 @@ SpanExporter getCoreSpanExporter(String endpoint) { OpenTelemetryAssertions.assertThat( attributes) .containsEntry( - SplunkRum.COMPONENT_KEY, + COMPONENT_KEY, SplunkRum.COMPONENT_ERROR) .containsEntry( stringKey("attribute"), diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/RumResponseAttributesExtractorTest.java b/splunk-otel-android/src/test/java/com/splunk/rum/RumResponseAttributesExtractorTest.java index 14f7eb20f..1ca693b2e 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/RumResponseAttributesExtractorTest.java +++ b/splunk-otel-android/src/test/java/com/splunk/rum/RumResponseAttributesExtractorTest.java @@ -16,6 +16,9 @@ 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; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.mockito.Mockito.mock; @@ -56,9 +59,9 @@ void spanDecoration() { assertThat(attributes) .containsOnly( - entry(SplunkRum.COMPONENT_KEY, "http"), - entry(SplunkRum.LINK_TRACE_ID_KEY, "9499195c502eb217c448a68bfe0f967c"), - entry(SplunkRum.LINK_SPAN_ID_KEY, "fe16eca542cd5d86")); + entry(COMPONENT_KEY, "http"), + entry(LINK_TRACE_ID_KEY, "9499195c502eb217c448a68bfe0f967c"), + entry(LINK_SPAN_ID_KEY, "fe16eca542cd5d86")); } @Test @@ -82,6 +85,6 @@ void spanDecoration_noLinkingHeader() { attributesExtractor.onStart(attributesBuilder, Context.root(), fakeRequest); Attributes attributes = attributesBuilder.build(); - assertThat(attributes).containsOnly(entry(SplunkRum.COMPONENT_KEY, "http")); + assertThat(attributes).containsOnly(entry(COMPONENT_KEY, "http")); } } diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/ScreenAttributesAppenderTest.java b/splunk-otel-android/src/test/java/com/splunk/rum/ScreenAttributesAppenderTest.java index 2ed8961e5..20c0ac651 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/ScreenAttributesAppenderTest.java +++ b/splunk-otel-android/src/test/java/com/splunk/rum/ScreenAttributesAppenderTest.java @@ -16,6 +16,8 @@ package com.splunk.rum; +import static io.opentelemetry.rum.internal.RumConstants.LAST_SCREEN_NAME_KEY; +import static io.opentelemetry.rum.internal.RumConstants.SCREEN_NAME_KEY; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -26,6 +28,7 @@ import static org.mockito.Mockito.when; import io.opentelemetry.context.Context; +import io.opentelemetry.rum.internal.instrumentation.activity.VisibleScreenTracker; import io.opentelemetry.sdk.trace.ReadWriteSpan; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -58,7 +61,7 @@ void appendAttributesOnStart() { new ScreenAttributesAppender(visibleScreenTracker); screenAttributesAppender.onStart(Context.current(), span); - verify(span).setAttribute(SplunkRum.SCREEN_NAME_KEY, "ScreenOne"); + verify(span).setAttribute(SCREEN_NAME_KEY, "ScreenOne"); } @Test @@ -71,7 +74,7 @@ void appendAttributes_noCurrentScreens() { new ScreenAttributesAppender(visibleScreenTracker); screenAttributesAppender.onStart(Context.current(), span); - verify(span).setAttribute(SplunkRum.SCREEN_NAME_KEY, "unknown"); - verify(span, never()).setAttribute(eq(SplunkRum.LAST_SCREEN_NAME_KEY), any()); + verify(span).setAttribute(SCREEN_NAME_KEY, "unknown"); + verify(span, never()).setAttribute(eq(LAST_SCREEN_NAME_KEY), any()); } } diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/SplunkRumTest.java b/splunk-otel-android/src/test/java/com/splunk/rum/SplunkRumTest.java index 2de376466..3000572c7 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/SplunkRumTest.java +++ b/splunk-otel-android/src/test/java/com/splunk/rum/SplunkRumTest.java @@ -16,6 +16,7 @@ package com.splunk.rum; +import static com.splunk.rum.SplunkRum.COMPONENT_KEY; import static io.opentelemetry.api.common.AttributeKey.longKey; import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; @@ -193,7 +194,7 @@ void addException() { .hasName("NullPointerException") .hasAttributes( attributes.toBuilder() - .put(SplunkRum.COMPONENT_KEY, SplunkRum.COMPONENT_ERROR) + .put(COMPONENT_KEY, SplunkRum.COMPONENT_ERROR) .build()) .hasException(exception); } diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/ThrottlingExporterTest.java b/splunk-otel-android/src/test/java/com/splunk/rum/ThrottlingExporterTest.java index fb16017d1..953eb092c 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/ThrottlingExporterTest.java +++ b/splunk-otel-android/src/test/java/com/splunk/rum/ThrottlingExporterTest.java @@ -16,6 +16,7 @@ package com.splunk.rum; +import static com.splunk.rum.SplunkRum.COMPONENT_KEY; import static java.util.Arrays.asList; import static org.mockito.Mockito.verify; @@ -108,7 +109,7 @@ void shouldCountDifferentComponentsSeparately() { // given SpanExporter underTest = ThrottlingExporter.newBuilder(delegate) - .categorizeByAttribute(SplunkRum.COMPONENT_KEY) + .categorizeByAttribute(COMPONENT_KEY) .maxSpansInWindow(2) .windowSize(Duration.ofSeconds(15)) .build(); @@ -155,7 +156,7 @@ void shouldKeepStateBetweenExportCalls() { // given SpanExporter underTest = ThrottlingExporter.newBuilder(delegate) - .categorizeByAttribute(SplunkRum.COMPONENT_KEY) + .categorizeByAttribute(COMPONENT_KEY) .maxSpansInWindow(2) .windowSize(Duration.ofSeconds(15)) .build(); @@ -228,7 +229,7 @@ private static SpanData span(String component, Instant endTime) { .setStartEpochNanos(0) .setEndEpochNanos( TimeUnit.SECONDS.toNanos(endTime.getEpochSecond()) + endTime.getNano()) - .setAttributes(Attributes.of(SplunkRum.COMPONENT_KEY, component)) + .setAttributes(Attributes.of(COMPONENT_KEY, component)) .build(); } } diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/ActivityCallbackTestHarness.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityCallbackTestHarness.java similarity index 98% rename from splunk-otel-android/src/test/java/com/splunk/rum/ActivityCallbackTestHarness.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityCallbackTestHarness.java index ef5171ba1..9e2847e5f 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/ActivityCallbackTestHarness.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityCallbackTestHarness.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import static org.mockito.Mockito.mock; diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/ActivityCallbacksTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityCallbacksTest.java similarity index 81% rename from splunk-otel-android/src/test/java/com/splunk/rum/ActivityCallbacksTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityCallbacksTest.java index 119dee91c..86f84d2de 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/ActivityCallbacksTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityCallbacksTest.java @@ -14,8 +14,11 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; +import static io.opentelemetry.rum.internal.RumConstants.LAST_SCREEN_NAME_KEY; +import static io.opentelemetry.rum.internal.RumConstants.SCREEN_NAME_KEY; +import static io.opentelemetry.rum.internal.RumConstants.START_TYPE_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -24,6 +27,7 @@ import android.app.Activity; import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.rum.internal.instrumentation.startup.AppStartupTimer; import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; import io.opentelemetry.sdk.trace.data.EventData; import io.opentelemetry.sdk.trace.data.SpanData; @@ -65,17 +69,13 @@ void appStartup() { // assertEquals("AppStart", startupSpan.getName()); // assertEquals("cold", startupSpan.getAttributes().get(SplunkRum.START_TYPE_KEY)); - // SpanData creationSpan = spans.get(1); - assertEquals( activity.getClass().getSimpleName(), creationSpan.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( activity.getClass().getSimpleName(), - creationSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, creationSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(creationSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + creationSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(creationSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = creationSpan.getEvents(); assertEquals(9, events.size()); @@ -109,16 +109,13 @@ void activityCreation() { SpanData span = spans.get(0); assertEquals("AppStart", span.getName()); - assertEquals("warm", span.getAttributes().get(SplunkRum.START_TYPE_KEY)); + assertEquals("warm", span.getAttributes().get(START_TYPE_KEY)); assertEquals( activity.getClass().getSimpleName(), span.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( - activity.getClass().getSimpleName(), - span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_APPSTART, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + activity.getClass().getSimpleName(), span.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = span.getEvents(); assertEquals(9, events.size()); @@ -160,16 +157,13 @@ void activityRestart() { SpanData span = spans.get(0); assertEquals("AppStart", span.getName()); - assertEquals("hot", span.getAttributes().get(SplunkRum.START_TYPE_KEY)); + assertEquals("hot", span.getAttributes().get(START_TYPE_KEY)); assertEquals( activity.getClass().getSimpleName(), span.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( - activity.getClass().getSimpleName(), - span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_APPSTART, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + activity.getClass().getSimpleName(), span.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = span.getEvents(); assertEquals(6, events.size()); @@ -206,10 +200,8 @@ void activityResumed() { activity.getClass().getSimpleName(), span.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( - activity.getClass().getSimpleName(), - span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals(SplunkRum.COMPONENT_UI, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertEquals("previousScreen", span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + activity.getClass().getSimpleName(), span.getAttributes().get(SCREEN_NAME_KEY)); + assertEquals("previousScreen", span.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = span.getEvents(); assertEquals(3, events.size()); @@ -241,10 +233,8 @@ void activityDestroyedFromStopped() { activity.getClass().getSimpleName(), span.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( - activity.getClass().getSimpleName(), - span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals(SplunkRum.COMPONENT_UI, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + activity.getClass().getSimpleName(), span.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = span.getEvents(); assertEquals(3, events.size()); @@ -277,10 +267,8 @@ void activityDestroyedFromPaused() { stoppedSpan.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( activity.getClass().getSimpleName(), - stoppedSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, stoppedSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(stoppedSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + stoppedSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(stoppedSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = stoppedSpan.getEvents(); assertEquals(3, events.size()); @@ -297,9 +285,8 @@ void activityDestroyedFromPaused() { destroyedSpan.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( activity.getClass().getSimpleName(), - destroyedSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals("ui", destroyedSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(destroyedSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + destroyedSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(destroyedSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); events = destroyedSpan.getEvents(); assertEquals(3, events.size()); @@ -332,10 +319,8 @@ void activityStoppedFromRunning() { stoppedSpan.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( activity.getClass().getSimpleName(), - stoppedSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, stoppedSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(stoppedSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + stoppedSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(stoppedSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = stoppedSpan.getEvents(); assertEquals(3, events.size()); @@ -352,9 +337,8 @@ void activityStoppedFromRunning() { destroyedSpan.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( activity.getClass().getSimpleName(), - destroyedSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals("ui", destroyedSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(destroyedSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + destroyedSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(destroyedSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); events = destroyedSpan.getEvents(); assertEquals(3, events.size()); diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/ActivityTracerCacheTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracerCacheTest.java similarity index 98% rename from splunk-otel-android/src/test/java/com/splunk/rum/ActivityTracerCacheTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracerCacheTest.java index 736d4325f..776be8946 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/ActivityTracerCacheTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracerCacheTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import static org.junit.jupiter.api.Assertions.assertSame; import static org.mockito.ArgumentMatchers.anyString; diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/ActivityTracerTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracerTest.java similarity index 57% rename from splunk-otel-android/src/test/java/com/splunk/rum/ActivityTracerTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracerTest.java index e46ed55d7..852ae30be 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/ActivityTracerTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/ActivityTracerTest.java @@ -14,19 +14,24 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; +import static io.opentelemetry.rum.internal.RumConstants.LAST_SCREEN_NAME_KEY; +import static io.opentelemetry.rum.internal.RumConstants.SCREEN_NAME_KEY; +import static io.opentelemetry.rum.internal.RumConstants.START_TYPE_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.Activity; +import com.splunk.rum.RumScreenName; import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.rum.internal.instrumentation.startup.AppStartupTimer; +import io.opentelemetry.rum.internal.util.ActiveSpan; import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; import io.opentelemetry.sdk.trace.data.SpanData; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -37,106 +42,104 @@ public class ActivityTracerTest { private Tracer tracer; private final VisibleScreenTracker visibleScreenTracker = mock(VisibleScreenTracker.class); private final AppStartupTimer appStartupTimer = new AppStartupTimer(); + private ActiveSpan activeSpan; @BeforeEach public void setup() { tracer = otelTesting.getOpenTelemetry().getTracer("testTracer"); + activeSpan = new ActiveSpan(visibleScreenTracker::getPreviouslyVisibleScreen); } @Test void restart_nonInitialActivity() { ActivityTracer trackableTracer = - new ActivityTracer( - mock(Activity.class), - new AtomicReference<>("FirstActivity"), - tracer, - visibleScreenTracker, - appStartupTimer); + ActivityTracer.builder(mock(Activity.class)) + .setInitialAppActivity("FirstActivity") + .setTracer(tracer) + .setAppStartupTimer(appStartupTimer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.initiateRestartSpanIfNecessary(false); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); assertEquals("Restarted", span.getName()); - assertNull(span.getAttributes().get(SplunkRum.START_TYPE_KEY)); + assertNull(span.getAttributes().get(START_TYPE_KEY)); } @Test public void restart_initialActivity() { ActivityTracer trackableTracer = - new ActivityTracer( - mock(Activity.class), - new AtomicReference<>("Activity"), - tracer, - visibleScreenTracker, - appStartupTimer); + ActivityTracer.builder(mock(Activity.class)) + .setInitialAppActivity("Activity") + .setTracer(tracer) + .setAppStartupTimer(appStartupTimer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.initiateRestartSpanIfNecessary(false); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); assertEquals("AppStart", span.getName()); - assertEquals("hot", span.getAttributes().get(SplunkRum.START_TYPE_KEY)); - assertEquals( - SplunkRum.COMPONENT_APPSTART, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); + assertEquals("hot", span.getAttributes().get(START_TYPE_KEY)); } @Test public void restart_initialActivity_multiActivityApp() { ActivityTracer trackableTracer = - new ActivityTracer( - mock(Activity.class), - new AtomicReference<>("Activity"), - tracer, - visibleScreenTracker, - appStartupTimer); + ActivityTracer.builder(mock(Activity.class)) + .setInitialAppActivity("Activity") + .setTracer(tracer) + .setAppStartupTimer(appStartupTimer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.initiateRestartSpanIfNecessary(true); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); assertEquals("Restarted", span.getName()); - assertNull(span.getAttributes().get(SplunkRum.START_TYPE_KEY)); + assertNull(span.getAttributes().get(START_TYPE_KEY)); } @Test public void create_nonInitialActivity() { ActivityTracer trackableTracer = - new ActivityTracer( - mock(Activity.class), - new AtomicReference<>("FirstActivity"), - tracer, - visibleScreenTracker, - appStartupTimer); + ActivityTracer.builder(mock(Activity.class)) + .setInitialAppActivity("FirstActivity") + .setTracer(tracer) + .setAppStartupTimer(appStartupTimer) + .setActiveSpan(activeSpan) + .build(); + trackableTracer.startActivityCreation(); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); assertEquals("Created", span.getName()); - assertNull(span.getAttributes().get(SplunkRum.START_TYPE_KEY)); + assertNull(span.getAttributes().get(START_TYPE_KEY)); } @Test public void create_initialActivity() { ActivityTracer trackableTracer = - new ActivityTracer( - mock(Activity.class), - new AtomicReference<>("Activity"), - tracer, - visibleScreenTracker, - appStartupTimer); + ActivityTracer.builder(mock(Activity.class)) + .setInitialAppActivity("Activity") + .setTracer(tracer) + .setAppStartupTimer(appStartupTimer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.startActivityCreation(); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); assertEquals("AppStart", span.getName()); - assertEquals("warm", span.getAttributes().get(SplunkRum.START_TYPE_KEY)); - assertEquals( - SplunkRum.COMPONENT_APPSTART, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); + assertEquals("warm", span.getAttributes().get(START_TYPE_KEY)); } @Test public void create_initialActivity_firstTime() { appStartupTimer.start(tracer); ActivityTracer trackableTracer = - new ActivityTracer( - mock(Activity.class), - new AtomicReference<>(), - tracer, - visibleScreenTracker, - appStartupTimer); + ActivityTracer.builder(mock(Activity.class)) + .setTracer(tracer) + .setAppStartupTimer(appStartupTimer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.startActivityCreation(); trackableTracer.endActiveSpan(); appStartupTimer.end(); @@ -146,7 +149,7 @@ public void create_initialActivity_firstTime() { SpanData appStartSpan = spans.get(0); assertEquals("AppStart", appStartSpan.getName()); - assertEquals("cold", appStartSpan.getAttributes().get(SplunkRum.START_TYPE_KEY)); + assertEquals("cold", appStartSpan.getAttributes().get(START_TYPE_KEY)); SpanData innerSpan = spans.get(1); assertEquals("Created", innerSpan.getName()); @@ -154,22 +157,19 @@ public void create_initialActivity_firstTime() { @Test public void addPreviousScreen_noPrevious() { - VisibleScreenTracker visibleScreenTracker = mock(VisibleScreenTracker.class); - ActivityTracer trackableTracer = - new ActivityTracer( - mock(Activity.class), - new AtomicReference<>(), - tracer, - visibleScreenTracker, - appStartupTimer); + ActivityTracer.builder(mock(Activity.class)) + .setTracer(tracer) + .setAppStartupTimer(appStartupTimer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.startSpanIfNoneInProgress("starting"); trackableTracer.addPreviousScreenAttribute(); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); } @Test @@ -178,19 +178,18 @@ public void addPreviousScreen_currentSameAsPrevious() { when(visibleScreenTracker.getPreviouslyVisibleScreen()).thenReturn("Activity"); ActivityTracer trackableTracer = - new ActivityTracer( - mock(Activity.class), - new AtomicReference<>(), - tracer, - visibleScreenTracker, - appStartupTimer); + ActivityTracer.builder(mock(Activity.class)) + .setTracer(tracer) + .setAppStartupTimer(appStartupTimer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.startSpanIfNoneInProgress("starting"); trackableTracer.addPreviousScreenAttribute(); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); } @Test @@ -198,35 +197,33 @@ public void addPreviousScreen() { when(visibleScreenTracker.getPreviouslyVisibleScreen()).thenReturn("previousScreen"); ActivityTracer trackableTracer = - new ActivityTracer( - mock(Activity.class), - new AtomicReference<>(), - tracer, - visibleScreenTracker, - appStartupTimer); + ActivityTracer.builder(mock(Activity.class)) + .setTracer(tracer) + .setAppStartupTimer(appStartupTimer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.startSpanIfNoneInProgress("starting"); trackableTracer.addPreviousScreenAttribute(); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); - assertEquals("previousScreen", span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertEquals("previousScreen", span.getAttributes().get(LAST_SCREEN_NAME_KEY)); } @Test public void testAnnotatedActivity() { Activity annotatedActivity = new AnnotatedActivity(); ActivityTracer activityTracer = - new ActivityTracer( - annotatedActivity, - new AtomicReference<>(), - tracer, - visibleScreenTracker, - appStartupTimer); + ActivityTracer.builder(annotatedActivity) + .setTracer(tracer) + .setAppStartupTimer(appStartupTimer) + .setActiveSpan(activeSpan) + .build(); activityTracer.startActivityCreation(); activityTracer.endActiveSpan(); SpanData span = getSingleSpan(); - assertEquals("squarely", span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); + assertEquals("squarely", span.getAttributes().get(SCREEN_NAME_KEY)); } @RumScreenName("squarely") diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/Pre29ActivityCallbackTestHarness.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29ActivityCallbackTestHarness.java similarity index 97% rename from splunk-otel-android/src/test/java/com/splunk/rum/Pre29ActivityCallbackTestHarness.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29ActivityCallbackTestHarness.java index 460361d15..e8c7eb1d7 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/Pre29ActivityCallbackTestHarness.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29ActivityCallbackTestHarness.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import static org.mockito.Mockito.mock; diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/Pre29ActivityLifecycleCallbacksTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29ActivityLifecycleCallbacksTest.java similarity index 79% rename from splunk-otel-android/src/test/java/com/splunk/rum/Pre29ActivityLifecycleCallbacksTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29ActivityLifecycleCallbacksTest.java index b217efd98..f6302ed85 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/Pre29ActivityLifecycleCallbacksTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29ActivityLifecycleCallbacksTest.java @@ -14,8 +14,11 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; +import static io.opentelemetry.rum.internal.RumConstants.LAST_SCREEN_NAME_KEY; +import static io.opentelemetry.rum.internal.RumConstants.SCREEN_NAME_KEY; +import static io.opentelemetry.rum.internal.RumConstants.START_TYPE_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -24,6 +27,7 @@ import android.app.Activity; import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.rum.internal.instrumentation.startup.AppStartupTimer; import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; import io.opentelemetry.sdk.trace.data.EventData; import io.opentelemetry.sdk.trace.data.SpanData; @@ -70,10 +74,8 @@ void appStartup() { creationSpan.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( activity.getClass().getSimpleName(), - creationSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, creationSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(creationSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + creationSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(creationSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = creationSpan.getEvents(); assertEquals(3, events.size()); @@ -98,16 +100,13 @@ void activityCreation() { SpanData span = spans.get(0); assertEquals("AppStart", span.getName()); - assertEquals("warm", span.getAttributes().get(SplunkRum.START_TYPE_KEY)); + assertEquals("warm", span.getAttributes().get(START_TYPE_KEY)); assertEquals( activity.getClass().getSimpleName(), span.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( - activity.getClass().getSimpleName(), - span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_APPSTART, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + activity.getClass().getSimpleName(), span.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = span.getEvents(); assertEquals(3, events.size()); @@ -140,16 +139,13 @@ void activityRestart() { SpanData span = spans.get(0); assertEquals("AppStart", span.getName()); - assertEquals("hot", span.getAttributes().get(SplunkRum.START_TYPE_KEY)); + assertEquals("hot", span.getAttributes().get(START_TYPE_KEY)); assertEquals( activity.getClass().getSimpleName(), span.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( - activity.getClass().getSimpleName(), - span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_APPSTART, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + activity.getClass().getSimpleName(), span.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = span.getEvents(); assertEquals(2, events.size()); @@ -181,10 +177,8 @@ void activityResumed() { activity.getClass().getSimpleName(), span.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( - activity.getClass().getSimpleName(), - span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals(SplunkRum.COMPONENT_UI, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertEquals("previousScreen", span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + activity.getClass().getSimpleName(), span.getAttributes().get(SCREEN_NAME_KEY)); + assertEquals("previousScreen", span.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = span.getEvents(); assertEquals(1, events.size()); @@ -213,10 +207,8 @@ void activityDestroyedFromStopped() { activity.getClass().getSimpleName(), span.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( - activity.getClass().getSimpleName(), - span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals(SplunkRum.COMPONENT_UI, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + activity.getClass().getSimpleName(), span.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = span.getEvents(); assertEquals(1, events.size()); @@ -246,10 +238,8 @@ void activityDestroyedFromPaused() { stoppedSpan.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( activity.getClass().getSimpleName(), - stoppedSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, stoppedSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(stoppedSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + stoppedSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(stoppedSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = stoppedSpan.getEvents(); assertEquals(1, events.size()); @@ -264,9 +254,8 @@ void activityDestroyedFromPaused() { destroyedSpan.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( activity.getClass().getSimpleName(), - destroyedSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals("ui", destroyedSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(destroyedSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + destroyedSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(destroyedSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); events = destroyedSpan.getEvents(); assertEquals(1, events.size()); @@ -296,10 +285,8 @@ void activityStoppedFromRunning() { stoppedSpan.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( activity.getClass().getSimpleName(), - stoppedSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, stoppedSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(stoppedSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + stoppedSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(stoppedSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = stoppedSpan.getEvents(); assertEquals(1, events.size()); @@ -314,9 +301,8 @@ void activityStoppedFromRunning() { destroyedSpan.getAttributes().get(ActivityTracer.ACTIVITY_NAME_KEY)); assertEquals( activity.getClass().getSimpleName(), - destroyedSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals("ui", destroyedSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(destroyedSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + destroyedSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(destroyedSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); events = destroyedSpan.getEvents(); assertEquals(1, events.size()); diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/Pre29VisibleScreenLifecycleBindingTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29VisibleScreenLifecycleBindingTest.java similarity index 96% rename from splunk-otel-android/src/test/java/com/splunk/rum/Pre29VisibleScreenLifecycleBindingTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29VisibleScreenLifecycleBindingTest.java index 234ffc11c..65a2ccea1 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/Pre29VisibleScreenLifecycleBindingTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/Pre29VisibleScreenLifecycleBindingTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/VisibleScreenLifecycleBindingTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenLifecycleBindingTest.java similarity index 96% rename from splunk-otel-android/src/test/java/com/splunk/rum/VisibleScreenLifecycleBindingTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenLifecycleBindingTest.java index 29169b313..d25864f53 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/VisibleScreenLifecycleBindingTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenLifecycleBindingTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/VisibleScreenTrackerTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenTrackerTest.java similarity index 98% rename from splunk-otel-android/src/test/java/com/splunk/rum/VisibleScreenTrackerTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenTrackerTest.java index 1d9144113..efd3ff3ef 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/VisibleScreenTrackerTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/activity/VisibleScreenTrackerTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.activity; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/FragmentCallbackTestHarness.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/fragment/FragmentCallbackTestHarness.java similarity index 98% rename from splunk-otel-android/src/test/java/com/splunk/rum/FragmentCallbackTestHarness.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/fragment/FragmentCallbackTestHarness.java index 1ce17889d..9101d2d31 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/FragmentCallbackTestHarness.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/fragment/FragmentCallbackTestHarness.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.fragment; import static org.mockito.Mockito.mock; diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/FragmentTracerTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/fragment/FragmentTracerTest.java similarity index 63% rename from splunk-otel-android/src/test/java/com/splunk/rum/FragmentTracerTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/fragment/FragmentTracerTest.java index 843cb0235..53c3fe2b8 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/FragmentTracerTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/fragment/FragmentTracerTest.java @@ -14,15 +14,20 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.fragment; +import static io.opentelemetry.rum.internal.RumConstants.LAST_SCREEN_NAME_KEY; +import static io.opentelemetry.rum.internal.RumConstants.SCREEN_NAME_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import androidx.fragment.app.Fragment; +import com.splunk.rum.RumScreenName; import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.rum.internal.instrumentation.activity.VisibleScreenTracker; +import io.opentelemetry.rum.internal.util.ActiveSpan; import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; import io.opentelemetry.sdk.trace.data.SpanData; import java.util.List; @@ -33,17 +38,22 @@ class FragmentTracerTest { @RegisterExtension final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create(); private Tracer tracer; - private final VisibleScreenTracker visibleScreenTracker = mock(VisibleScreenTracker.class); + private ActiveSpan activeSpan; @BeforeEach void setup() { tracer = otelTesting.getOpenTelemetry().getTracer("testTracer"); + VisibleScreenTracker visibleScreenTracker = mock(VisibleScreenTracker.class); + activeSpan = new ActiveSpan(visibleScreenTracker::getPreviouslyVisibleScreen); } @Test void create() { FragmentTracer trackableTracer = - new FragmentTracer(mock(Fragment.class), tracer, visibleScreenTracker); + FragmentTracer.builder(mock(Fragment.class)) + .setTracer(tracer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.startFragmentCreation(); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); @@ -55,14 +65,17 @@ void addPreviousScreen_noPrevious() { VisibleScreenTracker visibleScreenTracker = mock(VisibleScreenTracker.class); FragmentTracer trackableTracer = - new FragmentTracer(mock(Fragment.class), tracer, visibleScreenTracker); + FragmentTracer.builder(mock(Fragment.class)) + .setTracer(tracer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.startSpanIfNoneInProgress("starting"); trackableTracer.addPreviousScreenAttribute(); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); } @Test @@ -71,39 +84,53 @@ void addPreviousScreen_currentSameAsPrevious() { when(visibleScreenTracker.getPreviouslyVisibleScreen()).thenReturn("Fragment"); FragmentTracer trackableTracer = - new FragmentTracer(mock(Fragment.class), tracer, visibleScreenTracker); + FragmentTracer.builder(mock(Fragment.class)) + .setTracer(tracer) + .setActiveSpan(activeSpan) + .build(); trackableTracer.startSpanIfNoneInProgress("starting"); trackableTracer.addPreviousScreenAttribute(); trackableTracer.endActiveSpan(); SpanData span = getSingleSpan(); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); } @Test void addPreviousScreen() { + + VisibleScreenTracker visibleScreenTracker = mock(VisibleScreenTracker.class); when(visibleScreenTracker.getPreviouslyVisibleScreen()).thenReturn("previousScreen"); + activeSpan = new ActiveSpan(visibleScreenTracker::getPreviouslyVisibleScreen); FragmentTracer fragmentTracer = - new FragmentTracer(mock(Fragment.class), tracer, visibleScreenTracker); + FragmentTracer.builder(mock(Fragment.class)) + .setTracer(tracer) + .setActiveSpan(activeSpan) + .build(); fragmentTracer.startSpanIfNoneInProgress("starting"); fragmentTracer.addPreviousScreenAttribute(); fragmentTracer.endActiveSpan(); SpanData span = getSingleSpan(); - assertEquals("previousScreen", span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertEquals("previousScreen", span.getAttributes().get(LAST_SCREEN_NAME_KEY)); } @Test void testAnnotatedScreenName() { Fragment fragment = new AnnotatedFragment(); - FragmentTracer fragmentTracer = new FragmentTracer(fragment, tracer, visibleScreenTracker); + FragmentTracer fragmentTracer = + FragmentTracer.builder(fragment) + .setTracer(tracer) + .setActiveSpan(activeSpan) + .build(); + fragmentTracer.startFragmentCreation(); fragmentTracer.endActiveSpan(); SpanData span = getSingleSpan(); - assertEquals("bumpity", span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); + assertEquals("bumpity", span.getAttributes().get(SCREEN_NAME_KEY)); } @RumScreenName("bumpity") diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/RumFragmentLifecycleCallbacksTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/fragment/RumFragmentLifecycleCallbacksTest.java similarity index 78% rename from splunk-otel-android/src/test/java/com/splunk/rum/RumFragmentLifecycleCallbacksTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/fragment/RumFragmentLifecycleCallbacksTest.java index 0bdbd7add..2a5ead6ad 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/RumFragmentLifecycleCallbacksTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/fragment/RumFragmentLifecycleCallbacksTest.java @@ -14,8 +14,10 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.fragment; +import static io.opentelemetry.rum.internal.RumConstants.LAST_SCREEN_NAME_KEY; +import static io.opentelemetry.rum.internal.RumConstants.SCREEN_NAME_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -25,6 +27,7 @@ import androidx.fragment.app.Fragment; import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.rum.internal.instrumentation.activity.VisibleScreenTracker; import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; import io.opentelemetry.sdk.trace.data.EventData; import io.opentelemetry.sdk.trace.data.SpanData; @@ -63,10 +66,8 @@ void fragmentCreation() { fragment.getClass().getSimpleName(), spanData.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); assertEquals( - fragment.getClass().getSimpleName(), - spanData.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals(SplunkRum.COMPONENT_UI, spanData.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(spanData.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + fragment.getClass().getSimpleName(), spanData.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(spanData.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = spanData.getEvents(); assertEquals(7, events.size()); @@ -99,11 +100,8 @@ void fragmentRestored() { fragment.getClass().getSimpleName(), spanData.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); assertEquals( - fragment.getClass().getSimpleName(), - spanData.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals(SplunkRum.COMPONENT_UI, spanData.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertEquals( - "previousScreen", spanData.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + fragment.getClass().getSimpleName(), spanData.getAttributes().get(SCREEN_NAME_KEY)); + assertEquals("previousScreen", spanData.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = spanData.getEvents(); assertEquals(3, events.size()); @@ -130,8 +128,7 @@ void fragmentResumed() { assertEquals( fragment.getClass().getSimpleName(), spanData.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); - assertEquals(SplunkRum.COMPONENT_UI, spanData.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(spanData.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertNull(spanData.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = spanData.getEvents(); assertEquals(1, events.size()); @@ -157,10 +154,8 @@ void fragmentPaused() { fragment.getClass().getSimpleName(), spanData.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); assertEquals( - fragment.getClass().getSimpleName(), - spanData.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals(SplunkRum.COMPONENT_UI, spanData.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(spanData.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + fragment.getClass().getSimpleName(), spanData.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(spanData.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = spanData.getEvents(); assertEquals(2, events.size()); @@ -188,10 +183,8 @@ void fragmentDetachedFromActive() { pauseSpan.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); assertEquals( fragment.getClass().getSimpleName(), - pauseSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, pauseSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(pauseSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + pauseSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(pauseSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = pauseSpan.getEvents(); assertEquals(2, events.size()); @@ -206,11 +199,8 @@ void fragmentDetachedFromActive() { destroyViewSpan.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); assertEquals( fragment.getClass().getSimpleName(), - destroyViewSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, - destroyViewSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(destroyViewSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + destroyViewSpan.getAttributes().get(SCREEN_NAME_KEY)); + assertNull(destroyViewSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); events = destroyViewSpan.getEvents(); assertEquals(1, events.size()); @@ -220,9 +210,7 @@ void fragmentDetachedFromActive() { assertEquals("Destroyed", detachSpan.getName()); assertNotNull(detachSpan.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, detachSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(detachSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertNull(detachSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); events = detachSpan.getEvents(); assertEquals(2, events.size()); @@ -246,13 +234,11 @@ void fragmentDestroyedFromStopped() { assertEquals("ViewDestroyed", span.getName()); assertEquals( - fragment.getClass().getSimpleName(), - span.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); + fragment.getClass().getSimpleName(), span.getAttributes().get(SCREEN_NAME_KEY)); assertEquals( fragment.getClass().getSimpleName(), span.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); - assertEquals(SplunkRum.COMPONENT_UI, span.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(span.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertNull(span.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = span.getEvents(); assertEquals(1, events.size()); @@ -276,14 +262,11 @@ void fragmentDetachedFromStopped() { assertEquals("ViewDestroyed", destroyViewSpan.getName()); assertEquals( fragment.getClass().getSimpleName(), - destroyViewSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); + destroyViewSpan.getAttributes().get(SCREEN_NAME_KEY)); assertEquals( fragment.getClass().getSimpleName(), destroyViewSpan.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, - destroyViewSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(destroyViewSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertNull(destroyViewSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = destroyViewSpan.getEvents(); assertEquals(1, events.size()); @@ -295,9 +278,7 @@ void fragmentDetachedFromStopped() { assertEquals( fragment.getClass().getSimpleName(), detachSpan.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, detachSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(detachSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertNull(detachSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); events = detachSpan.getEvents(); assertEquals(2, events.size()); @@ -322,13 +303,11 @@ void fragmentDetached() { assertEquals("Detached", detachSpan.getName()); assertEquals( fragment.getClass().getSimpleName(), - detachSpan.getAttributes().get(SplunkRum.SCREEN_NAME_KEY)); + detachSpan.getAttributes().get(SCREEN_NAME_KEY)); assertEquals( fragment.getClass().getSimpleName(), detachSpan.getAttributes().get(FragmentTracer.FRAGMENT_NAME_KEY)); - assertEquals( - SplunkRum.COMPONENT_UI, detachSpan.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertNull(detachSpan.getAttributes().get(SplunkRum.LAST_SCREEN_NAME_KEY)); + assertNull(detachSpan.getAttributes().get(LAST_SCREEN_NAME_KEY)); List events = detachSpan.getEvents(); assertEquals(1, events.size()); diff --git a/splunk-otel-android/src/test/java/com/splunk/rum/AppStartupTimerTest.java b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/startup/AppStartupTimerTest.java similarity index 90% rename from splunk-otel-android/src/test/java/com/splunk/rum/AppStartupTimerTest.java rename to splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/startup/AppStartupTimerTest.java index a133c4b7e..a6b8108d2 100644 --- a/splunk-otel-android/src/test/java/com/splunk/rum/AppStartupTimerTest.java +++ b/splunk-otel-android/src/test/java/io/opentelemetry/rum/internal/instrumentation/startup/AppStartupTimerTest.java @@ -14,8 +14,9 @@ * limitations under the License. */ -package com.splunk.rum; +package io.opentelemetry.rum.internal.instrumentation.startup; +import static io.opentelemetry.rum.internal.RumConstants.START_TYPE_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; @@ -50,10 +51,7 @@ void start_end() { SpanData spanData = spans.get(0); assertEquals("AppStart", spanData.getName()); - assertEquals( - SplunkRum.COMPONENT_APPSTART, - spanData.getAttributes().get(SplunkRum.COMPONENT_KEY)); - assertEquals("cold", spanData.getAttributes().get(SplunkRum.START_TYPE_KEY)); + assertEquals("cold", spanData.getAttributes().get(START_TYPE_KEY)); } @Test