├── .clomonitor.yml ├── .editorconfig ├── .fossa.yml ├── .github ├── CODEOWNERS ├── renovate.json5 ├── repository-settings.md ├── scripts │ ├── draft-change-log-entries.sh │ ├── generate-release-contributors.sh │ ├── generate-release-notes.sh │ ├── get-version.sh │ ├── markdown-link-check-config.json │ ├── markdown-link-check-with-retry.sh │ ├── update-version.sh │ └── use-cla-approved-github-bot.sh └── workflows │ ├── add-stale-label.yaml │ ├── build.yaml │ ├── codeql.yml │ ├── draft-change-log-entries.yaml │ ├── fossa.yml │ ├── gradle-wrapper-validation.yml │ ├── ossf-scorecard.yml │ ├── pr-check.yaml │ ├── prepare-release-branch.yml │ ├── release.yml │ ├── remove-needs-author-feedback.yaml │ ├── reusable-markdown-link-check.yml │ └── reusable-workflow-notification.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── RELEASING.md ├── VERSIONING.md ├── android-agent ├── build.gradle.kts └── src │ ├── main │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── agent │ │ ├── OpenTelemetryRumInitializer.kt │ │ ├── connectivity │ │ ├── EndpointConnectivity.kt │ │ └── HttpEndpointConnectivity.kt │ │ └── session │ │ ├── SessionConfig.kt │ │ ├── SessionIdGenerator.kt │ │ ├── SessionIdTimeoutHandler.kt │ │ ├── SessionManager.kt │ │ └── SessionStorage.kt │ └── test │ └── kotlin │ └── io │ └── opentelemetry │ └── android │ └── agent │ ├── OpenTelemetryRumInitializerTest.kt │ ├── connectivity │ └── HttpEndpointConnectivityTest.kt │ └── session │ ├── SessionIdTimeoutHandlerTest.kt │ └── SessionManagerTest.kt ├── animal-sniffer-signature └── build.gradle.kts ├── build.gradle.kts ├── buildSrc ├── build.gradle.kts ├── empty-rules.pro ├── settings.gradle.kts └── src │ └── main │ └── kotlin │ ├── otel.android-app-conventions.gradle.kts │ ├── otel.android-library-conventions.gradle.kts │ ├── otel.animalsniffer-conventions.gradle.kts │ ├── otel.errorprone-conventions.gradle.kts │ ├── otel.publish-conventions.gradle.kts │ └── otel.spotless-conventions.gradle.kts ├── code-of-conduct.md ├── common ├── build.gradle.kts ├── consumer-rules.pro └── src │ ├── main │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── common │ │ ├── RumConstants.java │ │ ├── RuntimeDetailsExtractor.java │ │ └── internal │ │ ├── features │ │ └── networkattributes │ │ │ ├── CurrentNetworkAttributesExtractor.java │ │ │ └── data │ │ │ ├── Carrier.kt │ │ │ ├── CurrentNetwork.java │ │ │ └── NetworkState.java │ │ └── tools │ │ └── time │ │ └── SystemTime.kt │ └── test │ └── java │ └── io │ └── opentelemetry │ └── android │ └── common │ ├── RuntimeDetailsExtractorTest.java │ └── internal │ └── features │ └── networkattributes │ └── CurrentNetworkAttributesExtractorTest.java ├── core ├── build.gradle.kts ├── consumer-rules.pro └── src │ ├── integrationTest │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── AgentInitTest.kt │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ ├── AndroidResource.java │ │ ├── GlobalAttributesSpanAppender.kt │ │ ├── NoopOpenTelemetryRum.java │ │ ├── OpenTelemetryRum.java │ │ ├── OpenTelemetryRumBuilder.java │ │ ├── OpenTelemetryRumImpl.java │ │ ├── ScreenAttributesSpanProcessor.kt │ │ ├── SdkPreconfiguredRumBuilder.kt │ │ ├── SessionIdRatioBasedSampler.java │ │ ├── SessionIdSpanAppender.kt │ │ ├── config │ │ └── OtelRumConfig.java │ │ ├── export │ │ ├── AttributeModifyingSpanExporter.java │ │ ├── BufferDelegatingLogExporter.kt │ │ ├── BufferDelegatingMetricExporter.kt │ │ ├── BufferDelegatingSpanExporter.kt │ │ ├── DelegatingExporter.kt │ │ ├── FilteringSpanExporter.java │ │ ├── FilteringSpanExporterBuilder.java │ │ ├── ModifiedSpanData.java │ │ └── SpanDataModifier.java │ │ ├── features │ │ └── diskbuffering │ │ │ ├── DiskBufferingConfig.kt │ │ │ ├── SignalFromDiskExporter.kt │ │ │ └── scheduler │ │ │ ├── DefaultExportScheduleHandler.kt │ │ │ ├── DefaultExportScheduler.kt │ │ │ └── ExportScheduleHandler.kt │ │ ├── internal │ │ ├── features │ │ │ ├── networkattrs │ │ │ │ ├── NetworkAttributesLogRecordAppender.kt │ │ │ │ └── NetworkAttributesSpanAppender.kt │ │ │ └── persistence │ │ │ │ ├── DiskManager.kt │ │ │ │ └── SimpleTemporaryFileProvider.kt │ │ ├── initialization │ │ │ └── InitializationEvents.kt │ │ └── processors │ │ │ ├── GlobalAttributesLogRecordAppender.kt │ │ │ ├── ScreenAttributesLogRecordProcessor.kt │ │ │ └── SessionIdLogRecordAppender.kt │ │ └── package-info.java │ └── test │ ├── java │ └── io │ │ └── opentelemetry │ │ └── android │ │ ├── AndroidResourceTest.java │ │ ├── GlobalAttributesSpanAppenderTest.kt │ │ ├── OpenTelemetryRumBuilderTest.java │ │ ├── ScreenAttributesSpanProcessorTest.kt │ │ ├── SessionIdRatioBasedSamplerTest.java │ │ ├── SessionIdSpanAppenderTest.kt │ │ ├── export │ │ ├── AttributeModifyingSpanExporterTest.java │ │ ├── BufferDelegatingLogExporterTest.kt │ │ ├── BufferDelegatingSpanExporterTest.kt │ │ ├── FilteringSpanExporterTest.java │ │ ├── ModifiedSpanDataTest.java │ │ ├── SpanDataModifierTest.java │ │ └── TestSpanHelper.java │ │ ├── features │ │ └── diskbuffering │ │ │ └── scheduler │ │ │ ├── DefaultExportScheduleHandlerTest.kt │ │ │ ├── DefaultExportSchedulerTest.kt │ │ │ └── SignalFromDiskExporterTest.kt │ │ └── internal │ │ ├── features │ │ ├── networkattrs │ │ │ └── NetworkAttributesSpanAppenderTest.kt │ │ └── persistence │ │ │ ├── DiskManagerTest.kt │ │ │ └── SimpleTemporaryFileProviderTest.kt │ │ ├── initialization │ │ ├── InitializationEventsTest.kt │ │ └── TestInitializationEvents.kt │ │ └── processors │ │ ├── GlobalAttributesLogRecordAppenderTest.kt │ │ ├── ScreenAttributesLogRecordProcessorTest.kt │ │ └── SessionIdLogRecordAppenderTest.kt │ └── resources │ └── META-INF │ └── services │ └── io.opentelemetry.android.internal.initialization.InitializationEvents ├── demo-app ├── README.md ├── build.gradle.kts ├── collector.yaml ├── compose.yaml ├── gradle.properties ├── gradle │ ├── libs.versions.toml │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle.kts └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── demo │ │ └── ExampleInstrumentedTest.kt │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── images │ │ ├── EclipsmartTravelRefractorTelescope.jpg │ │ ├── LensCleaningKit.jpg │ │ ├── NationalParkFoundationExplorascope.jpg │ │ ├── OpticalTubeAssembly.jpg │ │ ├── RedFlashlight.jpg │ │ ├── RoofBinoculars.jpg │ │ ├── SolarFilter.jpg │ │ ├── SolarSystemColorImager.jpg │ │ ├── StarsenseExplorer.jpg │ │ └── TheCometBook.jpg │ └── products.json │ ├── ic_cart-playstore.png │ ├── ic_launcher-playstore.png │ ├── java │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── demo │ │ ├── CenterText.kt │ │ ├── DemoViewModel.kt │ │ ├── LauncherButton.kt │ │ ├── MainActivity.kt │ │ ├── MainOtelButton.kt │ │ ├── OtelDemoApplication.kt │ │ ├── SessionId.kt │ │ ├── about │ │ ├── AboutActivity.kt │ │ ├── AboutOpenTelemetryFragment.kt │ │ ├── AppFeaturesFragment.kt │ │ ├── Feature.kt │ │ └── FeatureAdapter.kt │ │ ├── shop │ │ ├── clients │ │ │ ├── ImageLoader.kt │ │ │ ├── ProductCatalogClient.kt │ │ │ └── RecommendationService.kt │ │ ├── model │ │ │ └── Product.kt │ │ └── ui │ │ │ ├── AstronomyShopActivity.kt │ │ │ ├── Navigation.kt │ │ │ ├── cart │ │ │ ├── Cart.kt │ │ │ ├── CartViewModel.kt │ │ │ ├── CheckoutConfirmation.kt │ │ │ ├── CheckoutInfo.kt │ │ │ └── CheckoutInfoViewModel.kt │ │ │ ├── components │ │ │ ├── ConfirmCrashPopUp.kt │ │ │ ├── QuantityChooser.kt │ │ │ ├── SlowCometAnimation.kt │ │ │ └── UpPressButton.kt │ │ │ └── products │ │ │ ├── ProductCard.kt │ │ │ ├── ProductDetails.kt │ │ │ ├── ProductList.kt │ │ │ └── RecommendedSection.kt │ │ └── theme │ │ ├── Color.kt │ │ ├── Theme.kt │ │ └── Type.kt │ └── res │ ├── drawable │ ├── exit_to_main.xml │ ├── ic_arrow_drop_down.xml │ ├── ic_cart_background.xml │ ├── ic_cart_foreground.xml │ ├── ic_dashboard_black_24dp.xml │ ├── ic_home_black_24dp.xml │ ├── ic_launcher_background.xml │ ├── ic_launcher_foreground.xml │ ├── ic_notifications_black_24dp.xml │ └── otel_icon.png │ ├── font │ └── gotham_bold.ttf │ ├── layout │ ├── activity_about.xml │ ├── fragment_about_opentelemetry.xml │ ├── fragment_app_features.xml │ ├── fragment_notifications.xml │ └── item_feature.xml │ ├── menu │ └── bottom_nav_menu.xml │ ├── mipmap-anydpi-v26 │ ├── ic_cart.xml │ ├── ic_cart_round.xml │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_cart.webp │ ├── ic_cart_round.webp │ ├── ic_launcher.webp │ ├── ic_launcher_foreground.webp │ └── ic_launcher_round.webp │ ├── mipmap-mdpi │ ├── ic_cart.webp │ ├── ic_cart_round.webp │ ├── ic_launcher.webp │ ├── ic_launcher_foreground.webp │ └── ic_launcher_round.webp │ ├── mipmap-xhdpi │ ├── ic_cart.webp │ ├── ic_cart_round.webp │ ├── ic_launcher.webp │ ├── ic_launcher_foreground.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxhdpi │ ├── ic_cart.webp │ ├── ic_cart_round.webp │ ├── ic_launcher.webp │ ├── ic_launcher_foreground.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxxhdpi │ ├── ic_cart.webp │ ├── ic_cart_round.webp │ ├── ic_launcher.webp │ ├── ic_launcher_foreground.webp │ └── ic_launcher_round.webp │ ├── values │ ├── colors.xml │ ├── dimens.xml │ ├── ic_launcher_background.xml │ ├── strings.xml │ └── themes.xml │ └── xml │ ├── backup_rules.xml │ ├── data_extraction_rules.xml │ └── network_security_config.xml ├── gradle.properties ├── gradle ├── libs.versions.toml ├── spotless.license.java └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── instrumentation ├── activity │ ├── README.md │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ └── activity │ │ │ ├── ActivityCallbacks.kt │ │ │ ├── ActivityLifecycleInstrumentation.kt │ │ │ ├── ActivityTracer.java │ │ │ ├── ActivityTracerCache.java │ │ │ ├── Pre29ActivityCallbacks.java │ │ │ └── startup │ │ │ ├── AnchoredClock.java │ │ │ └── AppStartupTimer.java │ │ └── test │ │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── activity │ │ ├── ActivityCallbackTestHarness.java │ │ ├── ActivityCallbacksTest.java │ │ ├── ActivityLifecycleInstrumentationTest.kt │ │ ├── ActivityTracerCacheTest.java │ │ ├── ActivityTracerTest.java │ │ ├── Pre29ActivityCallbackTestHarness.java │ │ ├── Pre29ActivityLifecycleCallbacksTest.java │ │ └── startup │ │ └── AppStartupTimerTest.java ├── android-instrumentation │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ ├── AndroidInstrumentation.kt │ │ │ ├── AndroidInstrumentationLoader.kt │ │ │ ├── InstallationContext.kt │ │ │ └── internal │ │ │ └── AndroidInstrumentationLoaderImpl.kt │ │ └── test │ │ ├── java │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ ├── AndroidInstrumentationLoaderTest.kt │ │ │ ├── TestAndroidInstrumentation.kt │ │ │ └── internal │ │ │ └── AndroidInstrumentationLoaderImplTest.kt │ │ └── resources │ │ └── META-INF │ │ └── services │ │ └── io.opentelemetry.android.instrumentation.AndroidInstrumentation ├── android-log │ ├── README.md │ ├── agent │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── io │ │ │ │ └── opentelemetry │ │ │ │ └── instrumentation │ │ │ │ └── agent │ │ │ │ └── log │ │ │ │ └── AndroidLogPlugin.java │ │ │ └── resources │ │ │ └── META-INF │ │ │ └── net.bytebuddy │ │ │ └── build.plugins │ ├── library │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── io │ │ │ │ └── opentelemetry │ │ │ │ └── instrumentation │ │ │ │ └── library │ │ │ │ └── log │ │ │ │ ├── AndroidLogInstrumentation.java │ │ │ │ └── AndroidLogSubstitutions.java │ │ │ └── kotlin │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── instrumentation │ │ │ └── library │ │ │ └── log │ │ │ └── internal │ │ │ └── LogRecordBuilderCreator.kt │ └── testing │ │ ├── build.gradle.kts │ │ └── src │ │ ├── androidTest │ │ └── kotlin │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── instrumentation │ │ │ └── library │ │ │ └── log │ │ │ └── testing │ │ │ └── InstrumentationTest.kt │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── instrumentation │ │ └── library │ │ └── log │ │ └── LoggingTestUtil.kt ├── anr │ ├── README.md │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ └── anr │ │ │ ├── AnrDetector.java │ │ │ ├── AnrDetectorToggler.java │ │ │ ├── AnrInstrumentation.java │ │ │ ├── AnrWatcher.kt │ │ │ └── StackTraceFormatter.java │ │ └── test │ │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── anr │ │ ├── AnrDetectorTest.java │ │ ├── AnrDetectorTogglerTest.java │ │ ├── AnrWatcherTest.kt │ │ └── StackTraceFormatterTest.java ├── common-api │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ ├── annotations │ │ │ └── RumScreenName.java │ │ │ └── common │ │ │ ├── ActiveSpan.java │ │ │ ├── Constants.kt │ │ │ └── ScreenNameExtractor.java │ │ └── test │ │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── common │ │ └── ScreenNameExtractorTest.kt ├── crash │ ├── README.md │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ └── crash │ │ │ ├── CrashDetails.java │ │ │ ├── CrashReporter.java │ │ │ ├── CrashReporterInstrumentation.java │ │ │ └── CrashReportingExceptionHandler.java │ │ └── test │ │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── crash │ │ ├── CrashReporterTest.java │ │ └── CrashReportingExceptionHandlerTest.java ├── fragment │ ├── README.md │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ └── fragment │ │ │ ├── FragmentLifecycleInstrumentation.kt │ │ │ ├── FragmentTracer.java │ │ │ └── RumFragmentLifecycleCallbacks.java │ │ └── test │ │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── fragment │ │ ├── FragmentCallbackTestHarness.java │ │ ├── FragmentTracerTest.java │ │ └── RumFragmentLifecycleCallbacksTest.java ├── httpurlconnection │ ├── README.md │ ├── agent │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── io │ │ │ │ └── opentelemetry │ │ │ │ └── instrumentation │ │ │ │ └── agent │ │ │ │ └── httpurlconnection │ │ │ │ └── HttpUrlConnectionPlugin.java │ │ │ └── resources │ │ │ └── META-INF │ │ │ └── net.bytebuddy │ │ │ └── build.plugins │ ├── library │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── instrumentation │ │ │ └── library │ │ │ └── httpurlconnection │ │ │ ├── HttpUrlInstrumentation.java │ │ │ ├── HttpUrlReplacements.java │ │ │ ├── internal │ │ │ ├── HttpUrlConnectionSingletons.java │ │ │ ├── HttpUrlHttpAttributesGetter.java │ │ │ └── RequestPropertySetter.java │ │ │ └── package-info.java │ └── testing │ │ ├── build.gradle.kts │ │ └── src │ │ ├── androidTest │ │ └── kotlin │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── instrumentation │ │ │ └── library │ │ │ └── httpurlconnection │ │ │ └── InstrumentationTest.kt │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── instrumentation │ │ └── library │ │ └── httpurlconnection │ │ └── HttpUrlConnectionTestUtil.kt ├── network │ ├── README.md │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ ├── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ └── network │ │ │ ├── NetworkApplicationListener.kt │ │ │ ├── NetworkChangeAttributesExtractor.kt │ │ │ └── NetworkChangeInstrumentation.kt │ │ └── test │ │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── network │ │ └── NetworkChangeInstrumentationTest.kt ├── okhttp3-websocket │ ├── agent │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── io │ │ │ │ └── opentelemetry │ │ │ │ └── instrumentation │ │ │ │ └── agent │ │ │ │ └── okhttp │ │ │ │ └── v3_0 │ │ │ │ └── websocket │ │ │ │ ├── OkHttpClientWebsocketAdvice.java │ │ │ │ └── OkHttpClientWebsocketPlugin.java │ │ │ └── resources │ │ │ └── META-INF │ │ │ └── net.bytebuddy │ │ │ └── build.plugins │ ├── library │ │ ├── build.gradle.kts │ │ ├── consumer-rules.pro │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── instrumentation │ │ │ └── library │ │ │ └── okhttp │ │ │ └── v3_0 │ │ │ └── websocket │ │ │ └── internal │ │ │ ├── OkHttpWebsocketInstrumentation.java │ │ │ ├── WebsocketAttributeExtractor.java │ │ │ ├── WebsocketAttributes.java │ │ │ ├── WebsocketEventGenerator.java │ │ │ └── WebsocketListenerWrapper.java │ └── testing │ │ ├── build.gradle.kts │ │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── instrumentation │ │ │ └── library │ │ │ └── okhttp │ │ │ └── websocket │ │ │ └── v3_0 │ │ │ └── InstrumentationTest.java │ │ └── main │ │ └── AndroidManifest.xml ├── okhttp3 │ ├── README.md │ ├── agent │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── io │ │ │ │ └── opentelemetry │ │ │ │ └── instrumentation │ │ │ │ └── agent │ │ │ │ └── okhttp │ │ │ │ └── v3_0 │ │ │ │ ├── OkHttpClientAdvice.java │ │ │ │ ├── OkHttpClientPlugin.java │ │ │ │ └── callback │ │ │ │ ├── OkHttpCallbackAdvice.java │ │ │ │ └── OkHttpCallbackPlugin.java │ │ │ └── resources │ │ │ └── META-INF │ │ │ └── net.bytebuddy │ │ │ └── build.plugins │ ├── library │ │ ├── build.gradle.kts │ │ ├── consumer-rules.pro │ │ └── src │ │ │ ├── main │ │ │ └── java │ │ │ │ └── io │ │ │ │ └── opentelemetry │ │ │ │ └── instrumentation │ │ │ │ └── library │ │ │ │ └── okhttp │ │ │ │ └── v3_0 │ │ │ │ ├── OkHttpInstrumentation.java │ │ │ │ ├── internal │ │ │ │ ├── OkHttp3Singletons.java │ │ │ │ ├── OkHttpCallbackAdviceHelper.java │ │ │ │ └── TracingCallback.java │ │ │ │ └── package-info.java │ │ │ └── test │ │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── instrumentation │ │ │ └── library │ │ │ └── okhttp │ │ │ └── v3_0 │ │ │ └── OkHttpInstrumentationTest.java │ └── testing │ │ ├── build.gradle.kts │ │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── instrumentation │ │ │ └── library │ │ │ └── okhttp │ │ │ └── v3_0 │ │ │ └── InstrumentationTest.java │ │ └── main │ │ └── AndroidManifest.xml ├── sessions │ ├── README.md │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ └── main │ │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── sessions │ │ ├── SessionIdEventSender.kt │ │ └── SessionInstrumentation.kt ├── slowrendering │ ├── README.md │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ └── slowrendering │ │ │ ├── SlowRenderListener.java │ │ │ └── SlowRenderingInstrumentation.java │ │ └── test │ │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── slowrendering │ │ ├── SlowRenderListenerTest.java │ │ └── SlowRenderingInstrumentationTest.kt ├── startup │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ └── startup │ │ │ ├── SdkInitializationEvents.kt │ │ │ └── StartupInstrumentation.kt │ │ └── test │ │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── startup │ │ ├── SdkInitializationEventsTest.kt │ │ └── StartupInstrumentationTest.kt ├── view-click │ ├── README.md │ ├── build.gradle.kts │ ├── consumer-rules.pro │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── android │ │ │ └── instrumentation │ │ │ └── view │ │ │ └── click │ │ │ ├── ViewClickActivityCallback.kt │ │ │ ├── ViewClickEventGenerator.kt │ │ │ ├── ViewClickInstrumentation.kt │ │ │ ├── WindowCallbackWrapper.kt │ │ │ └── internal │ │ │ └── ViewUtils.kt │ │ └── test │ │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── view │ │ └── click │ │ └── ViewClickInstrumentationTest.kt └── volley │ ├── .gitignore │ ├── README.md │ └── library │ ├── build.gradle.kts │ └── src │ ├── main │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── instrumentation │ │ └── volley │ │ ├── ClientRequestHeaderSetter.java │ │ ├── RequestWrapper.java │ │ ├── TracingHurlStack.java │ │ ├── VolleyHttpClientAttributesGetter.java │ │ ├── VolleyResponseAttributesExtractor.java │ │ ├── VolleyTracing.java │ │ └── VolleyTracingBuilder.java │ └── test │ └── java │ └── io │ └── opentelemetry │ └── android │ └── instrumentation │ └── volley │ ├── StuckTestHelper.java │ ├── TestRequestQueue.java │ ├── TracingHurlStackExceptionTest.java │ ├── TracingHurlStackTest.java │ ├── VolleyHttpClientAttributesGetterTest.java │ └── VolleyResponseAttributesExtractorTest.java ├── opentelemetry-android-bom └── build.gradle.kts ├── services ├── build.gradle.kts ├── consumer-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── io │ │ └── opentelemetry │ │ └── android │ │ └── internal │ │ └── services │ │ ├── CacheStorage.java │ │ ├── Preferences.kt │ │ ├── Services.kt │ │ ├── applifecycle │ │ ├── AppLifecycle.kt │ │ ├── ApplicationStateListener.java │ │ └── ApplicationStateWatcher.kt │ │ ├── network │ │ ├── CarrierFinder.java │ │ ├── CurrentNetworkProvider.java │ │ ├── NetworkChangeListener.java │ │ └── detector │ │ │ ├── NetworkDetector.kt │ │ │ ├── PostApi28NetworkDetector.kt │ │ │ └── SimpleNetworkDetector.kt │ │ ├── periodicwork │ │ ├── PeriodicRunnable.kt │ │ └── PeriodicWork.kt │ │ └── visiblescreen │ │ ├── VisibleScreenTracker.kt │ │ ├── activities │ │ ├── DefaultingActivityLifecycleCallbacks.kt │ │ ├── Pre29VisibleScreenLifecycleBinding.kt │ │ └── VisibleScreenLifecycleBinding.kt │ │ └── fragments │ │ ├── RumFragmentActivityRegisterer.java │ │ └── VisibleFragmentTracker.kt │ └── test │ └── java │ └── io │ └── opentelemetry │ └── android │ └── internal │ └── services │ ├── ServicesTest.kt │ ├── applifecycle │ ├── AppLifecycleTest.kt │ └── ApplicationStateWatcherTest.java │ ├── network │ ├── CarrierFinderTest.java │ ├── CurrentNetworkProviderTest.kt │ └── detector │ │ ├── NetworkDetectorTest.java │ │ ├── PostApi28NetworkDetectorTest.java │ │ └── SimpleNetworkDetectorTest.java │ ├── periodicwork │ ├── PeriodicRunnableTest.kt │ └── PeriodicWorkTest.kt │ └── visiblescreen │ ├── VisibleScreenTrackerTest.java │ ├── activities │ ├── Pre29VisibleScreenLifecycleBindingTest.java │ └── VisibleScreenLifecycleBindingTest.java │ └── fragments │ ├── RumFragmentActivityRegistererTest.java │ └── VisibleFragmentTrackerTest.kt ├── session ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── io │ └── opentelemetry │ └── android │ └── session │ ├── Session.kt │ ├── SessionObserver.kt │ ├── SessionProvider.kt │ └── SessionPublisher.kt ├── settings.gradle.kts └── test-common ├── build.gradle.kts └── src └── main └── kotlin └── io └── opentelemetry └── android └── test └── common ├── AssertionExtensions.kt └── OpenTelemetryRumRule.kt /.clomonitor.yml: -------------------------------------------------------------------------------- 1 | # see https://github.com/cncf/clomonitor/blob/main/docs/checks.md#exemptions 2 | exemptions: 3 | - check: artifacthub_badge 4 | reason: "Artifact Hub doesn't support Android packages" 5 | - check: openssf_badge 6 | reason: "ETOOMANYBADGES, but the work has been done: https://www.bestpractices.dev/projects/10007" 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{kt,kts}] 2 | ktlint_function_naming_ignore_when_annotated_with=Composable 3 | -------------------------------------------------------------------------------- /.fossa.yml: -------------------------------------------------------------------------------- 1 | version: 3 2 | 3 | targets: 4 | only: 5 | - type: gradle 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code owners file. 2 | # This file controls who is tagged for review for any given pull request. 3 | 4 | # For anything not explicitly taken by someone else: 5 | * @open-telemetry/android-approvers 6 | -------------------------------------------------------------------------------- /.github/scripts/draft-change-log-entries.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | version=$("$(dirname "$0")/get-version.sh") 4 | 5 | if [[ $version =~ ([0-9]+)\.([0-9]+)\.0 ]]; then 6 | major="${BASH_REMATCH[1]}" 7 | minor="${BASH_REMATCH[2]}" 8 | else 9 | echo "unexpected version: $version" 10 | exit 1 11 | fi 12 | 13 | if [[ $minor == 0 ]]; then 14 | prior_major=$((major - 1)) 15 | prior_minor=$(sed -n "s/^## Version $prior_major\.\([0-9]\+\)\..*/\1/p" CHANGELOG.md | head -1) 16 | if [[ -z $prior_minor ]]; then 17 | # assuming this is the first release 18 | range= 19 | else 20 | range="v$prior_major.$prior_minor.0..HEAD" 21 | fi 22 | else 23 | range="v$major.$((minor - 1)).0..HEAD" 24 | fi 25 | 26 | echo "## Unreleased" 27 | echo 28 | echo "### Migration notes" 29 | echo 30 | echo 31 | echo "### 🌟 New instrumentation" 32 | echo 33 | echo 34 | echo "### 📈 Enhancements" 35 | echo 36 | echo 37 | echo "### 🛠️ Bug fixes" 38 | echo 39 | echo 40 | echo "### 🧰 Tooling" 41 | echo 42 | 43 | git log --reverse \ 44 | --perl-regexp \ 45 | --author='^(?!renovate\[bot\] )' \ 46 | --pretty=format:"- %s" \ 47 | "$range" \ 48 | | sed -E 's,\(#([0-9]+)\)$,\n ([#\1](https://github.com/open-telemetry/opentelemetry-android/pull/\1)),' -------------------------------------------------------------------------------- /.github/scripts/generate-release-notes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Generates release notes, like what appears in GitHub release pages. 4 | 5 | VERSION=$1 6 | PRIOR_VERSION=$2 7 | INST_VER=$3 8 | SDK_VER=$4 9 | 10 | cat > /tmp/release-notes.txt << EOF 11 | This release is based on OpenTelemetry Java Instrumentation $INST_VER and 12 | the OpenTelemetry Java Core (sdk/api/exporters) $SDK_VER. 13 | 14 | Note that many artifacts have the \`-alpha\` suffix attached to their version number, reflecting 15 | that they are still alpha quality and will continue to have breaking changes. Please see the 16 | [VERSIONING.md](https://github.com/open-telemetry/opentelemetry-android/blob/main/VERSIONING.md#opentelemetry-android-versioning) for more details. 17 | 18 | EOF 19 | 20 | sed -n "0,/^## Version $VERSION /d;/^## Version /q;p" CHANGELOG.md > /tmp/CHANGELOG_SECTION.md 21 | 22 | # the complex perl regex is needed because markdown docs render newlines as soft wraps 23 | # while release notes render them as line breaks 24 | perl -0pe 's/(?> /tmp/release-notes.txt 26 | 27 | cat >> /tmp/release-notes.txt << EOF 28 | ### 🙇 Thank you 29 | 30 | This release was possible thanks to the following contributors: 31 | 32 | EOF 33 | 34 | .github/scripts/generate-release-contributors.sh "v${PRIOR_VERSION}" >> /tmp/release-notes.txt 35 | -------------------------------------------------------------------------------- /.github/scripts/get-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | grep -Po "version=\K[0=9]+.[0-9]+.[0-9]+" gradle.properties 4 | -------------------------------------------------------------------------------- /.github/scripts/markdown-link-check-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "retryOn429": true, 3 | "aliveStatusCodes": [ 4 | 200, 5 | 403 6 | ], 7 | "ignorePatterns": [ 8 | { 9 | "pattern": "^http://localhost:16686$" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /.github/scripts/markdown-link-check-with-retry.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # this script helps to reduce sporadic link check failures by retrying at a file-by-file level 4 | 5 | retry_count=3 6 | 7 | for file in "$@"; do 8 | for i in $(seq 1 $retry_count); do 9 | if markdown-link-check --config "$(dirname "$0")/markdown-link-check-config.json" \ 10 | "$file"; then 11 | break 12 | elif [[ $i -eq $retry_count ]]; then 13 | exit 1 14 | fi 15 | sleep 5 16 | done 17 | done -------------------------------------------------------------------------------- /.github/scripts/update-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | version=$1 4 | alpha_version=${version}-alpha 5 | 6 | sed -Ei "s/version=.*/version=$version/" gradle.properties 7 | 8 | -------------------------------------------------------------------------------- /.github/scripts/use-cla-approved-github-bot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | git config user.name opentelemetrybot 4 | git config user.email 107717825+opentelemetrybot@users.noreply.github.com 5 | -------------------------------------------------------------------------------- /.github/workflows/add-stale-label.yaml: -------------------------------------------------------------------------------- 1 | name: Issue management - run stale action 2 | 3 | on: 4 | schedule: 5 | # every 8 hours at 41 past 6 | - cron: "41 */8 * * *" 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | stale: 13 | permissions: 14 | issues: write # for actions/stale to close stale issues 15 | pull-requests: write # for actions/stale to close stale PRs 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 19 | with: 20 | repo-token: ${{ secrets.GITHUB_TOKEN }} 21 | days-before-stale: 21 22 | days-before-close: 14 23 | only-labels: "needs author feedback" 24 | stale-issue-label: stale 25 | stale-issue-message: > 26 | This has been automatically marked as stale because it has been marked 27 | as needing author feedback and has not had any activity for 21 days. 28 | It will be closed automatically if there is no response from the author 29 | within 14 additional days from this comment. 30 | stale-pr-label: stale 31 | stale-pr-message: > 32 | This has been automatically marked as stale because it has been marked 33 | as needing author feedback and has not had any activity for 21 days. 34 | It will be closed automatically if there is no response from the author 35 | within 14 additional days from this comment. -------------------------------------------------------------------------------- /.github/workflows/draft-change-log-entries.yaml: -------------------------------------------------------------------------------- 1 | name: Draft CHANGELOG entries for a release 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | permissions: 7 | contents: read 8 | 9 | jobs: 10 | create_draft: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 14 | with: 15 | fetch-depth: 0 16 | - name: Run changelog draft script 17 | run: ./.github/scripts/draft-change-log-entries.sh 18 | -------------------------------------------------------------------------------- /.github/workflows/fossa.yml: -------------------------------------------------------------------------------- 1 | name: FOSSA 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | fossa: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 16 | 17 | - uses: fossas/fossa-action@3ebcea1862c6ffbd5cf1b4d0bd6b3fe7bd6f2cac # v1.7.0 18 | with: 19 | api-key: ${{secrets.FOSSA_API_KEY}} 20 | team: OpenTelemetry 21 | -------------------------------------------------------------------------------- /.github/workflows/gradle-wrapper-validation.yml: -------------------------------------------------------------------------------- 1 | name: Gradle wrapper validation 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | gradle-wrapper-validation: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 15 | 16 | - uses: gradle/actions/wrapper-validation@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0 17 | -------------------------------------------------------------------------------- /.github/workflows/pr-check.yaml: -------------------------------------------------------------------------------- 1 | name: PR build 2 | 3 | on: pull_request 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | pr-checks: 10 | name: "pr-checks" 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 14 | - name: Set up JDK for running Gradle 15 | uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 16 | with: 17 | distribution: temurin 18 | java-version: 17 19 | - name: touch local props 20 | run: touch demo-app/local.properties 21 | - name: run gradle 22 | run: ./gradlew check 23 | - name: build demo app 24 | working-directory: ./demo-app 25 | run: ./gradlew check assemble 26 | 27 | required-status-check: 28 | needs: 29 | - pr-checks 30 | runs-on: ubuntu-latest 31 | if: always() 32 | steps: 33 | - if: | 34 | needs.pr-checks.result != 'success' 35 | run: exit 1 -------------------------------------------------------------------------------- /.github/workflows/remove-needs-author-feedback.yaml: -------------------------------------------------------------------------------- 1 | name: Issue management - remove labels as needed 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | issue_comment: 12 | permissions: 13 | contents: read 14 | issues: write 15 | if: > 16 | contains(github.event.issue.labels.*.name, 'needs author feedback') && 17 | github.event.comment.user.login == github.event.issue.user.login 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 21 | 22 | - name: Remove labels 23 | env: 24 | ISSUE_NUMBER: ${{ github.event.issue.number }} 25 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | run: | 27 | gh issue edit --remove-label "needs author feedback" $ISSUE_NUMBER 28 | gh issue edit --remove-label "stale" $ISSUE_NUMBER -------------------------------------------------------------------------------- /.github/workflows/reusable-markdown-link-check.yml: -------------------------------------------------------------------------------- 1 | name: Reusable - Markdown link check 2 | 3 | on: 4 | workflow_call: 5 | 6 | permissions: 7 | contents: read 8 | 9 | jobs: 10 | markdown-link-check: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 14 | 15 | - name: Install markdown-link-check 16 | # https://github.com/tcort/markdown-link-check/issues/297 17 | run: npm install -g markdown-link-check@3.11.2 18 | 19 | - name: Run markdown-link-check 20 | run: | 21 | find . -type f \ 22 | -name '*.md' \ 23 | -not -path './CHANGELOG.md' \ 24 | | xargs .github/scripts/markdown-link-check-with-retry.sh -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .gradle 3 | /local.properties 4 | demo-app/local.properties 5 | .DS_Store 6 | **/build/ 7 | -------------------------------------------------------------------------------- /android-agent/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("otel.android-library-conventions") 3 | id("otel.publish-conventions") 4 | } 5 | 6 | android { 7 | namespace = "io.opentelemetry.android.agent" 8 | } 9 | 10 | dependencies { 11 | api(project(":core")) 12 | implementation(project(":common")) 13 | implementation(project(":session")) 14 | implementation(project(":services")) 15 | implementation(libs.opentelemetry.instrumentation.api) 16 | implementation(libs.opentelemetry.exporter.otlp) 17 | 18 | // Default instrumentations: 19 | api(project(":instrumentation:activity")) 20 | api(project(":instrumentation:anr")) 21 | api(project(":instrumentation:crash")) 22 | api(project(":instrumentation:fragment")) 23 | api(project(":instrumentation:network")) 24 | api(project(":instrumentation:slowrendering")) 25 | api(project(":instrumentation:startup")) 26 | 27 | testImplementation(libs.robolectric) 28 | } 29 | 30 | extra["pomName"] = "OpenTelemetry Android Agent" 31 | description = 32 | "A library that contains all the commonly needed instrumentation for Android apps in a " + 33 | "convenient way with minimum configuration needed." 34 | -------------------------------------------------------------------------------- /android-agent/src/main/kotlin/io/opentelemetry/android/agent/connectivity/EndpointConnectivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.agent.connectivity 7 | 8 | interface EndpointConnectivity { 9 | fun getUrl(): String 10 | 11 | fun getHeaders(): Map 12 | } 13 | -------------------------------------------------------------------------------- /android-agent/src/main/kotlin/io/opentelemetry/android/agent/connectivity/HttpEndpointConnectivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.agent.connectivity 7 | 8 | class HttpEndpointConnectivity private constructor( 9 | private val url: String, 10 | private val headers: Map, 11 | ) : EndpointConnectivity { 12 | companion object { 13 | fun forTraces( 14 | baseUrl: String, 15 | headers: Map = emptyMap(), 16 | ): HttpEndpointConnectivity = HttpEndpointConnectivity(baseUrl.trimEnd('/') + "/v1/traces", headers) 17 | 18 | fun forLogs( 19 | baseUrl: String, 20 | headers: Map = emptyMap(), 21 | ): HttpEndpointConnectivity = HttpEndpointConnectivity(baseUrl.trimEnd('/') + "/v1/logs", headers) 22 | 23 | fun forMetrics( 24 | baseUrl: String, 25 | headers: Map = emptyMap(), 26 | ): HttpEndpointConnectivity = HttpEndpointConnectivity(baseUrl.trimEnd('/') + "/v1/metrics", headers) 27 | } 28 | 29 | override fun getUrl(): String = url 30 | 31 | override fun getHeaders(): Map = headers 32 | } 33 | -------------------------------------------------------------------------------- /android-agent/src/main/kotlin/io/opentelemetry/android/agent/session/SessionConfig.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.agent.session 7 | 8 | import kotlin.time.Duration 9 | import kotlin.time.Duration.Companion.hours 10 | import kotlin.time.Duration.Companion.minutes 11 | 12 | data class SessionConfig( 13 | val backgroundInactivityTimeout: Duration = 15.minutes, 14 | val maxLifetime: Duration = 4.hours, 15 | ) { 16 | companion object { 17 | @JvmStatic 18 | fun withDefaults(): SessionConfig = SessionConfig() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /android-agent/src/main/kotlin/io/opentelemetry/android/agent/session/SessionIdGenerator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.agent.session 7 | 8 | import io.opentelemetry.api.trace.TraceId 9 | import java.util.Random 10 | 11 | interface SessionIdGenerator { 12 | fun generateSessionId(): String 13 | 14 | object DEFAULT : SessionIdGenerator { 15 | override fun generateSessionId(): String { 16 | val random = Random() 17 | // The OTel TraceId has exactly the same format as a RUM SessionId, so let's re-use it here, 18 | // rather than re-inventing the wheel. 19 | return TraceId.fromLongs(random.nextLong(), random.nextLong()) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /android-agent/src/main/kotlin/io/opentelemetry/android/agent/session/SessionStorage.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.agent.session 7 | 8 | import io.opentelemetry.android.session.Session 9 | 10 | interface SessionStorage { 11 | fun get(): Session 12 | 13 | fun save(newSession: Session) 14 | 15 | class InMemory( 16 | @Volatile var session: Session = Session.NONE, 17 | ) : SessionStorage { 18 | override fun get(): Session = session 19 | 20 | override fun save(newSession: Session) { 21 | this.session = newSession 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /android-agent/src/test/kotlin/io/opentelemetry/android/agent/connectivity/HttpEndpointConnectivityTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.agent.connectivity 7 | 8 | import org.assertj.core.api.Assertions.assertThat 9 | import org.junit.Test 10 | 11 | class HttpEndpointConnectivityTest { 12 | @Test 13 | fun `Validate exporter endpoint configuration`() { 14 | val headers = mapOf("Authorization" to "Basic something") 15 | val tracesConnectivity = HttpEndpointConnectivity.forTraces("http://some.endpoint", headers) 16 | val logsConnectivity = HttpEndpointConnectivity.forLogs("http://some.endpoint/", headers) 17 | val metricsConnectivity = 18 | HttpEndpointConnectivity.forMetrics("http://some.endpoint", headers) 19 | 20 | assertThat(tracesConnectivity.getUrl()).isEqualTo("http://some.endpoint/v1/traces") 21 | assertThat(tracesConnectivity.getHeaders()).isEqualTo(headers) 22 | assertThat(logsConnectivity.getUrl()).isEqualTo("http://some.endpoint/v1/logs") 23 | assertThat(logsConnectivity.getHeaders()).isEqualTo(headers) 24 | assertThat(metricsConnectivity.getUrl()).isEqualTo("http://some.endpoint/v1/metrics") 25 | assertThat(metricsConnectivity.getHeaders()).isEqualTo(headers) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.KotlinVersion 2 | 3 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 4 | buildscript { 5 | repositories { 6 | google() 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath(libs.android.plugin) 11 | classpath(libs.byteBuddy.plugin) 12 | } 13 | } 14 | 15 | plugins { 16 | id("otel.spotless-conventions") 17 | alias(libs.plugins.publishPlugin) 18 | } 19 | 20 | extra["java_version"] = JavaVersion.VERSION_1_8 21 | extra["kotlin_min_supported_version"] = KotlinVersion.KOTLIN_1_8 22 | 23 | allprojects { 24 | repositories { 25 | google() 26 | mavenCentral() 27 | } 28 | if (findProperty("final") != "true") { 29 | version = "$version-SNAPSHOT" 30 | } 31 | } 32 | 33 | subprojects { 34 | apply(plugin = "otel.spotless-conventions") 35 | } 36 | 37 | nexusPublishing { 38 | repositories { 39 | // see https://central.sonatype.org/publish/publish-portal-ossrh-staging-api/#configuration 40 | sonatype { 41 | nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/")) 42 | snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/")) 43 | username.set(System.getenv("SONATYPE_USER")) 44 | password.set(System.getenv("SONATYPE_KEY")) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | alias(libs.plugins.spotless) 4 | } 5 | 6 | spotless { 7 | kotlinGradle { 8 | ktlint() 9 | target("* * / *.gradle.kts") 10 | } 11 | } 12 | 13 | repositories { 14 | mavenCentral() 15 | google() 16 | gradlePluginPortal() 17 | } 18 | 19 | dependencies { 20 | implementation(libs.android.plugin) 21 | implementation(libs.spotless.plugin) 22 | implementation(libs.errorprone.plugin) 23 | implementation(libs.nullaway.plugin) 24 | implementation(libs.animalsniffer.plugin) 25 | implementation(libs.kotlin.plugin) 26 | } 27 | -------------------------------------------------------------------------------- /buildSrc/empty-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/buildSrc/empty-rules.pro -------------------------------------------------------------------------------- /buildSrc/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | versionCatalogs { 3 | create("libs") { 4 | from(files("../gradle/libs.versions.toml")) 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/otel.animalsniffer-conventions.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.util.Locale 2 | import ru.vyarus.gradle.plugin.animalsniffer.AnimalSniffer 3 | 4 | plugins { 5 | id("com.android.library") 6 | id("ru.vyarus.animalsniffer") 7 | } 8 | 9 | dependencies { 10 | signature(project(path = ":animal-sniffer-signature", configuration = "generatedSignature")) 11 | } 12 | 13 | val capitalizedVariantNames = mutableListOf() 14 | androidComponents.onVariants { variant -> 15 | val capitalizedName = 16 | variant.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } 17 | capitalizedVariantNames.add(capitalizedName) 18 | } 19 | 20 | afterEvaluate { 21 | capitalizedVariantNames.forEach { capitalizedName -> 22 | tasks.named("pre${capitalizedName}Build").configure { 23 | finalizedBy("animalsniffer$capitalizedName") 24 | } 25 | } 26 | } 27 | 28 | // Any class, method or field annotated with this annotation will be ignored by animal sniffer. 29 | animalsniffer.annotation = "androidx.annotation.RequiresApi" 30 | 31 | tasks.withType { 32 | // always having declared output makes this task properly participate in tasks up-to-date checks 33 | reports.text.required.set(true) 34 | } 35 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # OpenTelemetry Community Code of Conduct 2 | 3 | Please refer to our [OpenTelemetry Community Code of Conduct](https://github.com/open-telemetry/community/blob/main/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("otel.android-library-conventions") 3 | id("otel.publish-conventions") 4 | } 5 | 6 | description = "OpenTelemetry android common utils" 7 | 8 | android { 9 | namespace = "io.opentelemetry.android.common" 10 | 11 | defaultConfig { 12 | consumerProguardFiles("consumer-rules.pro") 13 | } 14 | } 15 | 16 | dependencies { 17 | api(platform(libs.opentelemetry.platform.alpha)) 18 | api(libs.opentelemetry.api) 19 | implementation(libs.opentelemetry.sdk) 20 | implementation(libs.opentelemetry.instrumentation.api) 21 | implementation(libs.opentelemetry.semconv.incubating) 22 | implementation(libs.androidx.core) 23 | 24 | testImplementation(libs.robolectric) 25 | } 26 | -------------------------------------------------------------------------------- /common/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/common/consumer-rules.pro -------------------------------------------------------------------------------- /common/src/main/java/io/opentelemetry/android/common/internal/features/networkattributes/data/Carrier.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.common.internal.features.networkattributes.data 7 | 8 | import android.os.Build 9 | import android.telephony.TelephonyManager 10 | import androidx.annotation.RequiresApi 11 | 12 | /** 13 | * This class is internal and not for public use. Its APIs are unstable and can change at any time. 14 | */ 15 | @RequiresApi(api = Build.VERSION_CODES.P) 16 | data class Carrier 17 | @JvmOverloads 18 | constructor( 19 | val id: Int = TelephonyManager.UNKNOWN_CARRIER_ID, 20 | val name: String? = null, 21 | val mobileCountryCode: String? = null, 22 | val mobileNetworkCode: String? = null, 23 | val isoCountryCode: String? = null, 24 | ) 25 | -------------------------------------------------------------------------------- /common/src/main/java/io/opentelemetry/android/common/internal/features/networkattributes/data/NetworkState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.common.internal.features.networkattributes.data; 7 | 8 | import static io.opentelemetry.semconv.incubating.NetworkIncubatingAttributes.NetworkConnectionTypeIncubatingValues; 9 | 10 | /** 11 | * This class is internal and not for public use. Its APIs are unstable and can change at any time. 12 | */ 13 | public enum NetworkState { 14 | NO_NETWORK_AVAILABLE(NetworkConnectionTypeIncubatingValues.UNAVAILABLE), 15 | TRANSPORT_CELLULAR(NetworkConnectionTypeIncubatingValues.CELL), 16 | TRANSPORT_WIFI(NetworkConnectionTypeIncubatingValues.WIFI), 17 | TRANSPORT_WIRED(NetworkConnectionTypeIncubatingValues.WIRED), 18 | TRANSPORT_UNKNOWN(NetworkConnectionTypeIncubatingValues.UNKNOWN), 19 | // this one doesn't seem to have an otel value at this point. 20 | TRANSPORT_VPN("vpn"); 21 | 22 | private final String humanName; 23 | 24 | NetworkState(String humanName) { 25 | this.humanName = humanName; 26 | } 27 | 28 | public String getHumanName() { 29 | return humanName; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/src/main/java/io/opentelemetry/android/common/internal/tools/time/SystemTime.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.common.internal.tools.time 7 | 8 | /** 9 | * Utility to be able to mock the current system time for testing purposes. 10 | * 11 | *

This class is internal and not for public use. Its APIs are unstable and can change at any 12 | * time. 13 | */ 14 | interface SystemTime { 15 | companion object { 16 | private var instance: SystemTime = DefaultSystemTime() 17 | 18 | fun get(): SystemTime = instance 19 | 20 | fun setForTest(instance: SystemTime) { 21 | this.instance = instance 22 | } 23 | } 24 | 25 | fun getCurrentTimeMillis(): Long 26 | 27 | class DefaultSystemTime : SystemTime { 28 | override fun getCurrentTimeMillis(): Long = System.currentTimeMillis() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /core/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -dontwarn com.google.auto.value.AutoValue$Builder 2 | -dontwarn com.google.auto.value.AutoValue$CopyAnnotations 3 | -dontwarn com.google.auto.value.AutoValue 4 | -dontwarn com.google.auto.value.extension.memoized.Memoized 5 | -dontwarn io.grpc.Channel 6 | -dontwarn io.grpc.MethodDescriptor$Builder 7 | -dontwarn io.grpc.MethodDescriptor$Marshaller 8 | -dontwarn io.grpc.MethodDescriptor$MethodType 9 | -dontwarn io.grpc.MethodDescriptor 10 | -dontwarn io.grpc.stub.AbstractFutureStub 11 | -dontwarn io.grpc.stub.AbstractStub$StubFactory 12 | -dontwarn io.grpc.stub.AbstractStub -------------------------------------------------------------------------------- /core/src/integrationTest/kotlin/io/opentelemetry/android/AgentInitTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android 7 | 8 | import android.app.Application 9 | import android.os.Build.VERSION_CODES.LOLLIPOP 10 | import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE 11 | import androidx.test.core.app.ApplicationProvider.getApplicationContext 12 | import androidx.test.ext.junit.runners.AndroidJUnit4 13 | import io.opentelemetry.android.config.OtelRumConfig 14 | import org.junit.Assert.assertNotNull 15 | import org.junit.Test 16 | import org.junit.runner.RunWith 17 | import org.robolectric.annotation.Config 18 | 19 | @RunWith(AndroidJUnit4::class) 20 | internal class AgentInitTest { 21 | @Config(sdk = [LOLLIPOP, UPSIDE_DOWN_CAKE]) 22 | @Test 23 | fun startOpenTelemetryRumInAndroid() { 24 | val application = getApplicationContext() 25 | val otelRum = 26 | OpenTelemetryRum 27 | .builder( 28 | application, 29 | OtelRumConfig(), 30 | ).build() 31 | assertNotNull(otelRum) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/NoopOpenTelemetryRum.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android; 7 | 8 | import io.opentelemetry.api.OpenTelemetry; 9 | import io.opentelemetry.api.common.Attributes; 10 | import io.opentelemetry.api.trace.TraceId; 11 | 12 | enum NoopOpenTelemetryRum implements OpenTelemetryRum { 13 | INSTANCE; 14 | 15 | @Override 16 | public OpenTelemetry getOpenTelemetry() { 17 | return OpenTelemetry.noop(); 18 | } 19 | 20 | @Override 21 | public String getRumSessionId() { 22 | // RUM session.id has the same format as traceId 23 | return TraceId.getInvalid(); 24 | } 25 | 26 | @Override 27 | public void emitEvent(String eventName, String body, Attributes attributes) {} 28 | } 29 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/ScreenAttributesSpanProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android 7 | 8 | import io.opentelemetry.android.common.RumConstants 9 | import io.opentelemetry.android.internal.services.visiblescreen.VisibleScreenTracker 10 | import io.opentelemetry.context.Context 11 | import io.opentelemetry.sdk.trace.ReadWriteSpan 12 | import io.opentelemetry.sdk.trace.ReadableSpan 13 | import io.opentelemetry.sdk.trace.SpanProcessor 14 | 15 | /** 16 | * This class appends the screen name to all spans. 17 | */ 18 | internal class ScreenAttributesSpanProcessor( 19 | private val visibleScreenTracker: VisibleScreenTracker, 20 | ) : SpanProcessor { 21 | override fun onStart( 22 | parentContext: Context, 23 | span: ReadWriteSpan, 24 | ) { 25 | val currentScreen = visibleScreenTracker.currentlyVisibleScreen 26 | span.setAttribute(RumConstants.SCREEN_NAME_KEY, currentScreen) 27 | } 28 | 29 | override fun isStartRequired(): Boolean = true 30 | 31 | override fun onEnd(span: ReadableSpan) { 32 | // nop 33 | } 34 | 35 | override fun isEndRequired(): Boolean = false 36 | } 37 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/SessionIdSpanAppender.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android 7 | 8 | import io.opentelemetry.android.session.SessionProvider 9 | import io.opentelemetry.context.Context 10 | import io.opentelemetry.sdk.trace.ReadWriteSpan 11 | import io.opentelemetry.sdk.trace.ReadableSpan 12 | import io.opentelemetry.sdk.trace.SpanProcessor 13 | import io.opentelemetry.semconv.incubating.SessionIncubatingAttributes.SESSION_ID 14 | 15 | /** 16 | * A [SpanProcessor] that sets the `session.id` attribute to the current span when the span is started. 17 | */ 18 | internal class SessionIdSpanAppender( 19 | private val sessionProvider: SessionProvider, 20 | ) : SpanProcessor { 21 | override fun onStart( 22 | parentContext: Context, 23 | span: ReadWriteSpan, 24 | ) { 25 | span.setAttribute(SESSION_ID, sessionProvider.getSessionId()) 26 | } 27 | 28 | override fun isStartRequired(): Boolean = true 29 | 30 | override fun onEnd(span: ReadableSpan) {} 31 | 32 | override fun isEndRequired(): Boolean = false 33 | } 34 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/export/BufferDelegatingLogExporter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.export 7 | 8 | import io.opentelemetry.sdk.common.CompletableResultCode 9 | import io.opentelemetry.sdk.logs.data.LogRecordData 10 | import io.opentelemetry.sdk.logs.export.LogRecordExporter 11 | 12 | /** 13 | * An in-memory buffer delegating log exporter that buffers log records in memory until a delegate is set. 14 | * Once a delegate is set, the buffered log records are exported to the delegate. 15 | * 16 | * The buffer size is set to 5,000 log entries by default. If the buffer is full, the exporter will drop new log records. 17 | */ 18 | internal class BufferDelegatingLogExporter( 19 | maxBufferedLogs: Int = 5_000, 20 | ) : LogRecordExporter { 21 | private val delegatingExporter = 22 | DelegatingExporter( 23 | doExport = LogRecordExporter::export, 24 | doFlush = LogRecordExporter::flush, 25 | doShutdown = LogRecordExporter::shutdown, 26 | maxBufferedData = maxBufferedLogs, 27 | logType = "log records", 28 | ) 29 | 30 | fun setDelegate(delegate: LogRecordExporter) { 31 | delegatingExporter.setDelegate(delegate) 32 | } 33 | 34 | override fun export(logs: Collection): CompletableResultCode = delegatingExporter.export(logs) 35 | 36 | override fun flush(): CompletableResultCode = delegatingExporter.flush() 37 | 38 | override fun shutdown(): CompletableResultCode = delegatingExporter.shutdown() 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/export/BufferDelegatingSpanExporter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.export 7 | 8 | import io.opentelemetry.sdk.common.CompletableResultCode 9 | import io.opentelemetry.sdk.trace.data.SpanData 10 | import io.opentelemetry.sdk.trace.export.SpanExporter 11 | 12 | /** 13 | * An in-memory buffer delegating span exporter that buffers span data in memory until a delegate is set. 14 | * Once a delegate is set, the buffered span data is exported to the delegate. 15 | * 16 | * The buffer size is set to 5,000 spans by default. If the buffer is full, the exporter will drop new span data. 17 | */ 18 | internal class BufferDelegatingSpanExporter( 19 | maxBufferedSpans: Int = 5_000, 20 | ) : SpanExporter { 21 | private val delegatingExporter = 22 | DelegatingExporter( 23 | doExport = SpanExporter::export, 24 | doFlush = SpanExporter::flush, 25 | doShutdown = SpanExporter::shutdown, 26 | maxBufferedData = maxBufferedSpans, 27 | logType = "span data", 28 | ) 29 | 30 | fun setDelegate(delegate: SpanExporter) { 31 | delegatingExporter.setDelegate(delegate) 32 | } 33 | 34 | override fun export(spans: Collection): CompletableResultCode = delegatingExporter.export(spans) 35 | 36 | override fun flush(): CompletableResultCode = delegatingExporter.flush() 37 | 38 | override fun shutdown(): CompletableResultCode = delegatingExporter.shutdown() 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/export/ModifiedSpanData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.export; 7 | 8 | import io.opentelemetry.api.common.Attributes; 9 | import io.opentelemetry.sdk.trace.data.DelegatingSpanData; 10 | import io.opentelemetry.sdk.trace.data.SpanData; 11 | 12 | final class ModifiedSpanData extends DelegatingSpanData { 13 | 14 | private final Attributes modifiedAttributes; 15 | 16 | ModifiedSpanData(SpanData original, Attributes modifiedAttributes) { 17 | super(original); 18 | this.modifiedAttributes = modifiedAttributes; 19 | } 20 | 21 | @Override 22 | public Attributes getAttributes() { 23 | return modifiedAttributes; 24 | } 25 | 26 | @Override 27 | public int getTotalAttributeCount() { 28 | return modifiedAttributes.size(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/DefaultExportScheduleHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.features.diskbuffering.scheduler 7 | 8 | import io.opentelemetry.android.internal.services.periodicwork.PeriodicWork 9 | import java.util.concurrent.atomic.AtomicBoolean 10 | 11 | class DefaultExportScheduleHandler( 12 | private val exportScheduler: DefaultExportScheduler, 13 | private val periodicWorkProvider: () -> PeriodicWork, 14 | ) : ExportScheduleHandler { 15 | private val periodicWorkService by lazy { periodicWorkProvider() } 16 | private val enabled = AtomicBoolean(false) 17 | 18 | override fun enable() { 19 | if (!enabled.getAndSet(true)) { 20 | periodicWorkService.enqueue(exportScheduler) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/DefaultExportScheduler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.features.diskbuffering.scheduler 7 | 8 | import android.util.Log 9 | import io.opentelemetry.android.common.RumConstants.OTEL_RUM_LOG_TAG 10 | import io.opentelemetry.android.features.diskbuffering.SignalFromDiskExporter 11 | import io.opentelemetry.android.internal.services.periodicwork.PeriodicRunnable 12 | import io.opentelemetry.android.internal.services.periodicwork.PeriodicWork 13 | import java.io.IOException 14 | import java.util.concurrent.TimeUnit 15 | 16 | class DefaultExportScheduler( 17 | periodicWorkProvider: () -> PeriodicWork, 18 | ) : PeriodicRunnable(periodicWorkProvider) { 19 | companion object { 20 | private val DELAY_BEFORE_NEXT_EXPORT_IN_MILLIS = TimeUnit.SECONDS.toMillis(10) 21 | } 22 | 23 | override fun onRun() { 24 | val exporter = SignalFromDiskExporter.get() ?: return 25 | 26 | try { 27 | do { 28 | val didExport = exporter.exportBatchOfEach() 29 | } while (didExport) 30 | } catch (e: IOException) { 31 | Log.e(OTEL_RUM_LOG_TAG, "Error while exporting signals from disk.", e) 32 | } 33 | } 34 | 35 | override fun shouldStopRunning(): Boolean = SignalFromDiskExporter.get() == null 36 | 37 | override fun minimumDelayUntilNextRunInMillis(): Long = DELAY_BEFORE_NEXT_EXPORT_IN_MILLIS 38 | } 39 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/ExportScheduleHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.features.diskbuffering.scheduler 7 | 8 | /** 9 | * Sets up a scheduling mechanism to read and export previously stored signals in disk. 10 | */ 11 | interface ExportScheduleHandler { 12 | /** 13 | * Start/Set up the exporting schedule. Called when the disk buffering feature gets enabled. 14 | */ 15 | fun enable() 16 | 17 | /** 18 | * Don't start (or stop if something was previously started) the exporting schedule, no look up 19 | * for data stored in the disk to export will be carried over if this function is called. 20 | * This will be called if the disk buffering feature gets disabled. 21 | */ 22 | fun disable() {} 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/internal/features/networkattrs/NetworkAttributesLogRecordAppender.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.internal.features.networkattrs 7 | 8 | import io.opentelemetry.android.common.internal.features.networkattributes.CurrentNetworkAttributesExtractor 9 | import io.opentelemetry.android.internal.services.network.CurrentNetworkProvider 10 | import io.opentelemetry.context.Context 11 | import io.opentelemetry.sdk.logs.LogRecordProcessor 12 | import io.opentelemetry.sdk.logs.ReadWriteLogRecord 13 | 14 | class NetworkAttributesLogRecordAppender( 15 | private val currentNetworkProvider: CurrentNetworkProvider, 16 | private val networkAttributesExtractor: CurrentNetworkAttributesExtractor = CurrentNetworkAttributesExtractor(), 17 | ) : LogRecordProcessor { 18 | constructor(networkProvider: CurrentNetworkProvider) : this(networkProvider, CurrentNetworkAttributesExtractor()) 19 | 20 | override fun onEmit( 21 | context: Context, 22 | logRecord: ReadWriteLogRecord, 23 | ) { 24 | val currentNetwork = currentNetworkProvider.currentNetwork 25 | logRecord.setAllAttributes(networkAttributesExtractor.extract(currentNetwork)) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/internal/features/persistence/SimpleTemporaryFileProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.internal.features.persistence 7 | 8 | import io.opentelemetry.contrib.disk.buffering.config.TemporaryFileProvider 9 | import java.io.File 10 | import java.util.UUID 11 | 12 | internal class SimpleTemporaryFileProvider( 13 | private val tempDir: File, 14 | ) : TemporaryFileProvider { 15 | /** Creates a unique file instance using the provided prefix and the current time in millis. */ 16 | override fun createTemporaryFile(prefix: String): File = File(tempDir, prefix + "_" + UUID.randomUUID() + ".tmp") 17 | } 18 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/internal/processors/GlobalAttributesLogRecordAppender.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.internal.processors 7 | 8 | import io.opentelemetry.api.common.Attributes 9 | import io.opentelemetry.context.Context 10 | import io.opentelemetry.sdk.logs.LogRecordProcessor 11 | import io.opentelemetry.sdk.logs.ReadWriteLogRecord 12 | import java.util.function.Supplier 13 | 14 | internal class GlobalAttributesLogRecordAppender( 15 | private val attributesSupplier: Supplier, 16 | ) : LogRecordProcessor { 17 | override fun onEmit( 18 | context: Context, 19 | logRecord: ReadWriteLogRecord, 20 | ) { 21 | logRecord.setAllAttributes(attributesSupplier.get()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/internal/processors/ScreenAttributesLogRecordProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.internal.processors 7 | 8 | import io.opentelemetry.android.common.RumConstants 9 | import io.opentelemetry.android.internal.services.visiblescreen.VisibleScreenTracker 10 | import io.opentelemetry.context.Context 11 | import io.opentelemetry.sdk.logs.LogRecordProcessor 12 | import io.opentelemetry.sdk.logs.ReadWriteLogRecord 13 | 14 | class ScreenAttributesLogRecordProcessor( 15 | val visibleScreenTracker: VisibleScreenTracker, 16 | ) : LogRecordProcessor { 17 | override fun onEmit( 18 | context: Context, 19 | logRecord: ReadWriteLogRecord, 20 | ) { 21 | val currentScreen = visibleScreenTracker.currentlyVisibleScreen 22 | logRecord.setAttribute(RumConstants.SCREEN_NAME_KEY, currentScreen) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/internal/processors/SessionIdLogRecordAppender.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.internal.processors 7 | 8 | import io.opentelemetry.android.session.SessionProvider 9 | import io.opentelemetry.context.Context 10 | import io.opentelemetry.sdk.logs.LogRecordProcessor 11 | import io.opentelemetry.sdk.logs.ReadWriteLogRecord 12 | import io.opentelemetry.semconv.incubating.SessionIncubatingAttributes.SESSION_ID 13 | 14 | internal class SessionIdLogRecordAppender( 15 | private val sessionProvider: SessionProvider, 16 | ) : LogRecordProcessor { 17 | override fun onEmit( 18 | context: Context, 19 | logRecord: ReadWriteLogRecord, 20 | ) { 21 | logRecord.setAttribute(SESSION_ID, sessionProvider.getSessionId()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/io/opentelemetry/android/package-info.java: -------------------------------------------------------------------------------- 1 | @ParametersAreNonnullByDefault 2 | package io.opentelemetry.android; 3 | 4 | import javax.annotation.ParametersAreNonnullByDefault; 5 | -------------------------------------------------------------------------------- /core/src/test/java/io/opentelemetry/android/export/TestSpanHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.export; 7 | 8 | import io.opentelemetry.api.common.Attributes; 9 | import io.opentelemetry.api.trace.SpanKind; 10 | import io.opentelemetry.sdk.testing.trace.TestSpanData; 11 | import io.opentelemetry.sdk.trace.data.SpanData; 12 | import io.opentelemetry.sdk.trace.data.StatusData; 13 | 14 | public class TestSpanHelper { 15 | 16 | static SpanData span(String name) { 17 | return span(name, Attributes.empty()); 18 | } 19 | 20 | static SpanData span(String name, Attributes attributes) { 21 | return TestSpanData.builder() 22 | .setName(name) 23 | .setKind(SpanKind.INTERNAL) 24 | .setStatus(StatusData.unset()) 25 | .setHasEnded(true) 26 | .setStartEpochNanos(0) 27 | .setEndEpochNanos(123) 28 | .setAttributes(attributes) 29 | .build(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/test/java/io/opentelemetry/android/internal/features/persistence/SimpleTemporaryFileProviderTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.internal.features.persistence 7 | 8 | import org.assertj.core.api.Assertions.assertThat 9 | import org.junit.jupiter.api.Test 10 | import org.junit.jupiter.api.io.TempDir 11 | import java.io.File 12 | 13 | internal class SimpleTemporaryFileProviderTest { 14 | @TempDir 15 | lateinit var tempDir: File 16 | 17 | @Test 18 | fun createUniqueFilesBasedOnCurrentTimeAndPrefix() { 19 | val provider = SimpleTemporaryFileProvider(tempDir) 20 | val first = provider.createTemporaryFile("a") 21 | val second = provider.createTemporaryFile("b") 22 | Thread.sleep(1) 23 | val third = provider.createTemporaryFile("a") 24 | assertThat(first.getName()).startsWith("a").endsWith(".tmp") 25 | assertThat(second.getName()).startsWith("b").endsWith(".tmp") 26 | assertThat(third.getName()).startsWith("a").endsWith(".tmp") 27 | assertThat(first).isNotEqualTo(third) 28 | assertThat(first.getParentFile()).isEqualTo(tempDir) 29 | assertThat(second.getParentFile()).isEqualTo(tempDir) 30 | assertThat(third.getParentFile()).isEqualTo(tempDir) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/src/test/java/io/opentelemetry/android/internal/initialization/InitializationEventsTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.internal.initialization 7 | 8 | import io.mockk.mockk 9 | import org.assertj.core.api.Assertions.assertThat 10 | import org.junit.jupiter.api.AfterEach 11 | import org.junit.jupiter.api.Test 12 | 13 | class InitializationEventsTest { 14 | @AfterEach 15 | fun tearDown() { 16 | InitializationEvents.resetForTest() 17 | } 18 | 19 | @Test 20 | fun `Verify service loading`() { 21 | val initializationEvents = InitializationEvents.get() 22 | assertThat(initializationEvents).isInstanceOf(TestInitializationEvents::class.java) 23 | } 24 | 25 | @Test 26 | fun `Verify setting instance once`() { 27 | val initializationEvents = mockk() 28 | InitializationEvents.set(initializationEvents) 29 | 30 | assertThat(InitializationEvents.get()).isEqualTo(initializationEvents) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/src/test/java/io/opentelemetry/android/internal/initialization/TestInitializationEvents.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.internal.initialization 7 | 8 | import io.opentelemetry.android.config.OtelRumConfig 9 | import io.opentelemetry.sdk.trace.export.SpanExporter 10 | 11 | class TestInitializationEvents : InitializationEvents { 12 | override fun sdkInitializationStarted() { 13 | } 14 | 15 | override fun recordConfiguration(config: OtelRumConfig) { 16 | } 17 | 18 | override fun currentNetworkProviderInitialized() { 19 | } 20 | 21 | override fun networkMonitorInitialized() { 22 | } 23 | 24 | override fun anrMonitorInitialized() { 25 | } 26 | 27 | override fun slowRenderingDetectorInitialized() { 28 | } 29 | 30 | override fun crashReportingInitialized() { 31 | } 32 | 33 | override fun spanExporterInitialized(spanExporter: SpanExporter) { 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /core/src/test/java/io/opentelemetry/android/internal/processors/ScreenAttributesLogRecordProcessorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.internal.processors 7 | 8 | import io.mockk.every 9 | import io.mockk.mockk 10 | import io.mockk.verify 11 | import io.opentelemetry.android.common.RumConstants.SCREEN_NAME_KEY 12 | import io.opentelemetry.android.internal.services.visiblescreen.VisibleScreenTracker 13 | import io.opentelemetry.api.common.AttributeKey 14 | import io.opentelemetry.sdk.logs.ReadWriteLogRecord 15 | import org.junit.Test 16 | 17 | private const val CURRENT_SCREEN = "party favors" 18 | 19 | class ScreenAttributesLogRecordProcessorTest { 20 | @Test 21 | fun `current screen name is appended`() { 22 | val visibleScreenTracker: VisibleScreenTracker = mockk() 23 | val logRecord: ReadWriteLogRecord = mockk() 24 | every { visibleScreenTracker.currentlyVisibleScreen }.returns(CURRENT_SCREEN) 25 | every { logRecord.setAttribute(any>(), any()) } returns logRecord 26 | val testClass = ScreenAttributesLogRecordProcessor(visibleScreenTracker) 27 | testClass.onEmit(mockk(), logRecord) 28 | verify { logRecord.setAttribute(SCREEN_NAME_KEY, CURRENT_SCREEN) } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /core/src/test/java/io/opentelemetry/android/internal/processors/SessionIdLogRecordAppenderTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.internal.processors 7 | 8 | import io.mockk.MockKAnnotations 9 | import io.mockk.every 10 | import io.mockk.impl.annotations.MockK 11 | import io.mockk.verify 12 | import io.opentelemetry.android.session.SessionProvider 13 | import io.opentelemetry.api.common.AttributeKey 14 | import io.opentelemetry.context.Context 15 | import io.opentelemetry.sdk.logs.ReadWriteLogRecord 16 | import io.opentelemetry.semconv.incubating.SessionIncubatingAttributes 17 | import org.junit.jupiter.api.BeforeEach 18 | import org.junit.jupiter.api.Test 19 | 20 | private const val SESSION_ID_VALUE = "0666" 21 | 22 | class SessionIdLogRecordAppenderTest { 23 | @MockK 24 | lateinit var sessionProvider: SessionProvider 25 | 26 | @MockK 27 | lateinit var log: ReadWriteLogRecord 28 | 29 | @BeforeEach 30 | fun setUp() { 31 | MockKAnnotations.init(this) 32 | every { sessionProvider.getSessionId() }.returns(SESSION_ID_VALUE) 33 | every { log.setAttribute(any>(), any()) } returns log 34 | } 35 | 36 | @Test 37 | fun `should set sessionId as log record attribute`() { 38 | val underTest = SessionIdLogRecordAppender(sessionProvider) 39 | 40 | underTest.onEmit(Context.root(), log) 41 | 42 | verify { log.setAttribute(SessionIncubatingAttributes.SESSION_ID, SESSION_ID_VALUE) } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /core/src/test/resources/META-INF/services/io.opentelemetry.android.internal.initialization.InitializationEvents: -------------------------------------------------------------------------------- 1 | io.opentelemetry.android.internal.initialization.TestInitializationEvents -------------------------------------------------------------------------------- /demo-app/collector.yaml: -------------------------------------------------------------------------------- 1 | receivers: 2 | otlp: 3 | protocols: 4 | grpc: 5 | endpoint: 0.0.0.0:4317 6 | http: 7 | endpoint: 0.0.0.0:4318 8 | extensions: 9 | exporters: 10 | otlphttp: 11 | traces_endpoint: "http://jaeger:4318/v1/traces" 12 | debug: 13 | verbosity: normal 14 | debug/detailed: 15 | verbosity: detailed 16 | service: 17 | pipelines: 18 | traces: 19 | receivers: [otlp] 20 | exporters: [debug/detailed, otlphttp] 21 | logs: 22 | receivers: [otlp] 23 | exporters: [debug/detailed] 24 | -------------------------------------------------------------------------------- /demo-app/compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | collector: 3 | image: "otel/opentelemetry-collector-contrib@sha256:1ab0baba0ee3695d823c46653d8a6e8894896e668ce8bd7ebe002e948d827bc7" 4 | volumes: 5 | - ./collector.yaml:/etc/demo-collector.yaml 6 | entrypoint: ["/otelcol-contrib"] 7 | command: ["--config", "/etc/demo-collector.yaml"] 8 | ports: 9 | - "4317:4317" # OTLP gRPC 10 | - "4318:4318" # OTLP HTTP 11 | jaeger: 12 | image: "jaegertracing/all-in-one:1.60@sha256:4fd2d70fa347d6a47e79fcb06b1c177e6079f92cba88b083153d56263082135e" 13 | environment: 14 | - COLLECTOR_OTLP_ENABLED=true 15 | - COLLECTOR_OTLP_HTTP_HOST_PORT=0.0.0.0:4318 16 | ports: 17 | - "16686:16686" # UI -------------------------------------------------------------------------------- /demo-app/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 2 | android.useAndroidX=true 3 | android.useFullClasspathForDexingTransform=true 4 | -------------------------------------------------------------------------------- /demo-app/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /demo-app/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=7197a12f450794931532469d4ff21a59ea2c1cd59a3ec3f89c035c3c420a6999 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /demo-app/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "opentelemetry-android-demo" 2 | 3 | pluginManagement { 4 | repositories { 5 | mavenCentral() 6 | google() 7 | gradlePluginPortal() 8 | } 9 | } 10 | dependencyResolutionManagement { 11 | versionCatalogs { 12 | create("rootLibs") { 13 | from(files("../gradle/libs.versions.toml")) 14 | } 15 | } 16 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 17 | repositories { 18 | mavenCentral() 19 | google() 20 | } 21 | } 22 | 23 | includeBuild("..") { 24 | dependencySubstitution { 25 | substitute(module("io.opentelemetry.android:android-agent")) 26 | .using(project(":android-agent")) 27 | substitute(module("io.opentelemetry.android:instrumentation-sessions")) 28 | .using(project(":instrumentation:sessions")) 29 | } 30 | } -------------------------------------------------------------------------------- /demo-app/src/androidTest/java/io/opentelemetry/android/demo/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.demo 7 | 8 | import androidx.test.ext.junit.runners.AndroidJUnit4 9 | import androidx.test.platform.app.InstrumentationRegistry 10 | import org.junit.Assert 11 | import org.junit.Test 12 | import org.junit.runner.RunWith 13 | 14 | /** 15 | * Instrumented test, which will execute on an Android device. 16 | * 17 | * See [testing documentation](http://d.android.com/tools/testing). 18 | */ 19 | @RunWith(AndroidJUnit4::class) 20 | class ExampleInstrumentedTest { 21 | @Test 22 | fun useAppContext() { 23 | // Context of the app under test. 24 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 25 | Assert.assertEquals("io.opentelemetry.android.demo", appContext.packageName) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /demo-app/src/main/assets/images/EclipsmartTravelRefractorTelescope.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/assets/images/EclipsmartTravelRefractorTelescope.jpg -------------------------------------------------------------------------------- /demo-app/src/main/assets/images/LensCleaningKit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/assets/images/LensCleaningKit.jpg -------------------------------------------------------------------------------- /demo-app/src/main/assets/images/NationalParkFoundationExplorascope.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/assets/images/NationalParkFoundationExplorascope.jpg -------------------------------------------------------------------------------- /demo-app/src/main/assets/images/OpticalTubeAssembly.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/assets/images/OpticalTubeAssembly.jpg -------------------------------------------------------------------------------- /demo-app/src/main/assets/images/RedFlashlight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/assets/images/RedFlashlight.jpg -------------------------------------------------------------------------------- /demo-app/src/main/assets/images/RoofBinoculars.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/assets/images/RoofBinoculars.jpg -------------------------------------------------------------------------------- /demo-app/src/main/assets/images/SolarFilter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/assets/images/SolarFilter.jpg -------------------------------------------------------------------------------- /demo-app/src/main/assets/images/SolarSystemColorImager.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/assets/images/SolarSystemColorImager.jpg -------------------------------------------------------------------------------- /demo-app/src/main/assets/images/StarsenseExplorer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/assets/images/StarsenseExplorer.jpg -------------------------------------------------------------------------------- /demo-app/src/main/assets/images/TheCometBook.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/assets/images/TheCometBook.jpg -------------------------------------------------------------------------------- /demo-app/src/main/ic_cart-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/ic_cart-playstore.png -------------------------------------------------------------------------------- /demo-app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/DemoViewModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.demo 7 | 8 | import androidx.lifecycle.ViewModel 9 | import androidx.lifecycle.viewModelScope 10 | import kotlinx.coroutines.delay 11 | import kotlinx.coroutines.flow.MutableStateFlow 12 | import kotlinx.coroutines.launch 13 | 14 | class DemoViewModel : ViewModel() { 15 | val sessionIdState = MutableStateFlow("? unknown ?") 16 | private val tracer = OtelDemoApplication.tracer("otel.demo")!! 17 | 18 | init { 19 | viewModelScope.launch { 20 | while (true) { 21 | delay(5000) 22 | // TODO: Do some work here maybe 23 | } 24 | } 25 | } 26 | 27 | private fun updateSession() { 28 | // TODO 29 | } 30 | 31 | private fun sendTrace( 32 | type: String, 33 | value: Float, 34 | ) { 35 | // A metric should be a better fit, but for now we're using spans. 36 | tracer.spanBuilder(type).setAttribute("value", value.toDouble()).startSpan().end() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/LauncherButton.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.demo 7 | 8 | import androidx.compose.foundation.BorderStroke 9 | import androidx.compose.foundation.layout.Row 10 | import androidx.compose.foundation.layout.Spacer 11 | import androidx.compose.foundation.layout.height 12 | import androidx.compose.foundation.layout.padding 13 | import androidx.compose.material3.Button 14 | import androidx.compose.material3.ButtonDefaults 15 | import androidx.compose.runtime.Composable 16 | import androidx.compose.ui.Modifier 17 | import androidx.compose.ui.graphics.Color 18 | import androidx.compose.ui.unit.dp 19 | import androidx.compose.ui.unit.sp 20 | 21 | @Composable 22 | fun LauncherButton( 23 | text: String, 24 | onClick: () -> Unit, 25 | ) { 26 | Row { 27 | Spacer(modifier = Modifier.height(5.dp)) 28 | } 29 | Row { 30 | Button( 31 | onClick = onClick, 32 | border = BorderStroke(1.dp, Color.Gray), 33 | modifier = Modifier.padding(20.dp).height(90.dp), 34 | colors = 35 | ButtonDefaults.buttonColors( 36 | containerColor = Color.Transparent, 37 | contentColor = Color(0xFF425CC7), 38 | ), 39 | content = { 40 | CenterText(text = text, fontSize = 30.sp) 41 | }, 42 | ) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/about/AboutOpenTelemetryFragment.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.android.demo.about 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.fragment.app.Fragment 8 | import io.opentelemetry.android.demo.R 9 | 10 | class AboutOpenTelemetryFragment : Fragment() { 11 | 12 | override fun onCreateView( 13 | inflater: LayoutInflater, container: ViewGroup?, 14 | savedInstanceState: Bundle? 15 | ): View? { 16 | return inflater.inflate(R.layout.fragment_about_opentelemetry, container, false) 17 | } 18 | } -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/about/AppFeaturesFragment.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.android.demo.about 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.fragment.app.Fragment 8 | import androidx.recyclerview.widget.LinearLayoutManager 9 | import androidx.recyclerview.widget.RecyclerView 10 | import io.opentelemetry.android.demo.R 11 | 12 | class AppFeaturesFragment : Fragment() { 13 | 14 | override fun onCreateView( 15 | inflater: LayoutInflater, container: ViewGroup?, 16 | savedInstanceState: Bundle? 17 | ): View? { 18 | val view = inflater.inflate(R.layout.fragment_app_features, container, false) 19 | lateinit var featureAdapter: FeatureAdapter 20 | val features = getFeatureList() 21 | val recyclerView: RecyclerView = view.findViewById(R.id.recyclerView) 22 | 23 | featureAdapter = FeatureAdapter(features) 24 | recyclerView.adapter = featureAdapter 25 | recyclerView.layoutManager = LinearLayoutManager(requireContext()) 26 | 27 | return view 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/shop/clients/ImageLoader.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.android.demo.shop.clients 2 | 3 | import android.content.Context 4 | import android.graphics.Bitmap 5 | import android.graphics.BitmapFactory 6 | 7 | /** 8 | * Fake (for now) image loader. Ideally this would fetch images from the 9 | * imageloader service. 10 | */ 11 | class ImageLoader(private val context: Context) { 12 | 13 | // `http://localhost:8080/${src}?w=${width}&q=${quality || 75}` 14 | fun load(name: String): Bitmap { 15 | val file = "images/${name}" 16 | val input = context.assets.open(file) 17 | return BitmapFactory.decodeStream(input) 18 | } 19 | } -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/shop/clients/ProductCatalogClient.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.android.demo.shop.clients 2 | 3 | import android.content.Context 4 | import com.google.gson.Gson 5 | import com.google.gson.reflect.TypeToken 6 | import io.opentelemetry.android.demo.shop.model.Product 7 | import io.opentelemetry.android.demo.shop.model.ProductDeserializationWrapper 8 | 9 | const val PRODUCTS_FILE = "products.json" 10 | 11 | /** A fake (for now!) client for the ProductCatalog */ 12 | // TODO: breedx-splk add instrumentation! 13 | // TODO: Allow this to be wired up to the go service from the actual demo 14 | class ProductCatalogClient(private val context: Context) { 15 | 16 | fun get(): List { 17 | val input = context.assets.open(PRODUCTS_FILE) 18 | val jsonStr = input.bufferedReader() 19 | val wrapper = Gson().fromJson(jsonStr, ProductDeserializationWrapper::class.java) 20 | return wrapper.products 21 | } 22 | } -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/shop/clients/RecommendationService.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.android.demo.shop.clients 2 | 3 | import io.opentelemetry.android.demo.shop.model.Product 4 | import io.opentelemetry.android.demo.shop.ui.cart.CartViewModel 5 | 6 | class RecommendationService( 7 | private val productCatalogClient: ProductCatalogClient, 8 | private val cartViewModel: CartViewModel 9 | ) { 10 | 11 | fun getRecommendedProducts(currentProduct: Product, numberOfProducts: Int = 4): List { 12 | return getAllNonCartProducts().filter { it.id != currentProduct.id } 13 | .shuffled().take(numberOfProducts) 14 | } 15 | 16 | fun getRecommendedProducts(numberOfProducts: Int = 4): List { 17 | return getAllNonCartProducts().shuffled().take(numberOfProducts) 18 | } 19 | 20 | private fun getAllNonCartProducts(): List{ 21 | val allProducts = productCatalogClient.get() 22 | val cartItems = cartViewModel.cartItems.value 23 | 24 | return allProducts.filter { product -> cartItems.none { it.product.id == product.id } } 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/shop/model/Product.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.android.demo.shop.model 2 | 3 | import androidx.annotation.Keep 4 | 5 | @Keep 6 | data class Product( 7 | val id: String, 8 | val name: String, 9 | val description: String, 10 | val picture: String, 11 | val priceUsd: PriceUsd, 12 | val categories: List 13 | ) { 14 | fun priceValue(): Double { 15 | return priceUsd.units.toDouble() + priceUsd.nanos.toDouble() / 1_000_000_000f 16 | } 17 | } 18 | 19 | // For deserialization 20 | @Keep 21 | data class ProductDeserializationWrapper( 22 | val products: List 23 | ) 24 | 25 | @Keep 26 | data class PriceUsd( 27 | val currencyCode: String, 28 | val units: Long, 29 | val nanos: Long 30 | ) -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/shop/ui/cart/CartViewModel.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.android.demo.shop.ui.cart 2 | 3 | import androidx.lifecycle.ViewModel 4 | import io.opentelemetry.android.demo.shop.model.Product 5 | import kotlinx.coroutines.flow.MutableStateFlow 6 | import kotlinx.coroutines.flow.StateFlow 7 | 8 | data class CartItem( 9 | val product: Product, 10 | var quantity: Int 11 | ) { 12 | fun totalPrice() = product.priceValue() * quantity 13 | } 14 | 15 | class CartViewModel : ViewModel() { 16 | private val _cartItems = MutableStateFlow>(emptyList()) 17 | val cartItems: StateFlow> = _cartItems 18 | 19 | fun addProduct(product: Product, quantity: Int) { 20 | _cartItems.value = _cartItems.value.toMutableList().apply { 21 | val index = indexOfFirst { it.product.id == product.id } 22 | if (index >= 0) { 23 | this[index] = this[index].copy(quantity = this[index].quantity + quantity) 24 | } else { 25 | add(CartItem(product, quantity)) 26 | } 27 | } 28 | } 29 | 30 | fun getTotalPrice(): Double { 31 | return _cartItems.value.sumOf { it.totalPrice() } 32 | } 33 | 34 | fun clearCart() { 35 | _cartItems.value = emptyList() 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/shop/ui/components/ConfirmCrashPopUp.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.android.demo.shop.ui.components 2 | 3 | import androidx.compose.material3.AlertDialog 4 | import androidx.compose.material3.Text 5 | import androidx.compose.material3.TextButton 6 | import androidx.compose.runtime.Composable 7 | 8 | @Composable 9 | fun ConfirmPopup( 10 | text : String, 11 | onConfirm: () -> Unit, 12 | onDismiss: () -> Unit 13 | ) { 14 | 15 | AlertDialog( 16 | onDismissRequest = { onDismiss() }, 17 | title = { 18 | Text(text = "Are you sure?") 19 | }, 20 | text = { 21 | Text(text = text) 22 | }, 23 | confirmButton = { 24 | TextButton(onClick = { onConfirm() }) { 25 | Text(text = "Yes, I'm sure") 26 | } 27 | }, 28 | dismissButton = { 29 | TextButton(onClick = { onDismiss() }) { 30 | Text(text = "No, go back") 31 | } 32 | } 33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/shop/ui/components/UpPressButton.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.android.demo.shop.ui.components 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.clickable 5 | import androidx.compose.foundation.layout.size 6 | import androidx.compose.foundation.layout.padding 7 | import androidx.compose.foundation.shape.CircleShape 8 | import androidx.compose.material3.Icon 9 | import androidx.compose.material.icons.Icons 10 | import androidx.compose.material.icons.automirrored.filled.ArrowBack 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.graphics.Color 14 | import androidx.compose.ui.unit.dp 15 | import androidx.compose.ui.zIndex 16 | 17 | @Composable 18 | fun UpPressButton( 19 | upPress: () -> Unit, 20 | modifier: Modifier = Modifier 21 | ) { 22 | Icon( 23 | imageVector = Icons.AutoMirrored.Filled.ArrowBack, 24 | contentDescription = "Navigate Up", 25 | tint = Color.Black, 26 | modifier = modifier 27 | .size(48.dp) 28 | .background(Color.White, shape = CircleShape) 29 | .padding(8.dp) 30 | .zIndex(1f) 31 | .clickable(onClick = upPress) 32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/shop/ui/products/ProductList.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.android.demo.shop.ui.products 2 | 3 | import androidx.compose.foundation.layout.Box 4 | import androidx.compose.foundation.layout.Row 5 | import androidx.compose.foundation.layout.fillMaxSize 6 | import androidx.compose.foundation.layout.height 7 | import androidx.compose.foundation.lazy.LazyColumn 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.unit.dp 11 | import io.opentelemetry.android.demo.shop.model.Product 12 | 13 | @Composable 14 | fun ProductList(products: List, onProductClick: (String) -> Unit) { 15 | LazyColumn(modifier = Modifier.fillMaxSize()) { 16 | items(products.size) { index -> 17 | Row { 18 | ProductCard(products[index], onProductClick = onProductClick) 19 | } 20 | } 21 | item { 22 | Box( 23 | modifier = Modifier.height(50.dp) 24 | ) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/theme/Color.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.demo.theme 7 | 8 | import androidx.compose.ui.graphics.Color 9 | 10 | val Purple80 = Color(0xFFD0BCFF) 11 | val PurpleGrey80 = Color(0xFFCCC2DC) 12 | val Pink80 = Color(0xFFEFB8C8) 13 | 14 | val Purple40 = Color(0xFF6650a4) 15 | val PurpleGrey40 = Color(0xFF625b71) 16 | val Pink40 = Color(0xFF7D5260) 17 | -------------------------------------------------------------------------------- /demo-app/src/main/java/io/opentelemetry/android/demo/theme/Type.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.android.demo.theme 7 | 8 | import androidx.compose.material3.Typography 9 | import androidx.compose.ui.text.TextStyle 10 | import androidx.compose.ui.text.font.FontFamily 11 | import androidx.compose.ui.text.font.FontWeight 12 | import androidx.compose.ui.unit.sp 13 | 14 | // Set of Material typography styles to start with 15 | val Typography = 16 | Typography( 17 | bodyLarge = 18 | TextStyle( 19 | fontFamily = FontFamily.Default, 20 | fontWeight = FontWeight.Normal, 21 | fontSize = 16.sp, 22 | lineHeight = 24.sp, 23 | letterSpacing = 0.5.sp, 24 | ), 25 | /* Other default text styles to override 26 | titleLarge = TextStyle( 27 | fontFamily = FontFamily.Default, 28 | fontWeight = FontWeight.Normal, 29 | fontSize = 22.sp, 30 | lineHeight = 28.sp, 31 | letterSpacing = 0.sp 32 | ), 33 | labelSmall = TextStyle( 34 | fontFamily = FontFamily.Default, 35 | fontWeight = FontWeight.Medium, 36 | fontSize = 11.sp, 37 | lineHeight = 16.sp, 38 | letterSpacing = 0.5.sp 39 | ) 40 | */ 41 | ) 42 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/exit_to_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/ic_arrow_drop_down.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/ic_cart_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/ic_dashboard_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/ic_home_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/ic_notifications_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/otel_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/drawable/otel_icon.png -------------------------------------------------------------------------------- /demo-app/src/main/res/font/gotham_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/font/gotham_bold.ttf -------------------------------------------------------------------------------- /demo-app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 23 | 24 | -------------------------------------------------------------------------------- /demo-app/src/main/res/layout/fragment_app_features.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 21 | 22 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /demo-app/src/main/res/layout/fragment_notifications.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 22 | -------------------------------------------------------------------------------- /demo-app/src/main/res/layout/item_feature.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | 19 | 20 | 27 | 28 | 29 | 37 | 38 | -------------------------------------------------------------------------------- /demo-app/src/main/res/menu/bottom_nav_menu.xml: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 8 | 9 | 12 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-anydpi-v26/ic_cart.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-anydpi-v26/ic_cart_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-hdpi/ic_cart.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-hdpi/ic_cart.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-hdpi/ic_cart_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-hdpi/ic_cart_round.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-mdpi/ic_cart.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-mdpi/ic_cart.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-mdpi/ic_cart_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-mdpi/ic_cart_round.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xhdpi/ic_cart.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xhdpi/ic_cart.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xhdpi/ic_cart_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xhdpi/ic_cart_round.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxhdpi/ic_cart.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xxhdpi/ic_cart.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxhdpi/ic_cart_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xxhdpi/ic_cart_round.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxxhdpi/ic_cart.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xxxhdpi/ic_cart.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxxhdpi/ic_cart_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xxxhdpi/ic_cart_round.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-telemetry/opentelemetry-android/f139349615dadf70473496b48a5c15fb5841394a/demo-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /demo-app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | OpenTelemetryDemoApp 3 | AstronomyShopActivity 4 | OpenTelemetry Astronomy Shop 5 | Dashboard 6 | Cart 7 | Exit 8 | Exit 9 | App Features 10 | About OpenTelemetry 11 | Expand or collapse content 12 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |