├── .java-version ├── manual_licenses_map.txt ├── agent-common ├── metadata │ └── agent-common.api ├── build.gradle.kts └── src │ └── main │ └── java │ └── co │ └── elastic │ └── otel │ └── android │ └── common │ └── internal │ ├── package-info.java │ ├── annotations │ └── InternalApi.kt │ └── logging │ ├── ELoggerFactory.kt │ ├── Elog.kt │ └── BaseELogger.kt ├── checks.sh ├── instrumentation ├── api │ ├── metadata │ │ └── api.api │ ├── src │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── co │ │ │ └── elastic │ │ │ └── otel │ │ │ └── android │ │ │ └── instrumentation │ │ │ └── internal │ │ │ ├── package-info.java │ │ │ └── Instrumentation.kt │ └── build.gradle.kts ├── okhttp │ ├── library │ │ ├── metadata │ │ │ └── library.api │ │ ├── src │ │ │ └── main │ │ │ │ └── java │ │ │ │ └── co │ │ │ │ └── elastic │ │ │ │ └── otel │ │ │ │ └── android │ │ │ │ └── okhttp │ │ │ │ └── internal │ │ │ │ ├── package-info.java │ │ │ │ ├── delegate │ │ │ │ └── InterceptorDelegator.kt │ │ │ │ ├── OkHttpInstrumentation.kt │ │ │ │ └── plugin │ │ │ │ └── TracingCallback.java │ │ └── build.gradle.kts │ ├── bytebuddy │ │ ├── metadata │ │ │ └── bytebuddy.api │ │ ├── src │ │ │ └── main │ │ │ │ ├── resources │ │ │ │ └── META-INF │ │ │ │ │ └── net.bytebuddy │ │ │ │ │ └── build.plugins │ │ │ │ └── java │ │ │ │ └── co │ │ │ │ └── elastic │ │ │ │ └── otel │ │ │ │ └── android │ │ │ │ └── okhttp │ │ │ │ └── internal │ │ │ │ ├── package-info.java │ │ │ │ ├── callback │ │ │ │ └── OkHttpCallbackAdvice.java │ │ │ │ └── OkHttpClientAdvice.java │ │ └── build.gradle.kts │ └── plugin │ │ ├── metadata │ │ └── plugin.api │ │ ├── build.gradle.kts │ │ └── src │ │ └── main │ │ └── java │ │ └── co │ │ └── elastic │ │ └── otel │ │ └── android │ │ └── okhttp │ │ └── OkHttpInstrumentationPlugin.kt └── oteladapter │ ├── library │ ├── metadata │ │ └── library.api │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── co │ │ │ └── elastic │ │ │ └── otel │ │ │ └── android │ │ │ └── oteladapter │ │ │ └── internal │ │ │ ├── package-info.java │ │ │ └── delegate │ │ │ ├── tools │ │ │ ├── Delegator.kt │ │ │ └── MultipleReference.kt │ │ │ ├── meter │ │ │ └── MeterProviderDelegator.kt │ │ │ └── logger │ │ │ └── noop │ │ │ └── NoopLoggerBuilder.kt │ └── build.gradle.kts │ └── plugin │ ├── metadata │ └── plugin.api │ ├── build.gradle.kts │ └── src │ └── main │ └── java │ └── co │ └── elastic │ └── otel │ └── android │ └── oteladapter │ └── ExperimentalOtelAdapterPlugin.kt ├── android_tests.sh ├── docs ├── release-notes │ ├── toc.yml │ └── known-issues.md ├── reference │ └── edot-android │ │ ├── images │ │ ├── opentelemetry-logo.png │ │ ├── find-export-endpoint │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ └── 4.png │ │ ├── span-visualization │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ └── 3.png │ │ ├── intro │ │ │ └── distributed-tracing.png │ │ └── dynamic-config.svg │ │ └── toc.yml ├── docset.yml └── redirects.yml ├── .ci ├── release-wrapper.sh ├── upload-logs.sh └── release.sh ├── internal-tools ├── agent-rule │ ├── src │ │ └── main │ │ │ └── AndroidManifest.xml │ └── build.gradle.kts ├── test-common │ ├── src │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── co │ │ │ └── elastic │ │ │ └── otel │ │ │ └── android │ │ │ └── test │ │ │ └── common │ │ │ └── ElasticAttributes.kt │ └── build.gradle.kts ├── otel-test-common │ ├── src │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── co │ │ │ └── elastic │ │ │ └── otel │ │ │ └── android │ │ │ └── test │ │ │ └── processor │ │ │ └── SimpleProcessorFactory.kt │ └── build.gradle.kts ├── androidtest-agent-rule │ ├── src │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── co │ │ │ └── elastic │ │ │ └── otel │ │ │ └── android │ │ │ └── test │ │ │ └── rule │ │ │ └── AndroidTestAgentRule.kt │ └── build.gradle.kts └── robolectric-agent-rule │ ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── co │ │ └── elastic │ │ └── otel │ │ └── android │ │ └── test │ │ └── rule │ │ └── RobolectricAgentRule.kt │ └── build.gradle.kts ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── instrumentation.versions.toml ├── integration-test ├── app │ ├── src │ │ └── main │ │ │ ├── res │ │ │ ├── values │ │ │ │ └── strings.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── java │ │ │ └── co │ │ │ │ └── elastic │ │ │ │ └── otel │ │ │ │ └── android │ │ │ │ └── integration │ │ │ │ ├── MyApp.kt │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ └── build.gradle.kts ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradle.properties ├── settings.gradle.kts └── build.gradle.kts ├── agent-api ├── build.gradle.kts ├── metadata │ └── agent-api.api └── src │ └── main │ └── java │ └── co │ └── elastic │ └── otel │ └── android │ └── api │ ├── ElasticOtelAgent.kt │ └── flusher │ ├── MetricFlusher.kt │ ├── SpanFlusher.kt │ └── LogRecordFlusher.kt ├── .github ├── labeler-config.yml ├── community-label.yml ├── CODEOWNERS ├── workflows │ ├── docs-cleanup.yml │ ├── github-commands-comment.yml │ ├── docs-build.yml │ ├── draft-changelog.yml │ ├── catalog-info.yml │ ├── test-reporter.yml │ ├── ci-docs.yml │ ├── addToProject.yml │ └── README.md ├── scripts │ ├── generate-release-notes │ │ └── sample.json │ ├── integration-test │ │ ├── await_port.sh │ │ └── Makefile │ ├── bump-minor-version │ │ └── main.sh │ └── change-log │ │ └── draft.sh ├── dependabot.yml └── actions │ └── setup │ └── action.yml ├── instrumentation-test ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── instrumentation │ ├── okhttp │ │ ├── src │ │ │ └── main │ │ │ │ ├── java │ │ │ │ └── co │ │ │ │ │ └── elastic │ │ │ │ │ └── otel │ │ │ │ │ └── android │ │ │ │ │ └── test │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle.kts │ └── oteladapter │ │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── co │ │ │ │ │ └── elastic │ │ │ │ │ └── otel │ │ │ │ │ └── android │ │ │ │ │ └── test │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ └── androidTest │ │ │ └── java │ │ │ └── co │ │ │ └── elastic │ │ │ └── otel │ │ │ └── android │ │ │ └── test │ │ │ └── InstrumentationTest.kt │ │ └── build.gradle.kts ├── buildSrc │ ├── build.gradle.kts │ ├── settings.gradle.kts │ └── src │ │ └── main │ │ └── kotlin │ │ └── elastic.instrumentation-test-app.gradle.kts ├── gradle.properties ├── settings.gradle.kts └── build.gradle.kts ├── agent-sdk ├── src │ ├── main │ │ ├── java │ │ │ └── co │ │ │ │ └── elastic │ │ │ │ └── otel │ │ │ │ └── android │ │ │ │ ├── internal │ │ │ │ ├── package-info.java │ │ │ │ ├── provider │ │ │ │ │ ├── StringProvider.kt │ │ │ │ │ └── Provider.kt │ │ │ │ ├── services │ │ │ │ │ ├── Service.kt │ │ │ │ │ └── network │ │ │ │ │ │ ├── data │ │ │ │ │ │ ├── CarrierInfo.kt │ │ │ │ │ │ └── NetworkType.kt │ │ │ │ │ │ └── listener │ │ │ │ │ │ └── NetworkChangeListener.kt │ │ │ │ ├── opentelemetry │ │ │ │ │ ├── SignalType.kt │ │ │ │ │ └── processors │ │ │ │ │ │ ├── logs │ │ │ │ │ │ └── LogRecordAttributesProcessor.kt │ │ │ │ │ │ └── spans │ │ │ │ │ │ └── SpanAttributesProcessor.kt │ │ │ │ ├── features │ │ │ │ │ ├── exportergate │ │ │ │ │ │ ├── latch │ │ │ │ │ │ │ └── Latch.kt │ │ │ │ │ │ ├── GateSpanExporter.kt │ │ │ │ │ │ └── GateLogRecordExporter.kt │ │ │ │ │ ├── httpinterceptor │ │ │ │ │ │ └── HttpSpanExporterInterceptor.kt │ │ │ │ │ ├── clock │ │ │ │ │ │ ├── SystemTimeClock.kt │ │ │ │ │ │ ├── MutableClock.kt │ │ │ │ │ │ └── ElasticClockBroadcastReceiver.kt │ │ │ │ │ ├── centralconfig │ │ │ │ │ │ └── CentralConfiguration.kt │ │ │ │ │ └── conditionaldrop │ │ │ │ │ │ ├── ConditionalDropSpanExporter.kt │ │ │ │ │ │ └── ConditionalDropLogRecordExporter.kt │ │ │ │ ├── connectivity │ │ │ │ │ ├── ConnectivityConfiguration.kt │ │ │ │ │ └── SignalConnectivityChangeListener.kt │ │ │ │ ├── utilities │ │ │ │ │ ├── cache │ │ │ │ │ │ ├── CacheHandler.kt │ │ │ │ │ │ ├── PreferencesLongCacheHandler.kt │ │ │ │ │ │ ├── PreferencesStringCacheHandler.kt │ │ │ │ │ │ └── PreferencesIntegerCacheHandler.kt │ │ │ │ │ ├── NumberTools.kt │ │ │ │ │ ├── interceptor │ │ │ │ │ │ ├── NoopInterceptor.kt │ │ │ │ │ │ ├── MultiInterceptor.kt │ │ │ │ │ │ └── MutableInterceptor.kt │ │ │ │ │ ├── logging │ │ │ │ │ │ └── AndroidLoggerFactory.kt │ │ │ │ │ ├── AttributesOverrideLogRecordData.kt │ │ │ │ │ └── AttributesOverrideSpanData.kt │ │ │ │ ├── session │ │ │ │ │ ├── DefaultSession.kt │ │ │ │ │ └── DefaultSessionProvider.kt │ │ │ │ ├── time │ │ │ │ │ ├── SystemTimeProvider.kt │ │ │ │ │ └── ntp │ │ │ │ │ │ └── SntpClient.kt │ │ │ │ ├── api │ │ │ │ │ └── ManagedElasticOtelAgentContract.kt │ │ │ │ ├── logging │ │ │ │ │ ├── SimpleLoggingPolicy.kt │ │ │ │ │ └── DefaultLoggingPolicy.kt │ │ │ │ └── exporters │ │ │ │ │ └── configurable │ │ │ │ │ └── MutableSpanExporter.kt │ │ │ │ ├── logging │ │ │ │ └── LogLevel.kt │ │ │ │ ├── exporters │ │ │ │ ├── configuration │ │ │ │ │ └── ExportProtocol.kt │ │ │ │ ├── ExporterProvider.kt │ │ │ │ └── NoopExporterProvider.kt │ │ │ │ ├── connectivity │ │ │ │ ├── ExportEndpointConfiguration.kt │ │ │ │ └── Authentication.kt │ │ │ │ ├── features │ │ │ │ ├── session │ │ │ │ │ ├── Session.kt │ │ │ │ │ ├── SessionProvider.kt │ │ │ │ │ └── SessionIdGenerator.kt │ │ │ │ └── diskbuffering │ │ │ │ │ └── DiskBufferingConfiguration.kt │ │ │ │ └── interceptor │ │ │ │ └── Interceptor.kt │ │ └── AndroidManifest.xml │ └── test │ │ └── java │ │ └── co │ │ └── elastic │ │ └── otel │ │ └── android │ │ ├── testutils │ │ ├── DummySntpClient.kt │ │ ├── TestUdpServer.kt │ │ └── NtpUtils.kt │ │ └── internal │ │ └── logging │ │ ├── DefaultLoggingPolicyTest.kt │ │ └── SimpleLoggingPolicyTest.kt └── build.gradle.kts ├── agent-plugin ├── src │ └── main │ │ └── java │ │ └── co │ │ └── elastic │ │ └── otel │ │ └── android │ │ └── plugin │ │ ├── internal │ │ ├── package-info.java │ │ ├── BuildVariantListener.kt │ │ ├── logging │ │ │ └── GradleLoggerFactory.kt │ │ ├── ByteBuddyDependencyAttacher.kt │ │ └── InstrumentationPlugin.kt │ │ └── extensions │ │ ├── BytecodeInstrumentation.kt │ │ └── ElasticApmExtension.kt ├── metadata │ └── agent-plugin.api └── build.gradle.kts ├── gradle.properties ├── .buildkite ├── release.yml └── README.md ├── shared-rules.pro ├── renovate.json ├── install-android-sdk.sh ├── README.md ├── settings.gradle.kts ├── .gitignore └── catalog-info.yaml /.java-version: -------------------------------------------------------------------------------- 1 | 17 -------------------------------------------------------------------------------- /manual_licenses_map.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /agent-common/metadata/agent-common.api: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /checks.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | ./gradlew check -------------------------------------------------------------------------------- /instrumentation/api/metadata/api.api: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /instrumentation/okhttp/library/metadata/library.api: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /instrumentation/okhttp/bytebuddy/metadata/bytebuddy.api: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /instrumentation/oteladapter/library/metadata/library.api: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /android_tests.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | ./gradlew -p "instrumentation-test" connectedCheck 3 | -------------------------------------------------------------------------------- /docs/release-notes/toc.yml: -------------------------------------------------------------------------------- 1 | toc: 2 | - file: index.md 3 | - file: known-issues.md -------------------------------------------------------------------------------- /instrumentation/api/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.ci/release-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | .ci/release.sh | tee release.out 5 | -------------------------------------------------------------------------------- /internal-tools/agent-rule/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /internal-tools/test-common/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /internal-tools/otel-test-common/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /internal-tools/androidtest-agent-rule/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /internal-tools/robolectric-agent-rule/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /integration-test/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | EDOT Integration 3 | -------------------------------------------------------------------------------- /agent-api/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.java-library") 3 | } 4 | 5 | dependencies { 6 | api(libs.opentelemetry.sdk) 7 | } -------------------------------------------------------------------------------- /.github/labeler-config.yml: -------------------------------------------------------------------------------- 1 | # add 'agent-ios' and 'agent-mobile' label to all new issues 2 | agent-android: 3 | - '.*' 4 | agent-mobile: 5 | - '.*' -------------------------------------------------------------------------------- /.github/community-label.yml: -------------------------------------------------------------------------------- 1 | # add 'community' label to all new issues and PRs created by the community 2 | community: 3 | - '.*' 4 | triage: 5 | - '.*' -------------------------------------------------------------------------------- /integration-test/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /integration-test/gradle.properties: -------------------------------------------------------------------------------- 1 | description=Integration application for EDOT Android 2 | org.gradle.jvmargs=-XX\:MaxMetaspaceSize\=2G 3 | android.useAndroidX=true -------------------------------------------------------------------------------- /instrumentation-test/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/instrumentation-test/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /docs/reference/edot-android/images/opentelemetry-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/docs/reference/edot-android/images/opentelemetry-logo.png -------------------------------------------------------------------------------- /internal-tools/test-common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.android-test-library") 3 | } 4 | 5 | dependencies { 6 | implementation(libs.opentelemetry.sdk) 7 | } -------------------------------------------------------------------------------- /docs/reference/edot-android/images/find-export-endpoint/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/docs/reference/edot-android/images/find-export-endpoint/1.png -------------------------------------------------------------------------------- /docs/reference/edot-android/images/find-export-endpoint/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/docs/reference/edot-android/images/find-export-endpoint/2.png -------------------------------------------------------------------------------- /docs/reference/edot-android/images/find-export-endpoint/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/docs/reference/edot-android/images/find-export-endpoint/3.png -------------------------------------------------------------------------------- /docs/reference/edot-android/images/find-export-endpoint/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/docs/reference/edot-android/images/find-export-endpoint/4.png -------------------------------------------------------------------------------- /docs/reference/edot-android/images/span-visualization/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/docs/reference/edot-android/images/span-visualization/1.png -------------------------------------------------------------------------------- /docs/reference/edot-android/images/span-visualization/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/docs/reference/edot-android/images/span-visualization/2.png -------------------------------------------------------------------------------- /docs/reference/edot-android/images/span-visualization/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/docs/reference/edot-android/images/span-visualization/3.png -------------------------------------------------------------------------------- /agent-common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.java-library") 3 | } 4 | 5 | dependencies { 6 | api(libs.slf4j.api) 7 | implementation(libs.androidx.annotations) 8 | } -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /docs/reference/edot-android/images/intro/distributed-tracing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/docs/reference/edot-android/images/intro/distributed-tracing.png -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/apm-agent-android/main/integration-test/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /internal-tools/otel-test-common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.android-test-library") 3 | } 4 | 5 | dependencies { 6 | api(project(":agent-sdk")) 7 | api(libs.opentelemetry.testing) 8 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/package-info.java: -------------------------------------------------------------------------------- 1 | @InternalApi 2 | package co.elastic.otel.android.internal; 3 | 4 | import co.elastic.otel.android.common.internal.annotations.InternalApi; 5 | -------------------------------------------------------------------------------- /instrumentation-test/instrumentation/okhttp/src/main/java/co/elastic/otel/android/test/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package co.elastic.otel.android.test 2 | 3 | import android.app.Activity 4 | 5 | class MainActivity : Activity() -------------------------------------------------------------------------------- /instrumentation/okhttp/bytebuddy/src/main/resources/META-INF/net.bytebuddy/build.plugins: -------------------------------------------------------------------------------- 1 | co.elastic.otel.android.okhttp.internal.OkHttpClientPlugin 2 | co.elastic.otel.android.okhttp.internal.callback.OkHttpCallbackPlugin -------------------------------------------------------------------------------- /instrumentation-test/buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | 5 | dependencies { 6 | implementation(rootLibs.kotlin.plugin) 7 | implementation(rootLibs.android.plugin) 8 | } 9 | 10 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | *.md @elastic/ingest-docs @elastic/apm-agent-approvers 2 | /docs/ @elastic/ingest-docs @elastic/apm-agent-approvers 3 | 4 | /.github/actions @elastic/observablt-ci 5 | /.github/workflows @elastic/observablt-ci 6 | -------------------------------------------------------------------------------- /agent-common/src/main/java/co/elastic/otel/android/common/internal/package-info.java: -------------------------------------------------------------------------------- 1 | @InternalApi 2 | package co.elastic.otel.android.common.internal; 3 | 4 | import co.elastic.otel.android.common.internal.annotations.InternalApi; 5 | -------------------------------------------------------------------------------- /agent-plugin/src/main/java/co/elastic/otel/android/plugin/internal/package-info.java: -------------------------------------------------------------------------------- 1 | @InternalApi 2 | package co.elastic.otel.android.plugin.internal; 3 | 4 | import co.elastic.otel.android.common.internal.annotations.InternalApi; 5 | -------------------------------------------------------------------------------- /internal-tools/robolectric-agent-rule/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.android-test-library") 3 | } 4 | 5 | dependencies { 6 | api(project(":internal-tools:agent-rule")) 7 | implementation(libs.robolectric) 8 | } -------------------------------------------------------------------------------- /.ci/upload-logs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ## This script uploads the given logs to a google bucket 3 | ## 4 | 5 | # Let's avoid failing the build 6 | set +e 7 | 8 | ls -l $1 || true 9 | echo 'TBC upload artifacts to google' 10 | -------------------------------------------------------------------------------- /instrumentation/okhttp/library/src/main/java/co/elastic/otel/android/okhttp/internal/package-info.java: -------------------------------------------------------------------------------- 1 | @InternalApi 2 | package co.elastic.otel.android.okhttp.internal; 3 | 4 | import co.elastic.otel.android.common.internal.annotations.InternalApi; -------------------------------------------------------------------------------- /instrumentation/okhttp/bytebuddy/src/main/java/co/elastic/otel/android/okhttp/internal/package-info.java: -------------------------------------------------------------------------------- 1 | @InternalApi 2 | package co.elastic.otel.android.okhttp.internal; 3 | 4 | import co.elastic.otel.android.common.internal.annotations.InternalApi; -------------------------------------------------------------------------------- /instrumentation/api/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.android-library") 3 | } 4 | 5 | android { 6 | namespace = "co.elastic.otel.android.instrumentation.api" 7 | } 8 | 9 | dependencies { 10 | api(project(":agent-api")) 11 | } -------------------------------------------------------------------------------- /instrumentation/api/src/main/java/co/elastic/otel/android/instrumentation/internal/package-info.java: -------------------------------------------------------------------------------- 1 | @InternalApi 2 | package co.elastic.otel.android.instrumentation.internal; 3 | 4 | import co.elastic.otel.android.common.internal.annotations.InternalApi; -------------------------------------------------------------------------------- /instrumentation/oteladapter/library/src/main/java/co/elastic/otel/android/oteladapter/internal/package-info.java: -------------------------------------------------------------------------------- 1 | @InternalApi 2 | package co.elastic.otel.android.oteladapter.internal; 3 | 4 | import co.elastic.otel.android.common.internal.annotations.InternalApi; -------------------------------------------------------------------------------- /internal-tools/agent-rule/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.android-test-library") 3 | } 4 | 5 | dependencies { 6 | implementation(project(":agent-sdk")) 7 | implementation(project(":internal-tools:test-common")) 8 | implementation(libs.opentelemetry.testing) 9 | } -------------------------------------------------------------------------------- /internal-tools/androidtest-agent-rule/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.android-test-library") 3 | } 4 | 5 | dependencies { 6 | api(project(":internal-tools:agent-rule")) 7 | api(instrumentation.bundles.androidTest) 8 | api(libs.opentelemetry.testing) 9 | api(libs.assertj) 10 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /instrumentation/okhttp/plugin/metadata/plugin.api: -------------------------------------------------------------------------------- 1 | public final class co/elastic/otel/android/okhttp/OkHttpInstrumentationPlugin : co/elastic/otel/android/plugin/internal/InstrumentationPlugin { 2 | public fun ()V 3 | public fun onApply (Lorg/gradle/api/Project;Lco/elastic/otel/android/plugin/ElasticAgentPlugin;)V 4 | } 5 | 6 | -------------------------------------------------------------------------------- /integration-test/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /instrumentation-test/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /instrumentation-test/instrumentation/oteladapter/src/main/java/co/elastic/otel/android/test/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package co.elastic.otel.android.test 2 | 3 | import android.app.Activity 4 | import android.util.Log 5 | 6 | class MainActivity : Activity() { 7 | 8 | fun sendLog() { 9 | Log.d("elastic", "My log") 10 | } 11 | } -------------------------------------------------------------------------------- /instrumentation/oteladapter/plugin/metadata/plugin.api: -------------------------------------------------------------------------------- 1 | public final class co/elastic/otel/android/oteladapter/ExperimentalOtelAdapterPlugin : co/elastic/otel/android/plugin/internal/InstrumentationPlugin { 2 | public fun ()V 3 | public fun onApply (Lorg/gradle/api/Project;Lco/elastic/otel/android/plugin/ElasticAgentPlugin;)V 4 | } 5 | 6 | -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.github/workflows/docs-cleanup.yml: -------------------------------------------------------------------------------- 1 | name: docs-cleanup 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - closed 7 | 8 | jobs: 9 | docs-preview: 10 | uses: elastic/docs-builder/.github/workflows/preview-cleanup.yml@main 11 | permissions: 12 | contents: none 13 | id-token: write 14 | deployments: write -------------------------------------------------------------------------------- /integration-test/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.github/scripts/generate-release-notes/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "features_enhancements": [ 3 | { 4 | "prId": 340, 5 | "message": "Bumping upstream libs" 6 | }, 7 | { 8 | "message": "Adding consumer R8 rules" 9 | } 10 | ], 11 | "fixes": [ 12 | { 13 | "prId": 319, 14 | "message": "HTTP exporting" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | #Mon Jul 29 12:17:40 UTC 2024 2 | description=OpenTelemetry Android agent for the Elastic stack 3 | org.gradle.jvmargs=-XX\:MaxMetaspaceSize\=2G 4 | version=1.5.0 5 | android.useAndroidX=true 6 | elastic.android.minSdk=21 7 | elastic.android.compileSdk=36 8 | elastic.java.compatibility=11 9 | elastic.kotlin.compatibility=1.9 10 | group=co.elastic.otel.android 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | 5 | # GitHub actions 6 | - package-ecosystem: "github-actions" 7 | directories: 8 | - "/" 9 | - "/.github/actions/*" 10 | schedule: 11 | interval: "weekly" 12 | day: "sunday" 13 | time: "22:00" 14 | groups: 15 | github-actions: 16 | patterns: 17 | - "*" 18 | -------------------------------------------------------------------------------- /instrumentation/okhttp/bytebuddy/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.instrumentation-library") 3 | } 4 | 5 | android { 6 | namespace = "co.elastic.otel.android.instrumentation.okhttp.bytebuddy" 7 | } 8 | 9 | dependencies { 10 | implementation(project(":instrumentation:okhttp:library")) 11 | implementation(libs.byteBuddy) 12 | implementation(libs.okhttp) 13 | } -------------------------------------------------------------------------------- /.github/workflows/github-commands-comment.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: github-commands-comment 3 | 4 | on: 5 | pull_request_target: 6 | types: 7 | - opened 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | comment: 14 | runs-on: ubuntu-latest 15 | permissions: 16 | pull-requests: write 17 | steps: 18 | - uses: elastic/oblt-actions/elastic/github-commands@v1 19 | -------------------------------------------------------------------------------- /instrumentation-test/gradle.properties: -------------------------------------------------------------------------------- 1 | # AndroidX package structure to make it clearer which packages are bundled with the 2 | # Android operating system, and which are packaged with your app"s APK 3 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 4 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 5 | android.useAndroidX=true -------------------------------------------------------------------------------- /docs/reference/edot-android/toc.yml: -------------------------------------------------------------------------------- 1 | toc: 2 | - file: index.md 3 | - file: getting-started.md 4 | - file: configuration.md 5 | - file: manual-instrumentation.md 6 | - file: automatic-instrumentation.md 7 | - title: Troubleshooting 8 | crosslink: docs-content://troubleshoot/ingest/opentelemetry/edot-sdks/android/index.md 9 | - title: Release notes 10 | crosslink: apm-agent-android://release-notes/index.md -------------------------------------------------------------------------------- /.github/workflows/docs-build.yml: -------------------------------------------------------------------------------- 1 | name: docs-build 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request_target: ~ 8 | 9 | jobs: 10 | docs-preview: 11 | uses: elastic/docs-builder/.github/workflows/preview-build.yml@main 12 | with: 13 | path-pattern: docs/** 14 | permissions: 15 | deployments: write 16 | id-token: write 17 | contents: read 18 | pull-requests: write -------------------------------------------------------------------------------- /.github/workflows/draft-changelog.yml: -------------------------------------------------------------------------------- 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@v6 14 | with: 15 | fetch-depth: 0 16 | - name: Run changelog draft script 17 | run: ./.github/scripts/change-log/draft.sh 18 | -------------------------------------------------------------------------------- /.buildkite/release.yml: -------------------------------------------------------------------------------- 1 | agents: 2 | provider: "gcp" 3 | image: "family/apm-agent-android-ubuntu-2204" 4 | 5 | env: 6 | TARBALL_FILE: ${TARBALL_FILE:-dist.tar} 7 | 8 | steps: 9 | - label: "Run the release" 10 | key: "release" 11 | commands: .ci/release-wrapper.sh 12 | artifact_paths: 13 | - "release.out" 14 | - "${TARBALL_FILE}" 15 | 16 | notify: 17 | - slack: 18 | channels: 19 | - "#apm-agent-mobile" 20 | -------------------------------------------------------------------------------- /instrumentation-test/instrumentation/okhttp/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.instrumentation-test-app") 3 | id("co.elastic.otel.android.agent") 4 | id("co.elastic.otel.android.instrumentation.okhttp") 5 | } 6 | 7 | android { 8 | namespace = "co.elastic.otel.android.test.okhttp" 9 | } 10 | 11 | dependencies { 12 | androidTestImplementation(libs.okhttp) 13 | androidTestImplementation(instrumentation.mockWebServer) 14 | } -------------------------------------------------------------------------------- /instrumentation/okhttp/plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.instrumentation-plugin") 3 | } 4 | 5 | elasticBuildConfig { 6 | libraryUri() 7 | byteBuddyPluginUri() 8 | } 9 | 10 | elasticInstrumentationPlugins { 11 | create { 12 | implementationClass = "co.elastic.otel.android.okhttp.OkHttpInstrumentationPlugin" 13 | displayName = "Elastic OTel Android instrumentation for tracking OkHttp requests" 14 | } 15 | } -------------------------------------------------------------------------------- /.github/workflows/catalog-info.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: catalog-info 3 | 4 | on: 5 | pull_request: 6 | branches: 7 | - main 8 | paths: 9 | - 'catalog-info.yaml' 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | validate: 16 | runs-on: ubuntu-latest 17 | permissions: 18 | contents: read 19 | packages: read 20 | steps: 21 | - uses: actions/checkout@v6 22 | 23 | - uses: elastic/oblt-actions/elastic/validate-catalog@v1 24 | 25 | -------------------------------------------------------------------------------- /instrumentation/okhttp/library/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.instrumentation-library") 3 | } 4 | 5 | android { 6 | namespace = "co.elastic.otel.android.instrumentation.okhttp" 7 | } 8 | 9 | dependencies { 10 | implementation(instrumentation.opentelemetry.instrumentation.api) 11 | implementation(instrumentation.opentelemetry.instrumentation.api.incubator) 12 | implementation(instrumentation.opentelemetry.instrumentation.okhttp) 13 | compileOnly(libs.okhttp) 14 | } -------------------------------------------------------------------------------- /instrumentation/oteladapter/plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.instrumentation-plugin") 3 | } 4 | 5 | elasticBuildConfig { 6 | libraryUri() 7 | } 8 | 9 | elasticInstrumentationPlugins { 10 | create(extraTags = listOf("experimental")) { 11 | implementationClass = "co.elastic.otel.android.oteladapter.ExperimentalOtelAdapterPlugin" 12 | displayName = 13 | "Elastic OTel Android experimental instrumentation adapter for OTel Android instrumentations" 14 | } 15 | } -------------------------------------------------------------------------------- /instrumentation/oteladapter/library/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.instrumentation-library") 3 | } 4 | 5 | android { 6 | namespace = "co.elastic.otel.android.instrumentation.oteladapter" 7 | } 8 | 9 | dependencies { 10 | implementation(instrumentation.opentelemetry.android.session) 11 | implementation(instrumentation.opentelemetry.android.instrumentation) 12 | implementation(instrumentation.opentelemetry.instrumentation.api.incubator) 13 | implementation(instrumentation.weakLockFree) 14 | } -------------------------------------------------------------------------------- /internal-tools/robolectric-agent-rule/src/main/java/co/elastic/otel/android/test/rule/RobolectricAgentRule.kt: -------------------------------------------------------------------------------- 1 | package co.elastic.otel.android.test.rule 2 | 3 | import android.app.Application 4 | import org.robolectric.RuntimeEnvironment 5 | 6 | class RobolectricAgentRule : AgentRule() { 7 | 8 | override fun runInitialization(initialization: () -> Unit) { 9 | initialization() 10 | } 11 | 12 | override fun getApplication(): Application { 13 | return RuntimeEnvironment.getApplication() 14 | } 15 | } -------------------------------------------------------------------------------- /instrumentation-test/buildSrc/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | mavenCentral() 4 | google() 5 | gradlePluginPortal() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | versionCatalogs { 10 | create("rootLibs") { 11 | from(files("../../gradle/libs.versions.toml")) 12 | } 13 | } 14 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 15 | repositories { 16 | mavenCentral() 17 | google() 18 | gradlePluginPortal() 19 | } 20 | } -------------------------------------------------------------------------------- /.github/scripts/integration-test/await_port.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | port_to_wait=$1 4 | max_seconds_to_wait=$2 5 | waited_seconds=0 6 | timedout=0 7 | while ! nc -z localhost "$port_to_wait"; do 8 | if [ $waited_seconds == "$max_seconds_to_wait" ]; then 9 | timedout=1 10 | break 11 | fi 12 | echo "$waited_seconds/$max_seconds_to_wait seconds waiting for port $port_to_wait to open" 13 | sleep 1 14 | waited_seconds=$((waited_seconds+1)) 15 | done 16 | if [ $timedout == 1 ]; then 17 | echo "Timeout waiting for the port $port_to_wait to open" 18 | exit 1 19 | fi 20 | -------------------------------------------------------------------------------- /shared-rules.pro: -------------------------------------------------------------------------------- 1 | -keepclassmembers enum io.opentelemetry.** { 2 | public static **[] values(); 3 | } 4 | -keepclassmembers enum co.elastic.otel.android.** { 5 | public static **[] values(); 6 | } 7 | -keep class io.opentelemetry.api.incubator.** { *; } 8 | -dontwarn com.fasterxml.jackson.** 9 | -dontwarn com.google.auto.service.AutoService 10 | -dontwarn com.google.auto.value.** 11 | -dontwarn com.google.common.io.ByteStreams 12 | -dontwarn com.google.errorprone.annotations.** 13 | -dontwarn io.grpc.** 14 | -dontwarn java.awt.** 15 | -dontwarn javax.json.bind.spi.JsonbProvider 16 | -------------------------------------------------------------------------------- /.github/scripts/bump-minor-version/main.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | bump_minor_version() { 4 | local version="$1" 5 | 6 | if [[ $version =~ ^([0-9]+)\.([0-9]+)[0-9\.]*$ ]]; then 7 | local major_version=${BASH_REMATCH[1]} 8 | local minor_version=${BASH_REMATCH[2]} 9 | 10 | local new_minor_version=$((minor_version + 1)) 11 | local new_version="$major_version.$new_minor_version.0" 12 | 13 | echo "$new_version" 14 | else 15 | echo "Could not find minor version in: $version" >&2 16 | return 1 17 | fi 18 | } 19 | 20 | bump_minor_version "$1" 21 | -------------------------------------------------------------------------------- /instrumentation-test/instrumentation/okhttp/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /instrumentation-test/instrumentation/oteladapter/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.instrumentation-test-app") 3 | id("co.elastic.otel.android.agent") 4 | id("co.elastic.otel.android.instrumentation.oteladapter") 5 | } 6 | 7 | android { 8 | namespace = "co.elastic.otel.android.test.oteladapter" 9 | } 10 | 11 | val logInstrumentationVersion = "0.11.0-alpha" 12 | dependencies { 13 | implementation("io.opentelemetry.android.instrumentation:android-log-library:$logInstrumentationVersion") 14 | byteBuddy("io.opentelemetry.android.instrumentation:android-log-agent:$logInstrumentationVersion") 15 | } -------------------------------------------------------------------------------- /integration-test/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | mavenCentral() 4 | google() 5 | gradlePluginPortal() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | versionCatalogs { 10 | create("rootLibs") { 11 | from(files("../gradle/libs.versions.toml")) 12 | } 13 | } 14 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 15 | repositories { 16 | mavenCentral() 17 | google() 18 | } 19 | } 20 | rootProject.name = "EDOT Android ES integration test" 21 | includeBuild("..") 22 | include(":app") 23 | -------------------------------------------------------------------------------- /instrumentation-test/instrumentation/oteladapter/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /integration-test/app/src/main/java/co/elastic/otel/android/integration/MyApp.kt: -------------------------------------------------------------------------------- 1 | package co.elastic.otel.android.integration 2 | 3 | import android.app.Application 4 | import co.elastic.otel.android.ElasticApmAgent 5 | import co.elastic.otel.android.api.ElasticOtelAgent 6 | 7 | class MyApp : Application() { 8 | companion object { 9 | internal lateinit var agent: ElasticOtelAgent 10 | } 11 | 12 | override fun onCreate() { 13 | super.onCreate() 14 | agent = ElasticApmAgent.builder(this) 15 | .setExportUrl("http://10.0.2.2:4318") 16 | .setServiceName("integration-test-app") 17 | .build() 18 | } 19 | } -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | name: common build tasks 4 | description: Install specific JDK 5 | 6 | inputs: 7 | java-version: 8 | description: 'Testing Java version' 9 | required: true 10 | default: '17' 11 | java-distribution: 12 | description: 'Testing Java distribution' 13 | required: true 14 | default: 'temurin' 15 | shell: 16 | description: 'Default shell' 17 | default: 'bash' 18 | required: false 19 | 20 | runs: 21 | using: "composite" 22 | steps: 23 | - name: Set up testing JDK 24 | uses: actions/setup-java@v5 25 | with: 26 | java-version: ${{ inputs.java-version }} 27 | distribution: ${{ inputs.java-distribution }} 28 | -------------------------------------------------------------------------------- /.buildkite/README.md: -------------------------------------------------------------------------------- 1 | # Buildkite 2 | 3 | This README provides an overview of the Buildkite pipeline to automate the build and publishing process. 4 | 5 | ## Release pipeline 6 | 7 | The Buildkite pipeline for the APM Agent Android is responsible for the releases. 8 | 9 | ### Pipeline Configuration 10 | 11 | To view the pipeline and its configuration, click [here](https://buildkite.com/elastic/apm-agent-android-release) or 12 | go to the definition in the `elastic/ci` repository. 13 | 14 | ### Credentials 15 | 16 | The release team provides the credentials to publish the artifacts in Maven Central/Gradle Plugin and sign them 17 | with the GPG. 18 | 19 | If further details are needed, please go to [pre-command](hooks/pre-command). 20 | -------------------------------------------------------------------------------- /agent-sdk/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/docset.yml: -------------------------------------------------------------------------------- 1 | project: 'APM Android agent docs' 2 | products: 3 | - id: apm-agent 4 | cross_links: 5 | - docs-content 6 | - opentelemetry 7 | - elastic-agent 8 | - apm-agent-android 9 | toc: 10 | - toc: release-notes 11 | - toc: reference/edot-android 12 | subs: 13 | motlp: Elastic Cloud Managed OTLP Endpoint 14 | edot: Elastic Distribution of OpenTelemetry 15 | ecloud: "Elastic Cloud" 16 | edot-cf: "EDOT Cloud Forwarder" 17 | ech: "Elastic Cloud Hosted" 18 | ess: "Elasticsearch Service" 19 | ece: "Elastic Cloud Enterprise" 20 | serverless-full: "Elastic Cloud Serverless" 21 | agent: "Elastic Agent" 22 | agents: "Elastic Agents" 23 | stack: "Elastic Stack" 24 | es: "Elasticsearch" 25 | kib: "Kibana" 26 | ls: "Logstash" 27 | 28 | -------------------------------------------------------------------------------- /integration-test/app/src/main/java/co/elastic/otel/android/integration/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package co.elastic.otel.android.integration 2 | 3 | import android.app.Activity 4 | import android.os.Bundle 5 | import co.elastic.otel.android.extensions.log 6 | import co.elastic.otel.android.extensions.span 7 | import co.elastic.otel.android.integration.MyApp.Companion.agent 8 | 9 | class MainActivity : Activity() { 10 | 11 | override fun onCreate(savedInstanceState: Bundle?) { 12 | super.onCreate(savedInstanceState) 13 | 14 | val meter = agent.getOpenTelemetry().getMeter("co.elastic.android.integration") 15 | meter.counterBuilder("meter counter").build().add(5) 16 | 17 | agent.span("span name") { 18 | agent.log("log body") 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /agent-api/metadata/agent-api.api: -------------------------------------------------------------------------------- 1 | public abstract interface class co/elastic/otel/android/api/ElasticOtelAgent : java/io/Closeable { 2 | public abstract fun getOpenTelemetry ()Lio/opentelemetry/api/OpenTelemetry; 3 | } 4 | 5 | public abstract interface class co/elastic/otel/android/api/flusher/LogRecordFlusher { 6 | public abstract fun flushLogRecords ()Lio/opentelemetry/sdk/common/CompletableResultCode; 7 | } 8 | 9 | public abstract interface class co/elastic/otel/android/api/flusher/MetricFlusher { 10 | public abstract fun flushMetrics ()Lio/opentelemetry/sdk/common/CompletableResultCode; 11 | } 12 | 13 | public abstract interface class co/elastic/otel/android/api/flusher/SpanFlusher { 14 | public abstract fun flushSpans ()Lio/opentelemetry/sdk/common/CompletableResultCode; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /internal-tools/androidtest-agent-rule/src/main/java/co/elastic/otel/android/test/rule/AndroidTestAgentRule.kt: -------------------------------------------------------------------------------- 1 | package co.elastic.otel.android.test.rule 2 | 3 | import android.annotation.SuppressLint 4 | import android.app.Application 5 | import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread 6 | import androidx.test.platform.app.InstrumentationRegistry 7 | 8 | class AndroidTestAgentRule : AgentRule() { 9 | 10 | @SuppressLint("RestrictedApi") 11 | override fun runInitialization(initialization: () -> Unit) { 12 | runOnUiThread { 13 | initialization() 14 | } 15 | } 16 | 17 | override fun getApplication(): Application { 18 | return InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as Application 19 | } 20 | } -------------------------------------------------------------------------------- /integration-test/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.github/workflows/test-reporter.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ## Workflow to process the JUnit test results and add a report to the checks. 3 | name: test-reporter 4 | on: 5 | workflow_run: 6 | workflows: 7 | - ci 8 | - release 9 | - snapshoty 10 | types: 11 | - completed 12 | 13 | permissions: 14 | contents: read 15 | actions: read 16 | checks: write 17 | 18 | jobs: 19 | report: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: elastic/oblt-actions/test-report@v1 23 | with: 24 | artifact: /test-results(.*)/ # artifact name pattern 25 | name: 'Test Report $1' # Name of the check run which will be created 26 | path: "**/*.xml" # Path to test results (inside artifact .zip) 27 | reporter: java-junit # Format of test results 28 | -------------------------------------------------------------------------------- /agent-plugin/metadata/agent-plugin.api: -------------------------------------------------------------------------------- 1 | public final class co/elastic/otel/android/plugin/ElasticAgentPlugin : org/gradle/api/Plugin { 2 | public fun ()V 3 | public final fun addBuildVariantListener (Lco/elastic/otel/android/plugin/internal/BuildVariantListener;)V 4 | public synthetic fun apply (Ljava/lang/Object;)V 5 | public fun apply (Lorg/gradle/api/Project;)V 6 | } 7 | 8 | public abstract interface class co/elastic/otel/android/plugin/extensions/BytecodeInstrumentation { 9 | public abstract fun getDisableForBuildTypes ()Lorg/gradle/api/provider/ListProperty; 10 | } 11 | 12 | public abstract class co/elastic/otel/android/plugin/extensions/ElasticApmExtension { 13 | public fun (Lorg/gradle/api/model/ObjectFactory;)V 14 | public final fun bytecodeInstrumentation (Lorg/gradle/api/Action;)V 15 | public final fun getBytecodeInstrumentation ()Lco/elastic/otel/android/plugin/extensions/BytecodeInstrumentation; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /integration-test/app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | plugins { 4 | id("com.android.application") 5 | id("org.jetbrains.kotlin.android") 6 | id("co.elastic.otel.android.agent") 7 | id("co.elastic.otel.android.instrumentation.okhttp") 8 | } 9 | 10 | android { 11 | namespace = "co.elastic.otel.android.integration" 12 | compileSdk = 36 13 | 14 | defaultConfig { 15 | applicationId = "co.elastic.otel.android.integration" 16 | minSdk = 26 17 | } 18 | 19 | buildTypes { 20 | release { 21 | isMinifyEnabled = true 22 | signingConfig = signingConfigs["debug"] 23 | } 24 | } 25 | compileOptions { 26 | sourceCompatibility = JavaVersion.VERSION_1_8 27 | targetCompatibility = JavaVersion.VERSION_1_8 28 | } 29 | } 30 | kotlin { 31 | compilerOptions { 32 | jvmTarget.set(JvmTarget.JVM_1_8) 33 | } 34 | } -------------------------------------------------------------------------------- /agent-plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.java-library") 3 | id("java-gradle-plugin") 4 | id("com.github.gmazzo.buildconfig") 5 | } 6 | 7 | dependencies { 8 | api(project(":agent-common")) 9 | implementation(libs.byteBuddy) 10 | implementation(libs.byteBuddy.plugin) 11 | compileOnly(libs.android.plugin) 12 | } 13 | 14 | buildConfig { 15 | packageName("${group}.generated") 16 | buildConfigField("String", "SDK_DEPENDENCY_URI", "\"$group:agent-sdk:$version\"") 17 | } 18 | 19 | gradlePlugin { 20 | plugins { 21 | create("elasticAndroidAgent") { 22 | id = "co.elastic.otel.android.agent" 23 | implementationClass = "co.elastic.otel.android.plugin.ElasticAgentPlugin" 24 | displayName = "Elastic OTel Android Agent" 25 | description = project.description 26 | tags.addAll("Android", "APM", "Elastic", "ELK", "opentelemetry") 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /docs/redirects.yml: -------------------------------------------------------------------------------- 1 | # Related to https://github.com/elastic/opentelemetry/issues/228 2 | redirects: 3 | 'release-notes/apm/agents/android/index.md': 'release-notes/index.md' 4 | 'reference/apm/agents/android/index.md': 'reference/edot-android/index.md' 5 | 'reference/apm/agents/android/getting-started.md': 'reference/edot-android/getting-started.md' 6 | 'reference/apm/agents/android/configuration.md': 'reference/edot-android/configuration.md' 7 | 'reference/apm/agents/android/manual-instrumentation.md': 'reference/edot-android/manual-instrumentation.md' 8 | 'reference/apm/agents/android/automatic-instrumentation.md': 'reference/edot-android/automatic-instrumentation.md' 9 | 'reference/apm/agents/android/faq.md': 'reference/edot-android/index.md' 10 | 'reference/apm/agents/android/how-tos.md': 'reference/edot-android/getting-started.md' 11 | 'reference/apm/agents/android/troubleshooting': 'opentelemetry://reference/edot-sdks/android/troubleshooting.md' 12 | -------------------------------------------------------------------------------- /internal-tools/test-common/src/main/java/co/elastic/otel/android/test/common/ElasticAttributes.kt: -------------------------------------------------------------------------------- 1 | package co.elastic.otel.android.test.common 2 | 3 | import io.opentelemetry.api.common.Attributes 4 | 5 | object ElasticAttributes { 6 | const val DEFAULT_SESSION_ID = "session-id" 7 | const val DEFAULT_NETWORK_CONNECTION_TYPE = "unavailable" 8 | 9 | fun getLogRecordDefaultAttributes( 10 | sessionId: String = DEFAULT_SESSION_ID, 11 | networkConnectionType: String = DEFAULT_NETWORK_CONNECTION_TYPE 12 | ): Attributes = 13 | Attributes.builder() 14 | .put("session.id", sessionId) 15 | .put("network.connection.type", networkConnectionType) 16 | .build() 17 | 18 | fun getSpanDefaultAttributes(logRecordAttributes: Attributes = getLogRecordDefaultAttributes()): Attributes = 19 | Attributes.builder() 20 | .putAll(logRecordAttributes) 21 | .put("type", "mobile") 22 | .build() 23 | } -------------------------------------------------------------------------------- /docs/reference/edot-android/images/dynamic-config.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | Dynamic 18 | 19 | Dynamic 20 | 21 | -------------------------------------------------------------------------------- /.github/scripts/change-log/draft.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | version=$(cat gradle.properties | grep version= | sed s/version=//g) 4 | 5 | if [[ $version =~ ([0-9]+)\.([0-9]+)\.0 ]]; then 6 | echo "Version found: ${version}" 7 | major="${BASH_REMATCH[1]}" 8 | minor="${BASH_REMATCH[2]}" 9 | else 10 | echo "unexpected version: $version" 11 | exit 1 12 | fi 13 | 14 | if [[ $minor == 0 ]]; then 15 | prior_major=$((major - 1)) 16 | prior_minor=$(sed -n "s/^## Version $prior_major\.\([0-9]\+\)\..*/\1/p" CHANGELOG.md | head -1) 17 | if [[ -z $prior_minor ]]; then 18 | # assuming this is the first release 19 | range= 20 | else 21 | range="v$prior_major.$prior_minor.0..HEAD" 22 | fi 23 | else 24 | range="v$major.$((minor - 1)).0..HEAD" 25 | fi 26 | 27 | echo "[$( 28 | git log --reverse \ 29 | --perl-regexp \ 30 | --author='^((?!elastic-renovate).*)$' \ 31 | --pretty=format:"%s" \ 32 | "$range" \ 33 | | sed -r 's;^(.+) \(#([0-9]+)\)$;{"message":"\1", "prId":"\2"},;g' \ 34 | | sed '$ s/,$//g' 35 | )]" -------------------------------------------------------------------------------- /docs/release-notes/known-issues.md: -------------------------------------------------------------------------------- 1 | --- 2 | navigation_title: "Known issues" 3 | description: Known issues for the Elastic Distribution of OpenTelemetry Android. 4 | applies_to: 5 | stack: 6 | serverless: 7 | observability: 8 | products: 9 | - id: cloud-serverless 10 | - id: observability 11 | - id: edot-sdk 12 | --- 13 | 14 | # Elastic Distribution of OpenTelemetry Android known issues 15 | 16 | Known issues are significant defects or limitations that may impact your implementation. These issues are actively being worked on and will be addressed in a future release. Review known issues to help you make informed decisions, such as upgrading to a new version. 17 | 18 | % Use the following template to add entries to this page. 19 | 20 | % :::{dropdown} Title of known issue 21 | % **Details** 22 | % On [Month/Day/Year], a known issue was discovered that [description of known issue]. 23 | 24 | % **Workaround** 25 | % Workaround description. 26 | 27 | % **Resolved** 28 | % On [Month/Day/Year], this issue was resolved. 29 | 30 | ::: 31 | 32 | _No known issues_ -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/logging/LogLevel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.logging 20 | 21 | enum class LogLevel(val value: Int) { 22 | TRACE(0), DEBUG(1), INFO(2), WARN(3), ERROR(4) 23 | } 24 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "local>elastic/renovate-config" 5 | ], 6 | "ignorePaths": [ 7 | ".ci/**", 8 | ".buildkite/**", 9 | ".github/*", 10 | ".github/actions/**", 11 | ".github/workflows/*" 12 | ], 13 | "packageRules": [ 14 | { 15 | "matchPackageNames": [ 16 | "io.opentelemetry:**" 17 | ], 18 | "ignoreUnstable": false, 19 | "groupName": "otel-core" 20 | }, 21 | { 22 | "matchPackageNames": [ 23 | "io.opentelemetry.contrib:**" 24 | ], 25 | "ignoreUnstable": false, 26 | "groupName": "otel-contrib" 27 | }, 28 | { 29 | "matchPackageNames": [ 30 | "io.opentelemetry.semconv:**" 31 | ], 32 | "ignoreUnstable": false, 33 | "groupName": "otel-semconv" 34 | }, 35 | { 36 | "matchPackageNames": [ 37 | "io.opentelemetry.instrumentation:**" 38 | ], 39 | "ignoreUnstable": false, 40 | "groupName": "otel-instrumentation" 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /install-android-sdk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | SDKDIR=$PWD/.android-sdk 6 | export ANDROID_SDK_ROOT=${SDKDIR} 7 | export ANDROID_HOME=${SDKDIR} 8 | export ANDROID_AVD_HOME=${SDKDIR}/avd 9 | 10 | mkdir ${SDKDIR} 11 | mkdir ${SDKDIR}/cmdline-tools 12 | 13 | echo Downloading Android SDK... 14 | cd ${SDKDIR}/cmdline-tools 15 | COMMAND_LINE_TOOLS_ZIP=${SDKDIR}/commandlinetools.zip 16 | # https://developer.android.com/studio#command-tools 17 | TYPE=linux 18 | if [[ "$OSTYPE" == "darwin"* ]]; then 19 | TYPE=mac 20 | fi 21 | curl -q https://dl.google.com/android/repository/commandlinetools-${TYPE}-8512546_latest.zip -o ${COMMAND_LINE_TOOLS_ZIP} 22 | unzip ${COMMAND_LINE_TOOLS_ZIP} 23 | rm ${COMMAND_LINE_TOOLS_ZIP} 24 | mv cmdline-tools latest 25 | ln -s ${SDKDIR}/cmdline-tools/latest ${SDKDIR}/tools 26 | 27 | echo Installing emulator... 28 | yes | ${ANDROID_HOME}/tools/bin/sdkmanager --install platform-tools emulator 29 | 30 | echo Installing platform SDK... 31 | yes | ${ANDROID_HOME}/tools/bin/sdkmanager --install "platforms;android-33" 32 | 33 | echo Starting ADB... 34 | ${ANDROID_HOME}/platform-tools/adb devices 35 | -------------------------------------------------------------------------------- /instrumentation-test/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | mavenCentral() 5 | google() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | versionCatalogs { 10 | create("libs") { 11 | from(files("../gradle/libs.versions.toml")) 12 | } 13 | create("instrumentation") { 14 | from(files("../gradle/instrumentation.versions.toml")) 15 | } 16 | } 17 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 18 | repositories { 19 | mavenCentral() 20 | google() 21 | } 22 | } 23 | includeBuild("..") 24 | 25 | val instrumentationDirName = "instrumentation" 26 | val instrumentationDir = File(rootDir, instrumentationDirName) 27 | val separator = Regex("[/\\\\]") 28 | instrumentationDir.walk().maxDepth(2).forEach { 29 | if (it.name.equals("build.gradle.kts")) { 30 | include( 31 | ":$instrumentationDirName:${ 32 | it.parentFile.toRelativeString(instrumentationDir).replace(separator, ":") 33 | }" 34 | ) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.github/workflows/ci-docs.yml: -------------------------------------------------------------------------------- 1 | # This workflow sets the ci / ci status check to success in case it's a docs only PR and ci.yml is not triggered 2 | # https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks 3 | name: ci # The name must be the same as in ci.yml 4 | 5 | on: 6 | pull_request: 7 | paths-ignore: # This expression needs to match the paths ignored on ci.yml. 8 | - '**' 9 | - '!**/*.md' 10 | - '!**/*.asciidoc' 11 | - '!**/*.png' 12 | 13 | permissions: 14 | contents: read 15 | 16 | ## Concurrency only allowed in the main branch. 17 | ## So old builds running for old commits within the same Pull Request are cancelled 18 | concurrency: 19 | group: ${{ github.workflow }}-${{ github.ref }} 20 | cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} 21 | 22 | jobs: 23 | 24 | # dummy steps that allow to bypass those mandatory checks for tests 25 | ci: 26 | runs-on: ubuntu-latest 27 | steps: 28 | - run: 'echo "Not required for docs"' 29 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/exporters/configuration/ExportProtocol.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.exporters.configuration 20 | 21 | /** 22 | * The protocol used to contact the Elastic server. 23 | */ 24 | enum class ExportProtocol { 25 | HTTP, 26 | GRPC 27 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # apm-agent-android 2 | 3 | Elastic OTel Android Agent 4 | 5 | See the [documentation](https://www.elastic.co/docs/reference/opentelemetry/edot-sdks/android) to find out more about its features, how to setup, and configuration details. 6 | 7 | ## Try it out 8 | 9 | Follow the [Demo application guide](https://github.com/elastic/android-agent-demo) to set up a test environment and take a quick 10 | look at the agent's functionalities. 11 | 12 | ## Publishing it locally 13 | 14 | In order to use a local build for your local projects, you'll need to publish it into your machine's 15 | maven local repo. To do so, open up a terminal in this project's root dir and 16 | run: `./gradlew publishToMavenLocal`. After that, you can apply the agent into an Android 17 | application project (that uses [mavenLocal()](https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.api.artifacts.dsl/-repository-handler/maven-local.html) as one of its dependency repositories) 18 | by following the [Getting started](https://www.elastic.co/docs/reference/opentelemetry/edot-sdks/android/getting-started) guide and using the version defined [here](gradle.properties). 19 | -------------------------------------------------------------------------------- /.github/workflows/addToProject.yml: -------------------------------------------------------------------------------- 1 | name: Auto Assign to Project(s) 2 | 3 | on: 4 | issues: 5 | types: [opened, edited, milestoned] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | assign_one_project: 12 | runs-on: ubuntu-latest 13 | name: Assign milestoned to Project 14 | steps: 15 | - name: Get token 16 | id: get_token 17 | uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0 18 | with: 19 | app_id: ${{ secrets.OBS_AUTOMATION_APP_ID }} 20 | private_key: ${{ secrets.OBS_AUTOMATION_APP_PEM }} 21 | permissions: >- 22 | { 23 | "organization_projects": "write", 24 | "issues": "read" 25 | } 26 | 27 | - name: Assign issues with milestones to project 28 | uses: elastic/assign-one-project-github-action@1.2.2 29 | if: github.event.issue && github.event.issue.milestone 30 | with: 31 | project: 'https://github.com/orgs/elastic/projects/454' 32 | project_id: '5882982' 33 | column_name: 'Planned' 34 | env: 35 | MY_GITHUB_TOKEN: ${{ steps.get_token.outputs.token }} 36 | -------------------------------------------------------------------------------- /agent-plugin/src/main/java/co/elastic/otel/android/plugin/extensions/BytecodeInstrumentation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.plugin.extensions 20 | 21 | import org.gradle.api.provider.ListProperty 22 | 23 | interface BytecodeInstrumentation { 24 | val disableForBuildTypes: ListProperty 25 | } 26 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/provider/StringProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.provider 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | fun interface StringProvider : Provider -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/provider/Provider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.provider 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | fun interface Provider { 26 | fun get(): T 27 | } -------------------------------------------------------------------------------- /agent-common/src/main/java/co/elastic/otel/android/common/internal/annotations/InternalApi.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.common.internal.annotations 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | annotation class InternalApi 26 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/services/Service.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.services 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | internal interface Service { 26 | fun start() {} 27 | 28 | fun stop() {} 29 | } -------------------------------------------------------------------------------- /agent-plugin/src/main/java/co/elastic/otel/android/plugin/internal/BuildVariantListener.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.plugin.internal 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | interface BuildVariantListener { 26 | fun onBuildVariant(name: String) 27 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/opentelemetry/SignalType.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.opentelemetry 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | internal enum class SignalType { 26 | TRACE, 27 | METRIC, 28 | LOG 29 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/features/exportergate/latch/Latch.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.features.exportergate.latch 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | internal data class Latch(val gateName: String, val name: String) -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/connectivity/ExportEndpointConfiguration.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.connectivity 20 | 21 | import co.elastic.otel.android.exporters.configuration.ExportProtocol 22 | 23 | data class ExportEndpointConfiguration( 24 | val url: String, 25 | val authentication: Authentication, 26 | val protocol: ExportProtocol 27 | ) -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/services/network/data/CarrierInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.services.network.data 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | internal data class CarrierInfo(val name: String, val mcc: String, val mnc: String, val icc: String) 26 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/connectivity/ConnectivityConfiguration.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.connectivity 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | interface ConnectivityConfiguration { 26 | fun getUrl(): String 27 | 28 | fun getHeaders(): Map 29 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/cache/CacheHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities.cache 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | internal interface CacheHandler { 26 | fun retrieve(): T? 27 | 28 | fun store(value: T) 29 | 30 | fun clear() 31 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/features/session/Session.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.features.session 20 | 21 | import co.elastic.otel.android.internal.session.DefaultSession 22 | 23 | interface Session { 24 | fun getId(): String 25 | 26 | companion object { 27 | @JvmStatic 28 | fun create(id: String): Session { 29 | return DefaultSession(id) 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/NumberTools.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities 20 | 21 | import java.util.Random 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | internal class NumberTools { 28 | fun random(): Double { 29 | return Random().nextDouble() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /agent-sdk/src/test/java/co/elastic/otel/android/testutils/DummySntpClient.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.testutils 20 | 21 | import co.elastic.otel.android.internal.time.ntp.SntpClient 22 | 23 | internal class DummySntpClient : SntpClient { 24 | 25 | override fun fetchTimeOffset(currentTimeMillis: Long): SntpClient.Response { 26 | return SntpClient.Response.Success(0) 27 | } 28 | 29 | override fun close() { 30 | } 31 | } -------------------------------------------------------------------------------- /agent-api/src/main/java/co/elastic/otel/android/api/ElasticOtelAgent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.api 20 | 21 | import io.opentelemetry.api.OpenTelemetry 22 | import java.io.Closeable 23 | 24 | /** 25 | * Entry point for the Elastic Android OpenTelemetry agent. 26 | */ 27 | interface ElasticOtelAgent : Closeable { 28 | 29 | /** 30 | * Provides the underlying [OpenTelemetry] instance. 31 | */ 32 | fun getOpenTelemetry(): OpenTelemetry 33 | } -------------------------------------------------------------------------------- /instrumentation-test/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.util.Properties 2 | 3 | val agentProperties = Properties() 4 | val propertiesFile = File(rootDir, "../gradle.properties") 5 | propertiesFile.inputStream().use { 6 | agentProperties.load(it) 7 | } 8 | val agentVersion = agentProperties["version"] 9 | 10 | extra.apply { 11 | set("jvmCompatibility", JavaVersion.VERSION_17) 12 | set("androidCompileSdk", 35) 13 | set("androidMinSdk", 26) 14 | set("agentVersion", agentVersion) 15 | } 16 | 17 | val instrumentationProjectPattern = Regex(":instrumentation:([^:]+)$") 18 | subprojects { 19 | instrumentationProjectPattern.matchEntire(path)?.let { 20 | val moduleId = it.groupValues[1] 21 | configurations.all { 22 | resolutionStrategy.dependencySubstitution { 23 | substitute(module("co.elastic.otel.android.instrumentation:${moduleId}-library")) 24 | .using(module("co.elastic.otel.android.${moduleId}:library:$agentVersion")) 25 | } 26 | resolutionStrategy.dependencySubstitution { 27 | substitute(module("co.elastic.otel.android.instrumentation:${moduleId}-bytebuddy")) 28 | .using(module("co.elastic.otel.android.${moduleId}:bytebuddy:$agentVersion")) 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/features/session/SessionProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.features.session 20 | 21 | import co.elastic.otel.android.internal.session.DefaultSessionProvider 22 | 23 | fun interface SessionProvider { 24 | fun getSession(): Session? 25 | 26 | companion object { 27 | @JvmStatic 28 | fun getDefault(): SessionProvider { 29 | return DefaultSessionProvider() 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | mavenLocal() 4 | mavenCentral() 5 | google() 6 | gradlePluginPortal() 7 | } 8 | } 9 | dependencyResolutionManagement { 10 | versionCatalogs { 11 | create("instrumentation") { 12 | from(files("./gradle/instrumentation.versions.toml")) 13 | } 14 | } 15 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 16 | repositories { 17 | mavenLocal() 18 | mavenCentral() 19 | google() 20 | } 21 | } 22 | rootProject.name = "elastic-otel-android" 23 | includeBuild("build-tools") 24 | include(":agent-api") 25 | include(":agent-sdk") 26 | include(":agent-plugin") 27 | include(":agent-common") 28 | includeFromDir("instrumentation") 29 | includeFromDir("internal-tools", 2) 30 | 31 | fun includeFromDir(dirName: String, maxDepth: Int = 3) { 32 | val instrumentationDir = File(rootDir, dirName) 33 | val separator = Regex("[/\\\\]") 34 | instrumentationDir.walk().maxDepth(maxDepth).forEach { 35 | if (it.name.equals("build.gradle.kts")) { 36 | include( 37 | ":$dirName:${ 38 | it.parentFile.toRelativeString(instrumentationDir).replace(separator, ":") 39 | }" 40 | ) 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/session/DefaultSession.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.session 20 | 21 | import co.elastic.otel.android.features.session.Session 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | internal data class DefaultSession(private val id: String) : Session { 28 | 29 | override fun getId(): String { 30 | return id 31 | } 32 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/connectivity/SignalConnectivityChangeListener.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.connectivity 20 | 21 | import co.elastic.otel.android.internal.opentelemetry.SignalType 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | internal interface SignalConnectivityChangeListener { 28 | fun onConnectivityConfigurationChange(signalType: SignalType) 29 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/services/network/listener/NetworkChangeListener.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.services.network.listener 20 | 21 | import android.net.NetworkCapabilities 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | internal interface NetworkChangeListener { 28 | fun onNewNetwork(capabilities: NetworkCapabilities) 29 | 30 | fun onNetworkLost() 31 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/interceptor/NoopInterceptor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities.interceptor 20 | 21 | import co.elastic.otel.android.interceptor.Interceptor 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | internal class NoopInterceptor : Interceptor { 28 | 29 | override fun intercept(item: T): T { 30 | return item 31 | } 32 | } -------------------------------------------------------------------------------- /integration-test/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.util.Properties 2 | 3 | plugins { 4 | alias(rootLibs.plugins.androidApp) apply false 5 | alias(rootLibs.plugins.kotlin.android) apply false 6 | } 7 | 8 | val agentProperties = Properties() 9 | val propertiesFile = File(rootDir, "../gradle.properties") 10 | propertiesFile.inputStream().use { 11 | agentProperties.load(it) 12 | } 13 | 14 | val agentVersion = agentProperties["version"] 15 | subprojects { 16 | if (name == "app") { 17 | configurations.all { 18 | File(rootDir, "../instrumentation").listFiles().forEach { 19 | val dirName = it.name 20 | if (dirName != "api") { 21 | resolutionStrategy.dependencySubstitution { 22 | substitute(module("co.elastic.otel.android.instrumentation:${dirName}-library")) 23 | .using(module("co.elastic.otel.android.${dirName}:library:$agentVersion")) 24 | } 25 | resolutionStrategy.dependencySubstitution { 26 | substitute(module("co.elastic.otel.android.instrumentation:${dirName}-bytebuddy")) 27 | .using(module("co.elastic.otel.android.${dirName}:bytebuddy:$agentVersion")) 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/README.md: -------------------------------------------------------------------------------- 1 | # CI/CD 2 | 3 | There are 2 main stages that run on GitHub actions for every push or Pull Request: 4 | 5 | * Linting 6 | * Test 7 | 8 | ## Scenarios 9 | 10 | * Tests should be triggered on branch, tag and PR basis. 11 | * Commits that are only affecting the docs files should not trigger any test or similar stages that are not required. 12 | * **This is not the case yet**, but if Github secrets are required then Pull Requests from forked repositories won't run any build accessing those secrets. If needed, then create a feature branch. 13 | 14 | ## How to interact with the CI? 15 | 16 | ### On a PR basis 17 | 18 | Once a PR has been opened then there are two different ways you can trigger builds in the CI: 19 | 20 | 1. Commit based. 21 | 2. UI based, any Elasticians can force a build through the GitHub UI 22 | 23 | ### Branches 24 | 25 | Every time there is a merge to main or any release branches the main workflow will lint and test all on Linux. 26 | 27 | ## Release 28 | 29 | The release automation relies on Buildkite for generating and publishing the artifacts, 30 | for further details please go to [the buildkite folder](../../.buildkite/README.md). 31 | 32 | ## OpenTelemetry 33 | 34 | Every workflow and its logs are exported to OpenTelemetry traces/logs/metrics. Those details can be seen in 35 | [here](https://ela.st/oblt-ci-cd-stats) (**NOTE**: only available for Elasticians). 36 | -------------------------------------------------------------------------------- /gradle/instrumentation.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | opentelemetry-instrumentation-alpha = "2.21.0-alpha" 3 | opentelemetry-android = "0.11.0-alpha" 4 | 5 | [libraries] 6 | opentelemetry-instrumentation-api = "io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:2.21.0" 7 | opentelemetry-instrumentation-api-incubator = { module = "io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator", version.ref = "opentelemetry-instrumentation-alpha" } 8 | opentelemetry-instrumentation-okhttp = { module = "io.opentelemetry.instrumentation:opentelemetry-okhttp-3.0", version.ref = "opentelemetry-instrumentation-alpha" } 9 | opentelemetry-android-session = { module = "io.opentelemetry.android:session", version.ref = "opentelemetry-android" } 10 | opentelemetry-android-instrumentation = { module = "io.opentelemetry.android.instrumentation:android-instrumentation", version.ref = "opentelemetry-android" } 11 | weakLockFree = "com.blogspot.mydailyjava:weak-lock-free:0.18" 12 | 13 | # Testing 14 | androidx-test-core = "androidx.test:core-ktx:1.7.0" 15 | androidx-test-rules = "androidx.test:rules:1.7.0" 16 | androidx-test-runner = "androidx.test:runner:1.7.0" 17 | androidx-test-ext = "androidx.test.ext:junit:1.3.0" 18 | mockWebServer = "com.squareup.okhttp3:mockwebserver:5.3.2" 19 | 20 | [bundles] 21 | androidTest = ["androidx-test-rules", "androidx-test-runner", "androidx-test-ext", "androidx-test-core"] 22 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/time/SystemTimeProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.time 20 | 21 | import android.os.SystemClock 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | class SystemTimeProvider { 28 | 29 | fun getCurrentTimeMillis(): Long = System.currentTimeMillis() 30 | 31 | fun getNanoTime(): Long = System.nanoTime() 32 | 33 | fun getElapsedRealTime(): Long = SystemClock.elapsedRealtime() 34 | } 35 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/services/network/data/NetworkType.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.services.network.data 20 | 21 | /** 22 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 23 | * any time. 24 | */ 25 | internal sealed class NetworkType(val name: String) { 26 | data class Cell(val subTypeName: String?) : NetworkType("cell") 27 | data object Wifi : NetworkType("wifi") 28 | data object Unknown : NetworkType("unknown") 29 | data object None : NetworkType("unavailable") 30 | } -------------------------------------------------------------------------------- /agent-plugin/src/main/java/co/elastic/otel/android/plugin/extensions/ElasticApmExtension.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.plugin.extensions 20 | 21 | import javax.inject.Inject 22 | import org.gradle.api.Action 23 | import org.gradle.api.model.ObjectFactory 24 | 25 | abstract class ElasticApmExtension @Inject constructor(objects: ObjectFactory) { 26 | val bytecodeInstrumentation = objects.newInstance(BytecodeInstrumentation::class.java) 27 | 28 | fun bytecodeInstrumentation(action: Action) { 29 | action.execute(bytecodeInstrumentation) 30 | } 31 | } -------------------------------------------------------------------------------- /agent-plugin/src/main/java/co/elastic/otel/android/plugin/internal/logging/GradleLoggerFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.plugin.internal.logging 20 | 21 | import co.elastic.otel.android.common.internal.logging.ELoggerFactory 22 | import org.gradle.api.logging.Logging 23 | import org.slf4j.Logger 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | class GradleLoggerFactory : ELoggerFactory() { 30 | 31 | override fun getLogger(name: String): Logger { 32 | return Logging.getLogger(name) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /agent-api/src/main/java/co/elastic/otel/android/api/flusher/MetricFlusher.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.api.flusher 20 | 21 | import io.opentelemetry.sdk.common.CompletableResultCode 22 | import io.opentelemetry.sdk.metrics.export.MetricReader 23 | 24 | /** 25 | * Marks the ability to force flush metrics. 26 | */ 27 | interface MetricFlusher { 28 | 29 | /** 30 | * Flushes metrics. This is useful to signal the [MetricReader] to read and export metrics on demand. 31 | * 32 | * @return [CompletableResultCode] to keep track of the async operation. 33 | */ 34 | fun flushMetrics(): CompletableResultCode 35 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/api/ManagedElasticOtelAgentContract.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.api 20 | 21 | import co.elastic.otel.android.api.ElasticOtelAgent 22 | import co.elastic.otel.android.api.flusher.LogRecordFlusher 23 | import co.elastic.otel.android.api.flusher.MetricFlusher 24 | import co.elastic.otel.android.api.flusher.SpanFlusher 25 | 26 | /** 27 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 28 | * any time. 29 | */ 30 | interface ManagedElasticOtelAgentContract : ElasticOtelAgent, SpanFlusher, LogRecordFlusher, 31 | MetricFlusher -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/exporters/ExporterProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.exporters 20 | 21 | import io.opentelemetry.sdk.logs.export.LogRecordExporter 22 | import io.opentelemetry.sdk.metrics.export.MetricExporter 23 | import io.opentelemetry.sdk.trace.export.SpanExporter 24 | 25 | interface ExporterProvider { 26 | companion object { 27 | fun noop(): ExporterProvider { 28 | return NoopExporterProvider() 29 | } 30 | } 31 | 32 | fun getSpanExporter(): SpanExporter? 33 | 34 | fun getLogRecordExporter(): LogRecordExporter? 35 | 36 | fun getMetricExporter(): MetricExporter? 37 | } -------------------------------------------------------------------------------- /agent-sdk/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("elastic.android-library") 3 | } 4 | 5 | android { 6 | namespace = "co.elastic.otel.android" 7 | buildFeatures.buildConfig = true 8 | 9 | defaultConfig { 10 | buildConfigField("String", "APM_AGENT_VERSION", "\"${project.version}\"") 11 | } 12 | 13 | testOptions { 14 | unitTests { 15 | isIncludeAndroidResources = true 16 | all { 17 | it.systemProperty("agent_version", project.version) 18 | } 19 | } 20 | } 21 | } 22 | 23 | apiValidation { 24 | ignoredClasses.add("co.elastic.otel.android.BuildConfig") 25 | } 26 | 27 | dependencies { 28 | api(project(":agent-api")) 29 | api(project(":instrumentation:api")) 30 | implementation(libs.opentelemetry.api.incubator) 31 | implementation(libs.stagemonitor.configuration) 32 | implementation(libs.opentelemetry.exporter.otlp) 33 | implementation(libs.bundles.opentelemetry.semconv) 34 | implementation(libs.opentelemetry.diskBuffering) 35 | implementation(libs.opentelemetry.opamp) 36 | implementation(libs.androidx.annotations) 37 | implementation(libs.androidx.core) 38 | implementation(libs.dsl.json) 39 | implementation(libs.okhttp) 40 | testImplementation(project(":internal-tools:otel-test-common")) 41 | testImplementation(libs.wireMock) 42 | testImplementation(libs.opentelemetry.testing) 43 | testImplementation(libs.robolectric) 44 | testImplementation(libs.awaitility) 45 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/exporters/NoopExporterProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.exporters 20 | 21 | import io.opentelemetry.sdk.logs.export.LogRecordExporter 22 | import io.opentelemetry.sdk.metrics.export.MetricExporter 23 | import io.opentelemetry.sdk.trace.export.SpanExporter 24 | 25 | internal class NoopExporterProvider : ExporterProvider { 26 | override fun getSpanExporter(): SpanExporter? { 27 | return null 28 | } 29 | 30 | override fun getLogRecordExporter(): LogRecordExporter? { 31 | return null 32 | } 33 | 34 | override fun getMetricExporter(): MetricExporter? { 35 | return null 36 | } 37 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/features/session/SessionIdGenerator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.features.session 20 | 21 | /** 22 | * Generates a session id to be sent as a [session.id](https://opentelemetry.io/docs/specs/semconv/attributes-registry/session/#session-id) attribute. 23 | */ 24 | fun interface SessionIdGenerator { 25 | /** 26 | * Called every time a span or log record is created to set its [session.id](https://opentelemetry.io/docs/specs/semconv/attributes-registry/session/#session-id) attribute. 27 | * 28 | * @return The generated session id, or null if no session id is needed. 29 | */ 30 | fun generate(): String? 31 | } -------------------------------------------------------------------------------- /agent-api/src/main/java/co/elastic/otel/android/api/flusher/SpanFlusher.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.api.flusher 20 | 21 | import io.opentelemetry.sdk.common.CompletableResultCode 22 | import io.opentelemetry.sdk.trace.SpanProcessor 23 | 24 | /** 25 | * Marks the ability to force flush spans. 26 | */ 27 | interface SpanFlusher { 28 | 29 | /** 30 | * Flushes spans. This is useful when the [SpanProcessor] temporarily stores items in-memory 31 | * and it's needed to send them to the exporter before they're due. 32 | * 33 | * @return [CompletableResultCode] to keep track of the async operation. 34 | */ 35 | fun flushSpans(): CompletableResultCode 36 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/logging/AndroidLoggerFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities.logging 20 | 21 | import co.elastic.otel.android.common.internal.logging.ELoggerFactory 22 | import co.elastic.otel.android.logging.LoggingPolicy 23 | import org.slf4j.Logger 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | internal class AndroidLoggerFactory(private val policy: LoggingPolicy) : ELoggerFactory() { 30 | 31 | override fun getLogger(name: String): Logger { 32 | return AndroidLogger(name, policy) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/interceptor/MultiInterceptor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities.interceptor 20 | 21 | import co.elastic.otel.android.interceptor.Interceptor 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | internal class MultiInterceptor(private val interceptors: List>) : 28 | Interceptor { 29 | 30 | override fun intercept(item: T): T { 31 | var result = item 32 | interceptors.forEach { 33 | result = it.intercept(result) 34 | } 35 | return result 36 | } 37 | } -------------------------------------------------------------------------------- /agent-plugin/src/main/java/co/elastic/otel/android/plugin/internal/ByteBuddyDependencyAttacher.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.plugin.internal 20 | 21 | import org.gradle.api.Project 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | class ByteBuddyDependencyAttacher( 28 | private val project: Project, 29 | private val dependencyUri: String 30 | ) : BuildVariantListener { 31 | 32 | override fun onBuildVariant(name: String) { 33 | project.configurations.maybeCreate("${name}ByteBuddy").dependencies.add( 34 | project.dependencies.create(dependencyUri) 35 | ) 36 | } 37 | } -------------------------------------------------------------------------------- /agent-api/src/main/java/co/elastic/otel/android/api/flusher/LogRecordFlusher.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.api.flusher 20 | 21 | import io.opentelemetry.sdk.common.CompletableResultCode 22 | import io.opentelemetry.sdk.logs.LogRecordProcessor 23 | 24 | /** 25 | * Marks the ability to force flush log records. 26 | */ 27 | interface LogRecordFlusher { 28 | 29 | /** 30 | * Flushes log records. This is useful when the [LogRecordProcessor] temporarily stores items in-memory 31 | * and it's needed to send them to the exporter before they're due. 32 | * 33 | * @return [CompletableResultCode] to keep track of the async operation. 34 | */ 35 | fun flushLogRecords(): CompletableResultCode 36 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/session/DefaultSessionProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.session 20 | 21 | import co.elastic.otel.android.features.session.Session 22 | import co.elastic.otel.android.features.session.SessionProvider 23 | import java.util.UUID 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | internal class DefaultSessionProvider : SessionProvider { 30 | private val providedSession by lazy { 31 | Session.create(UUID.randomUUID().toString()) 32 | } 33 | 34 | override fun getSession(): Session { 35 | return providedSession 36 | } 37 | } -------------------------------------------------------------------------------- /instrumentation-test/instrumentation/oteladapter/src/androidTest/java/co/elastic/otel/android/test/InstrumentationTest.kt: -------------------------------------------------------------------------------- 1 | package co.elastic.otel.android.test 2 | 3 | import androidx.test.core.app.launchActivity 4 | import co.elastic.otel.android.test.rule.AndroidTestAgentRule 5 | import io.opentelemetry.api.common.AttributeKey 6 | import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat 7 | import java.util.concurrent.TimeUnit 8 | import org.junit.Rule 9 | import org.junit.Test 10 | 11 | class InstrumentationTest { 12 | 13 | @get:Rule 14 | val agentRule = AndroidTestAgentRule() 15 | 16 | @Test 17 | fun verifyAndroidLogsAreInstrumented() { 18 | launchActivity().onActivity { activity -> 19 | activity.sendLog() 20 | 21 | agentRule.flushLogs().join(5, TimeUnit.SECONDS) 22 | 23 | val finishedLogRecords = agentRule.getFinishedLogRecords() 24 | assertThat(finishedLogRecords).hasSize(1) 25 | assertThat(finishedLogRecords.first()) 26 | .hasBody("My log") 27 | .hasAttributesSatisfying { 28 | assertThat(it.get(AttributeKey.stringKey("android.log.tag"))).isEqualTo("elastic") 29 | } 30 | 31 | // Closing instrumentation 32 | agentRule.getInstrumentationManager().close() 33 | 34 | activity.sendLog() 35 | 36 | agentRule.flushLogs().join(5, TimeUnit.SECONDS) 37 | assertThat(agentRule.getFinishedLogRecords()).isEmpty() 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /instrumentation/oteladapter/plugin/src/main/java/co/elastic/otel/android/oteladapter/ExperimentalOtelAdapterPlugin.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.oteladapter 20 | 21 | import co.elastic.otel.android.instrumentation.generated.oteladapter.BuildConfig 22 | import co.elastic.otel.android.plugin.ElasticAgentPlugin 23 | import co.elastic.otel.android.plugin.internal.InstrumentationPlugin 24 | import org.gradle.api.Project 25 | 26 | class ExperimentalOtelAdapterPlugin : InstrumentationPlugin() { 27 | 28 | override fun onApply(target: Project, agentPlugin: ElasticAgentPlugin) { 29 | target.dependencies.add( 30 | "implementation", 31 | target.dependencies.create(BuildConfig.LIBRARY_URI) 32 | ) 33 | } 34 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/logging/SimpleLoggingPolicy.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.logging 20 | 21 | import co.elastic.otel.android.logging.LogLevel 22 | import co.elastic.otel.android.logging.LoggingPolicy 23 | 24 | /** 25 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 26 | * any time. 27 | */ 28 | internal class SimpleLoggingPolicy( 29 | private val isEnabled: Boolean, 30 | private val minimumLevel: LogLevel 31 | ) : 32 | LoggingPolicy { 33 | 34 | override fun isEnabled(): Boolean { 35 | return isEnabled 36 | } 37 | 38 | override fun getMinimumLevel(): LogLevel { 39 | return minimumLevel 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/features/httpinterceptor/HttpSpanExporterInterceptor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.features.httpinterceptor 20 | 21 | import co.elastic.otel.android.interceptor.Interceptor 22 | import io.opentelemetry.sdk.trace.data.SpanData 23 | import io.opentelemetry.sdk.trace.export.SpanExporter 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | internal class HttpSpanExporterInterceptor(private val httpSpanInterceptor: Interceptor) : 30 | Interceptor { 31 | 32 | override fun intercept(item: SpanExporter): SpanExporter { 33 | return HttpSpanExporter(item, httpSpanInterceptor) 34 | } 35 | } -------------------------------------------------------------------------------- /instrumentation/api/src/main/java/co/elastic/otel/android/instrumentation/internal/Instrumentation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.instrumentation.internal 20 | 21 | import android.app.Application 22 | import co.elastic.otel.android.api.ElasticOtelAgent 23 | import java.io.Closeable 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | interface Instrumentation { 30 | 31 | fun install(application: Application, agent: ElasticOtelAgent): Installation 32 | 33 | fun getId(): String 34 | 35 | fun getVersion(): String 36 | 37 | fun interface Installation : Closeable { 38 | companion object { 39 | val NOOP = Installation {} 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # IntelliJ 40 | *.iml 41 | .idea/ 42 | .java-version 43 | 44 | # Keystore files 45 | # Uncomment the following lines if you do not want to check your keystore files in. 46 | #*.jks 47 | #*.keystore 48 | 49 | # External native build folder generated in Android Studio 2.2 and later 50 | .externalNativeBuild 51 | .cxx/ 52 | 53 | # Google Services (e.g. APIs or Firebase) 54 | # google-services.json 55 | 56 | # Freeline 57 | freeline.py 58 | freeline/ 59 | freeline_project_description.json 60 | 61 | # fastlane 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | fastlane/readme.md 67 | 68 | # Version control 69 | vcs.xml 70 | 71 | # lint 72 | lint/intermediates/ 73 | lint/generated/ 74 | lint/outputs/ 75 | lint/tmp/ 76 | # lint/reports/ 77 | 78 | # Deploy task 79 | .android-sdk 80 | 81 | # built documentation 82 | html_docs 83 | .artifacts 84 | docs/.artifacts 85 | 86 | .DS_Store -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/interceptor/MutableInterceptor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities.interceptor 20 | 21 | import co.elastic.otel.android.interceptor.Interceptor 22 | import java.util.concurrent.atomic.AtomicReference 23 | 24 | /** 25 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 26 | * any time. 27 | */ 28 | internal class MutableInterceptor(initialValue: Interceptor) : Interceptor { 29 | private val delegate = AtomicReference(initialValue) 30 | 31 | override fun intercept(item: T): T { 32 | return delegate.get().intercept(item) 33 | } 34 | 35 | fun setDelegate(value: Interceptor) { 36 | delegate.set(value) 37 | } 38 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/features/clock/SystemTimeClock.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.features.clock 20 | 21 | import co.elastic.otel.android.internal.time.SystemTimeProvider 22 | import io.opentelemetry.sdk.common.Clock 23 | import java.util.concurrent.TimeUnit 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | internal class SystemTimeClock(private val systemTimeProvider: SystemTimeProvider) : Clock { 30 | 31 | override fun now(): Long { 32 | return TimeUnit.MILLISECONDS.toNanos(systemTimeProvider.getCurrentTimeMillis()) 33 | } 34 | 35 | override fun nanoTime(): Long { 36 | return systemTimeProvider.getNanoTime() 37 | } 38 | } -------------------------------------------------------------------------------- /.github/scripts/integration-test/Makefile: -------------------------------------------------------------------------------- 1 | MAKEFLAGS += --no-print-directory 2 | .SHELLFLAGS = -euc 3 | SHELL = /bin/bash 4 | 5 | elastic_version?=9.2.0 6 | elastic-start-local: ## Start ES locally 7 | curl -fsSL https://elastic.co/start-local | sh -s -- --esonly -v $(elastic_version) 8 | 9 | .PHONY: start-edot-collector 10 | demo_app_dir="build/demo-app" 11 | edot_collector_build="$(demo_app_dir)/edot-collector/build" 12 | start-edot-collector: elastic-start-local ## Start EDOT Collector 13 | git clone https://github.com/elastic/android-agent-demo.git $(demo_app_dir) 14 | . elastic-start-local/.env; \ 15 | printf "endpoint=$$ES_LOCAL_URL\napi_key=$$ES_LOCAL_API_KEY" > "$(demo_app_dir)/elasticsearch.properties" 16 | 17 | # Preparing collector binary 18 | $(demo_app_dir)/gradlew -p "$(demo_app_dir)" :edot-collector:prepareEdotCollector 19 | 20 | # Launching EDOT Collector 21 | "$(edot_collector_build)/bin/otelcol" --config "$(edot_collector_build)/configuration/edot-configuration.yml" & 22 | 23 | # Waiting for EDOT Collector to run 24 | ./await_port.sh 4318 30 25 | 26 | .PHONY: run-tests 27 | run-tests: elastic-start-local ## Run integration tests 28 | . elastic-start-local/.env; \ 29 | ./integration_test.sh $$ES_LOCAL_URL $$ES_LOCAL_API_KEY 30 | 31 | .PHONY: clean 32 | clean: clean-es clean-edot-collector 33 | 34 | .PHONY: clean-es 35 | clean-es: ## Stop and uninstall ES 36 | yes | elastic-start-local/stop.sh 37 | yes | elastic-start-local/uninstall.sh 38 | rm -rf elastic-start-local 39 | 40 | .PHONY: clean-edot-collector 41 | clean-edot-collector: ## Stop and cleans EDOT Collector 42 | kill $$(lsof -t -i:4318) 43 | rm -rf $(demo_app_dir) -------------------------------------------------------------------------------- /instrumentation/oteladapter/library/src/main/java/co/elastic/otel/android/oteladapter/internal/delegate/tools/Delegator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.oteladapter.internal.delegate.tools 20 | 21 | import java.util.concurrent.atomic.AtomicReference 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | abstract class Delegator(initialValue: T) { 28 | private val delegate = AtomicReference(initialValue) 29 | 30 | abstract fun getNoopValue(): T 31 | 32 | open fun setDelegate(value: T) { 33 | delegate.set(value) 34 | } 35 | 36 | open fun reset() { 37 | delegate.set(getNoopValue()) 38 | } 39 | 40 | fun getDelegate(): T { 41 | return delegate.get() 42 | } 43 | } -------------------------------------------------------------------------------- /internal-tools/otel-test-common/src/main/java/co/elastic/otel/android/test/processor/SimpleProcessorFactory.kt: -------------------------------------------------------------------------------- 1 | package co.elastic.otel.android.test.processor 2 | 3 | import co.elastic.otel.android.api.flusher.MetricFlusher 4 | import co.elastic.otel.android.processors.ProcessorFactory 5 | import io.opentelemetry.sdk.common.CompletableResultCode 6 | import io.opentelemetry.sdk.logs.LogRecordProcessor 7 | import io.opentelemetry.sdk.logs.export.LogRecordExporter 8 | import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor 9 | import io.opentelemetry.sdk.metrics.export.MetricExporter 10 | import io.opentelemetry.sdk.metrics.export.MetricReader 11 | import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader 12 | import io.opentelemetry.sdk.trace.SpanProcessor 13 | import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor 14 | import io.opentelemetry.sdk.trace.export.SpanExporter 15 | 16 | class SimpleProcessorFactory : ProcessorFactory, MetricFlusher { 17 | private lateinit var metricReader: PeriodicMetricReader 18 | 19 | override fun createSpanProcessor(exporter: SpanExporter?): SpanProcessor? { 20 | return SimpleSpanProcessor.create(exporter) 21 | } 22 | 23 | override fun createLogRecordProcessor(exporter: LogRecordExporter?): LogRecordProcessor? { 24 | return SimpleLogRecordProcessor.create(exporter) 25 | } 26 | 27 | override fun createMetricReader(exporter: MetricExporter?): MetricReader { 28 | metricReader = PeriodicMetricReader.create(exporter) 29 | return metricReader 30 | } 31 | 32 | override fun flushMetrics(): CompletableResultCode { 33 | return metricReader.forceFlush() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/features/clock/MutableClock.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.features.clock 20 | 21 | import io.opentelemetry.sdk.common.Clock 22 | import java.util.concurrent.atomic.AtomicReference 23 | 24 | /** 25 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 26 | * any time. 27 | */ 28 | internal class MutableClock(initialClock: Clock) : Clock { 29 | private val delegate: AtomicReference = AtomicReference(initialClock) 30 | 31 | override fun now(): Long { 32 | return delegate.get().now() 33 | } 34 | 35 | override fun nanoTime(): Long { 36 | return delegate.get().nanoTime() 37 | } 38 | 39 | internal fun setDelegate(clock: Clock) { 40 | delegate.set(clock) 41 | } 42 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/AttributesOverrideLogRecordData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities 20 | 21 | import io.opentelemetry.api.common.Attributes 22 | import io.opentelemetry.sdk.logs.data.LogRecordData 23 | 24 | /** 25 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 26 | * any time. 27 | */ 28 | internal open class AttributesOverrideLogRecordData( 29 | delegate: LogRecordData, 30 | private val attributes: Attributes, 31 | private val totalAttributeCount: Int 32 | ) : DelegateLogRecordData(delegate) { 33 | 34 | override fun getAttributes(): Attributes { 35 | return attributes 36 | } 37 | 38 | override fun getTotalAttributeCount(): Int { 39 | return totalAttributeCount 40 | } 41 | } -------------------------------------------------------------------------------- /agent-sdk/src/test/java/co/elastic/otel/android/internal/logging/DefaultLoggingPolicyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.logging 20 | 21 | import co.elastic.otel.android.logging.LogLevel 22 | import org.assertj.core.api.Assertions.assertThat 23 | import org.junit.Test 24 | 25 | class DefaultLoggingPolicyTest { 26 | 27 | @Test 28 | fun `Validate minimum level on debuggable app`() { 29 | assertThat(getInstance(true).getMinimumLevel()).isEqualTo(LogLevel.DEBUG) 30 | } 31 | 32 | @Test 33 | fun `Validate minimum level on non-debuggable app`() { 34 | assertThat(getInstance(false).getMinimumLevel()).isEqualTo(LogLevel.INFO) 35 | } 36 | 37 | private fun getInstance(appIsDebuggable: Boolean): DefaultLoggingPolicy { 38 | return DefaultLoggingPolicy(appIsDebuggable) 39 | } 40 | } -------------------------------------------------------------------------------- /agent-sdk/src/test/java/co/elastic/otel/android/internal/logging/SimpleLoggingPolicyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.logging 20 | 21 | import co.elastic.otel.android.logging.LogLevel 22 | import co.elastic.otel.android.logging.LoggingPolicy 23 | import org.junit.Assert 24 | import org.junit.Test 25 | 26 | class SimpleLoggingPolicyTest { 27 | @Test 28 | fun verifyProvidedValues() { 29 | val policy: LoggingPolicy = SimpleLoggingPolicy(true, LogLevel.INFO) 30 | val policy2: LoggingPolicy = SimpleLoggingPolicy(false, LogLevel.ERROR) 31 | 32 | Assert.assertTrue(policy.isEnabled()) 33 | Assert.assertEquals(LogLevel.INFO, policy.getMinimumLevel()) 34 | Assert.assertFalse(policy2.isEnabled()) 35 | Assert.assertEquals(LogLevel.ERROR, policy2.getMinimumLevel()) 36 | } 37 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/features/centralconfig/CentralConfiguration.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.features.centralconfig 20 | 21 | import co.elastic.otel.android.internal.configuration.Configuration 22 | import java.util.Optional 23 | 24 | /** 25 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 26 | * any time. 27 | */ 28 | internal class CentralConfiguration : Configuration() { 29 | private val recording = createBooleanOption("recording") 30 | private val sessionSampleRate = createDoubleOption("session_sample_rate") 31 | 32 | fun isRecording(): Boolean { 33 | return recording.get().orElse(true) 34 | } 35 | 36 | fun getSessionSampleRate(): Optional { 37 | return sessionSampleRate.get() 38 | } 39 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/features/clock/ElasticClockBroadcastReceiver.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.features.clock 20 | 21 | import android.content.BroadcastReceiver 22 | import android.content.Context 23 | import android.content.Intent 24 | import co.elastic.otel.android.internal.services.ServiceManager 25 | 26 | /** 27 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 28 | * any time. 29 | */ 30 | class ElasticClockBroadcastReceiver : BroadcastReceiver() { 31 | override fun onReceive(context: Context, intent: Intent?) { 32 | if (intent?.action == Intent.ACTION_BOOT_COMPLETED) { 33 | RemoteTimeOffsetManager.TimeOffsetCache( 34 | ServiceManager.create(context).getPreferencesService() 35 | ).clear() 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/cache/PreferencesLongCacheHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities.cache 20 | 21 | import co.elastic.otel.android.internal.services.preferences.PreferencesService 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | internal class PreferencesLongCacheHandler( 28 | private val key: String, 29 | private val preferencesService: PreferencesService 30 | ) : CacheHandler { 31 | 32 | override fun retrieve(): Long { 33 | return preferencesService.retrieveLong(key, 0) 34 | } 35 | 36 | override fun clear() { 37 | preferencesService.remove(key) 38 | } 39 | 40 | override fun store(value: Long) { 41 | preferencesService.store(key, value) 42 | } 43 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/cache/PreferencesStringCacheHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities.cache 20 | 21 | import co.elastic.otel.android.internal.services.preferences.PreferencesService 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | internal class PreferencesStringCacheHandler( 28 | private val key: String, 29 | private val preferencesService: PreferencesService 30 | ) : CacheHandler { 31 | 32 | override fun retrieve(): String? { 33 | return preferencesService.retrieveString(key) 34 | } 35 | 36 | override fun clear() { 37 | preferencesService.remove(key) 38 | } 39 | 40 | override fun store(value: String) { 41 | preferencesService.store(key, value) 42 | } 43 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/AttributesOverrideSpanData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities 20 | 21 | import io.opentelemetry.api.common.Attributes 22 | import io.opentelemetry.sdk.trace.data.DelegatingSpanData 23 | import io.opentelemetry.sdk.trace.data.SpanData 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | internal open class AttributesOverrideSpanData( 30 | delegate: SpanData, 31 | private val attributes: Attributes, 32 | private val totalAttributeCount: Int = attributes.size() 33 | ) : DelegatingSpanData(delegate) { 34 | 35 | override fun getAttributes(): Attributes { 36 | return attributes 37 | } 38 | 39 | override fun getTotalAttributeCount(): Int { 40 | return totalAttributeCount 41 | } 42 | } -------------------------------------------------------------------------------- /agent-plugin/src/main/java/co/elastic/otel/android/plugin/internal/InstrumentationPlugin.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.plugin.internal 20 | 21 | import co.elastic.otel.android.plugin.ElasticAgentPlugin 22 | import org.gradle.api.Plugin 23 | import org.gradle.api.Project 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | abstract class InstrumentationPlugin : Plugin { 30 | 31 | final override fun apply(target: Project) { 32 | with(target.plugins) { 33 | if (!hasPlugin(ElasticAgentPlugin::class.java)) { 34 | apply(ElasticAgentPlugin::class.java) 35 | } 36 | } 37 | onApply(target, target.plugins.getPlugin(ElasticAgentPlugin::class.java)) 38 | } 39 | 40 | abstract fun onApply(target: Project, agentPlugin: ElasticAgentPlugin) 41 | } -------------------------------------------------------------------------------- /agent-common/src/main/java/co/elastic/otel/android/common/internal/logging/ELoggerFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.common.internal.logging 20 | 21 | import org.slf4j.ILoggerFactory 22 | import org.slf4j.Logger 23 | import org.slf4j.helpers.NOPLogger 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | abstract class ELoggerFactory : ILoggerFactory { 30 | 31 | fun getLogger(type: Class<*>): Logger { 32 | return getLogger(id + " - " + type.simpleName) 33 | } 34 | 35 | val defaultLogger: Logger 36 | get() = getLogger(id) 37 | 38 | protected val id: String 39 | get() = "ELASTIC_AGENT" 40 | 41 | internal class Noop : ELoggerFactory() { 42 | override fun getLogger(name: String): Logger { 43 | return NOPLogger.NOP_LOGGER 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/opentelemetry/processors/logs/LogRecordAttributesProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.opentelemetry.processors.logs 20 | 21 | import co.elastic.otel.android.interceptor.Interceptor 22 | import io.opentelemetry.api.common.Attributes 23 | import io.opentelemetry.context.Context 24 | import io.opentelemetry.sdk.logs.LogRecordProcessor 25 | import io.opentelemetry.sdk.logs.ReadWriteLogRecord 26 | 27 | /** 28 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 29 | * any time. 30 | */ 31 | internal class LogRecordAttributesProcessor(private val interceptor: Interceptor) : 32 | LogRecordProcessor { 33 | 34 | override fun onEmit(context: Context, logRecord: ReadWriteLogRecord) { 35 | logRecord.setAllAttributes(interceptor.intercept(logRecord.toLogRecordData().attributes)) 36 | } 37 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/utilities/cache/PreferencesIntegerCacheHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.utilities.cache 20 | 21 | import co.elastic.otel.android.internal.services.preferences.PreferencesService 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | internal class PreferencesIntegerCacheHandler( 28 | private val key: String, 29 | private val preferencesService: PreferencesService, 30 | private val defaultValue: Int = 0 31 | ) : CacheHandler { 32 | 33 | override fun retrieve(): Int { 34 | return preferencesService.retrieveInt(key, defaultValue) 35 | } 36 | 37 | override fun clear() { 38 | preferencesService.remove(key) 39 | } 40 | 41 | override fun store(value: Int) { 42 | preferencesService.store(key, value) 43 | } 44 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/features/diskbuffering/DiskBufferingConfiguration.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.features.diskbuffering 20 | 21 | /** 22 | * Defines the disk-buffering behavior. 23 | */ 24 | sealed class DiskBufferingConfiguration { 25 | 26 | internal data class Enabled( 27 | val maxCacheFileSize: Int = 1024 * 1024, 28 | val maxCacheSize: Int = 15 * 1024 * 1024, 29 | val maxFileAgeForWrite: Long? = null, 30 | val minFileAgeForRead: Long? = null 31 | ) : DiskBufferingConfiguration() 32 | 33 | internal data object Disabled : DiskBufferingConfiguration() 34 | 35 | companion object { 36 | @JvmStatic 37 | fun enabled(): DiskBufferingConfiguration { 38 | return Enabled() 39 | } 40 | 41 | @JvmStatic 42 | fun disabled(): DiskBufferingConfiguration { 43 | return Disabled 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /agent-common/src/main/java/co/elastic/otel/android/common/internal/logging/Elog.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.common.internal.logging 20 | 21 | import androidx.annotation.GuardedBy 22 | import java.util.concurrent.atomic.AtomicReference 23 | import org.slf4j.Logger 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | object Elog { 30 | private val loggerFactory = AtomicReference(ELoggerFactory.Noop()) 31 | 32 | @GuardedBy("this") 33 | private var initialized = false 34 | 35 | fun init(factory: ELoggerFactory) { 36 | if (initialized) { 37 | return 38 | } 39 | loggerFactory.set(factory) 40 | initialized = true 41 | } 42 | 43 | fun getLogger(name: String): Logger { 44 | return loggerFactory.get().getLogger(name) 45 | } 46 | 47 | fun getLogger(): Logger = loggerFactory.get().defaultLogger 48 | } 49 | -------------------------------------------------------------------------------- /instrumentation/okhttp/plugin/src/main/java/co/elastic/otel/android/okhttp/OkHttpInstrumentationPlugin.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.okhttp 20 | 21 | import co.elastic.otel.android.instrumentation.generated.okhttp.BuildConfig 22 | import co.elastic.otel.android.plugin.ElasticAgentPlugin 23 | import co.elastic.otel.android.plugin.internal.ByteBuddyDependencyAttacher 24 | import co.elastic.otel.android.plugin.internal.InstrumentationPlugin 25 | import org.gradle.api.Project 26 | 27 | class OkHttpInstrumentationPlugin : InstrumentationPlugin() { 28 | 29 | override fun onApply(target: Project, agentPlugin: ElasticAgentPlugin) { 30 | target.dependencies.add( 31 | "implementation", 32 | target.dependencies.create(BuildConfig.LIBRARY_URI) 33 | ) 34 | agentPlugin.addBuildVariantListener( 35 | ByteBuddyDependencyAttacher( 36 | target, 37 | BuildConfig.BYTEBUDDY_PLUGIN_URI 38 | ) 39 | ) 40 | } 41 | } -------------------------------------------------------------------------------- /.ci/release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ## This script runs the release given the different environment variables 3 | ## branch_specifier 4 | ## target_specifier 5 | ## dry_run 6 | ## 7 | ## NOTE: *_SECRET env variables are masked, hence if you'd like to avoid any 8 | ## surprises please use the suffix _SECRET for those values that contain 9 | ## any sensitive data. Buildkite can mask those values automatically 10 | 11 | set -e 12 | 13 | echo "--- Prepare release context" 14 | # Avoid detached HEAD since the release plugin requires to be on a branch 15 | git checkout -f "${branch_specifier}" 16 | 17 | set +x 18 | # Setting up common deploy params in env var 19 | export COMMON_GRADLE_DEPLOY_PARAMS="-Prelease=true --stacktrace" 20 | 21 | if [[ "$target_specifier" == "all" || "$target_specifier" == "mavenCentral" ]]; then 22 | if [[ "$dry_run" == "false" ]] ; then 23 | echo "--- Release the binaries to Maven Central" 24 | ./gradlew publishAndReleaseElasticToMavenCentral $COMMON_GRADLE_DEPLOY_PARAMS 25 | else 26 | echo "--- Release the binaries to Maven Central :package: (dry-run)" 27 | ./gradlew assemble 28 | fi 29 | fi 30 | 31 | if [[ "$target_specifier" == "all" || "$target_specifier" == "pluginPortal" ]]; then 32 | if [[ "$dry_run" == "false" ]] ; then 33 | echo "--- Release the binaries to the Gradle Plugin portal" 34 | ./gradlew publishPlugins -Pgradle.publish.key=$PLUGIN_PORTAL_KEY -Pgradle.publish.secret=$PLUGIN_PORTAL_SECRET $COMMON_GRADLE_DEPLOY_PARAMS 35 | else 36 | echo "--- Release the binaries to Gradle Plugin portal :package: (dry-run)" 37 | ./gradlew assemble 38 | fi 39 | fi 40 | 41 | echo "--- Archive the build folders with jar/aar files" 42 | find . -type d -name build -exec find {} \( -name '*.jar' -o -name '*.aar' \) -print0 \; | xargs -0 tar -cvf "${TARBALL_FILE:-dist.tar}" 43 | 44 | set -x 45 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/features/exportergate/GateSpanExporter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.features.exportergate 20 | 21 | import io.opentelemetry.sdk.common.CompletableResultCode 22 | import io.opentelemetry.sdk.trace.data.SpanData 23 | import io.opentelemetry.sdk.trace.export.SpanExporter 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | internal class GateSpanExporter( 30 | private val delegate: SpanExporter, 31 | private val spanQueue: ExporterGateQueue 32 | ) : SpanExporter { 33 | 34 | override fun export(spans: MutableCollection): CompletableResultCode { 35 | return spanQueue.enqueue(spans) 36 | } 37 | 38 | override fun flush(): CompletableResultCode { 39 | return delegate.flush() 40 | } 41 | 42 | override fun shutdown(): CompletableResultCode { 43 | return delegate.shutdown() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /integration-test/app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | 16 | 19 | 22 | 23 | 24 | 25 | 31 | -------------------------------------------------------------------------------- /instrumentation/okhttp/bytebuddy/src/main/java/co/elastic/otel/android/okhttp/internal/callback/OkHttpCallbackAdvice.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.okhttp.internal.callback; 20 | 21 | import net.bytebuddy.asm.Advice; 22 | 23 | import co.elastic.otel.android.okhttp.internal.plugin.OkHttpCallbackAdviceHelper; 24 | import co.elastic.otel.android.okhttp.internal.plugin.TracingCallback; 25 | import io.opentelemetry.context.Context; 26 | import okhttp3.Call; 27 | import okhttp3.Callback; 28 | 29 | /** 30 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 31 | * any time. 32 | */ 33 | public class OkHttpCallbackAdvice { 34 | 35 | @Advice.OnMethodEnter 36 | public static void enter( 37 | @Advice.This Call call, 38 | @Advice.Argument(value = 0, readOnly = false) Callback callback) { 39 | if (OkHttpCallbackAdviceHelper.propagateContext(call)) { 40 | callback = new TracingCallback(callback, Context.current()); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/connectivity/Authentication.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.connectivity 20 | 21 | /** 22 | * Authentication strategies to connect to Elastic. 23 | */ 24 | sealed class Authentication { 25 | /** 26 | * Represents an [API Key](https://www.elastic.co/guide/en/observability/current/apm-api-key.html) auth method. 27 | */ 28 | data class ApiKey(val key: String) : Authentication() { 29 | override fun toString(): String { 30 | return "ApiKey(key.length=${key.length})" 31 | } 32 | } 33 | 34 | /** 35 | * Represent a [Secret token](https://www.elastic.co/guide/en/observability/current/apm-secret-token.html) auth method. 36 | */ 37 | data class SecretToken(val token: String) : Authentication() { 38 | override fun toString(): String { 39 | return "SecretToken(token.length=${token.length})" 40 | } 41 | } 42 | 43 | /** 44 | * No auth method. 45 | */ 46 | data object None : Authentication() 47 | } -------------------------------------------------------------------------------- /instrumentation-test/buildSrc/src/main/kotlin/elastic.instrumentation-test-app.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.util.Properties 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | id("com.android.application") 6 | id("org.jetbrains.kotlin.android") 7 | } 8 | 9 | val properties = Properties() 10 | val propertiesFile = File(rootDir, "../gradle.properties") 11 | propertiesFile.inputStream().use { 12 | properties.load(it) 13 | } 14 | 15 | val javaVersionStr = properties.getProperty("elastic.java.compatibility") as String 16 | android { 17 | compileSdk = (properties.getProperty("elastic.android.compileSdk") as String).toInt() 18 | 19 | defaultConfig { 20 | minSdk = 26 21 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 22 | } 23 | 24 | testOptions { 25 | unitTests { 26 | isIncludeAndroidResources = true 27 | } 28 | animationsDisabled = true 29 | } 30 | 31 | val javaVersionStr = properties.getProperty("elastic.java.compatibility") as String 32 | val javaVersion = JavaVersion.toVersion(javaVersionStr) 33 | compileOptions { 34 | sourceCompatibility = javaVersion 35 | targetCompatibility = javaVersion 36 | } 37 | packaging.resources { 38 | excludes += "META-INF/LICENSE*" 39 | } 40 | } 41 | 42 | kotlin { 43 | compilerOptions { 44 | jvmTarget = JvmTarget.fromTarget(javaVersionStr) 45 | } 46 | } 47 | 48 | val libs = extensions.getByType().named("libs") 49 | dependencies { 50 | testImplementation(libs.findBundle("mocking").get()) 51 | testImplementation(libs.findLibrary("junit4").get()) 52 | testImplementation(libs.findLibrary("assertj").get()) 53 | androidTestImplementation("co.elastic.otel.android:test-common") 54 | androidTestImplementation("co.elastic.otel.android:androidtest-agent-rule") 55 | } -------------------------------------------------------------------------------- /instrumentation/oteladapter/library/src/main/java/co/elastic/otel/android/oteladapter/internal/delegate/meter/MeterProviderDelegator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.oteladapter.internal.delegate.meter 20 | 21 | import co.elastic.otel.android.oteladapter.internal.delegate.tools.Delegator 22 | import io.opentelemetry.api.metrics.MeterBuilder 23 | import io.opentelemetry.api.metrics.MeterProvider 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | class MeterProviderDelegator(initialValue: MeterProvider) : Delegator(initialValue), 30 | MeterProvider { 31 | 32 | override fun meterBuilder(instrumentationScopeName: String): MeterBuilder? { 33 | return getDelegate().meterBuilder(instrumentationScopeName) 34 | } 35 | 36 | override fun getNoopValue(): MeterProvider { 37 | return NOOP_INSTANCE 38 | } 39 | 40 | companion object { 41 | val NOOP_INSTANCE: MeterProvider = MeterProvider.noop() 42 | } 43 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/features/exportergate/GateLogRecordExporter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.features.exportergate 20 | 21 | import io.opentelemetry.sdk.common.CompletableResultCode 22 | import io.opentelemetry.sdk.logs.data.LogRecordData 23 | import io.opentelemetry.sdk.logs.export.LogRecordExporter 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | internal class GateLogRecordExporter( 30 | private val delegate: LogRecordExporter, 31 | private val logRecordQueue: ExporterGateQueue 32 | ) : LogRecordExporter { 33 | 34 | override fun export(logs: MutableCollection): CompletableResultCode { 35 | return logRecordQueue.enqueue(logs) 36 | } 37 | 38 | override fun flush(): CompletableResultCode { 39 | return delegate.flush() 40 | } 41 | 42 | override fun shutdown(): CompletableResultCode { 43 | return delegate.shutdown() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /instrumentation/oteladapter/library/src/main/java/co/elastic/otel/android/oteladapter/internal/delegate/logger/noop/NoopLoggerBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.oteladapter.internal.delegate.logger.noop 20 | 21 | import co.elastic.otel.android.oteladapter.internal.delegate.logger.LoggerDelegator 22 | import io.opentelemetry.api.logs.Logger 23 | import io.opentelemetry.api.logs.LoggerBuilder 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | class NoopLoggerBuilder private constructor() : LoggerBuilder { 30 | 31 | override fun setSchemaUrl(schemaUrl: String): LoggerBuilder { 32 | return this 33 | } 34 | 35 | override fun setInstrumentationVersion(instrumentationVersion: String): LoggerBuilder { 36 | return this 37 | } 38 | 39 | override fun build(): Logger { 40 | return LoggerDelegator.Companion.NOOP_INSTANCE 41 | } 42 | 43 | companion object { 44 | val INSTANCE = NoopLoggerBuilder() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/logging/DefaultLoggingPolicy.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.logging 20 | 21 | import co.elastic.otel.android.internal.services.ServiceManager 22 | import co.elastic.otel.android.logging.LogLevel 23 | import co.elastic.otel.android.logging.LoggingPolicy 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | internal class DefaultLoggingPolicy internal constructor(debugMode: Boolean) : 30 | LoggingPolicy { 31 | 32 | private val logLevel by lazy { if (debugMode) LogLevel.DEBUG else LogLevel.INFO } 33 | 34 | override fun isEnabled(): Boolean { 35 | return true 36 | } 37 | 38 | override fun getMinimumLevel(): LogLevel { 39 | return logLevel 40 | } 41 | 42 | companion object { 43 | fun create(serviceManager: ServiceManager): DefaultLoggingPolicy { 44 | return DefaultLoggingPolicy(serviceManager.getAppInfoService().isInDebugMode()) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/opentelemetry/processors/spans/SpanAttributesProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.opentelemetry.processors.spans 20 | 21 | import co.elastic.otel.android.interceptor.Interceptor 22 | import io.opentelemetry.api.common.Attributes 23 | import io.opentelemetry.context.Context 24 | import io.opentelemetry.sdk.trace.ReadWriteSpan 25 | import io.opentelemetry.sdk.trace.ReadableSpan 26 | import io.opentelemetry.sdk.trace.SpanProcessor 27 | 28 | /** 29 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 30 | * any time. 31 | */ 32 | internal class SpanAttributesProcessor(private val interceptor: Interceptor) : 33 | SpanProcessor { 34 | 35 | override fun onStart(parentContext: Context, span: ReadWriteSpan) { 36 | span.setAllAttributes(interceptor.intercept(span.attributes)) 37 | } 38 | 39 | override fun isStartRequired(): Boolean = true 40 | 41 | override fun onEnd(span: ReadableSpan) { 42 | 43 | } 44 | 45 | override fun isEndRequired(): Boolean = false 46 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/time/ntp/SntpClient.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.time.ntp 20 | 21 | import co.elastic.otel.android.internal.time.SystemTimeProvider 22 | import java.io.Closeable 23 | 24 | /** 25 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 26 | * any time. 27 | */ 28 | interface SntpClient : Closeable { 29 | 30 | fun fetchTimeOffset(currentTimeMillis: Long): Response 31 | 32 | companion object { 33 | internal fun create(systemTimeProvider: SystemTimeProvider): SntpClient { 34 | return SntpClientImpl(UdpClient("time.android.com", 123, 48), systemTimeProvider) 35 | } 36 | } 37 | 38 | sealed class Response { 39 | data class Success(val offsetMillis: Long) : Response() 40 | data class Error(val type: ErrorType) : Response() 41 | } 42 | 43 | enum class ErrorType { 44 | TRY_LATER, 45 | ORIGIN_TIME_NOT_MATCHING, 46 | INVALID_VERSION, 47 | INVALID_MODE, 48 | INVALID_TRANSMIT_TIMESTAMP 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /instrumentation/oteladapter/library/src/main/java/co/elastic/otel/android/oteladapter/internal/delegate/tools/MultipleReference.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.oteladapter.internal.delegate.tools 20 | 21 | import com.blogspot.mydailyjava.weaklockfree.WeakConcurrentSet 22 | 23 | /** 24 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 25 | * any time. 26 | */ 27 | class MultipleReference( 28 | private val noopValue: T, 29 | private val delegatorFactory: (T) -> Delegator 30 | ) { 31 | private val references = WeakConcurrentSet>(WeakConcurrentSet.Cleaner.INLINE) 32 | 33 | @Suppress("UNCHECKED_CAST") 34 | fun maybeAdd(value: T): T { 35 | if (value != noopValue) { 36 | val delegator = delegatorFactory.invoke(value) 37 | references.expungeStaleEntries() 38 | references.add(delegator) 39 | return delegator as T 40 | } 41 | 42 | return value 43 | } 44 | 45 | fun reset() { 46 | for (delegator in references) { 47 | delegator?.reset() 48 | } 49 | references.clear() 50 | } 51 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/features/conditionaldrop/ConditionalDropSpanExporter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.features.conditionaldrop 20 | 21 | import co.elastic.otel.android.internal.opentelemetry.SignalType 22 | import io.opentelemetry.sdk.common.CompletableResultCode 23 | import io.opentelemetry.sdk.trace.data.SpanData 24 | import io.opentelemetry.sdk.trace.export.SpanExporter 25 | 26 | /** 27 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 28 | * any time. 29 | */ 30 | internal class ConditionalDropSpanExporter( 31 | private val delegate: SpanExporter, 32 | private val drop: (SignalType) -> Boolean 33 | ) : SpanExporter { 34 | 35 | override fun export(spans: MutableCollection): CompletableResultCode { 36 | if (drop(SignalType.TRACE)) { 37 | return CompletableResultCode.ofSuccess() 38 | } 39 | return delegate.export(spans) 40 | } 41 | 42 | override fun flush(): CompletableResultCode { 43 | return delegate.flush() 44 | } 45 | 46 | override fun shutdown(): CompletableResultCode { 47 | return delegate.shutdown() 48 | } 49 | } -------------------------------------------------------------------------------- /instrumentation/okhttp/bytebuddy/src/main/java/co/elastic/otel/android/okhttp/internal/OkHttpClientAdvice.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.okhttp.internal; 20 | 21 | import net.bytebuddy.asm.Advice; 22 | 23 | import co.elastic.otel.android.okhttp.internal.plugin.OkHttp3Singletons; 24 | import okhttp3.OkHttpClient; 25 | 26 | /** 27 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 28 | * any time. 29 | */ 30 | public class OkHttpClientAdvice { 31 | 32 | @Advice.OnMethodEnter 33 | public static void enter(@Advice.Argument(0) OkHttpClient.Builder builder) { 34 | if (!builder.interceptors().contains(OkHttp3Singletons.CALLBACK_CONTEXT_INTERCEPTOR)) { 35 | builder.interceptors().add(0, OkHttp3Singletons.CALLBACK_CONTEXT_INTERCEPTOR); 36 | builder.interceptors().add(1, OkHttp3Singletons.RESEND_COUNT_CONTEXT_INTERCEPTOR); 37 | builder.interceptors().add(2, OkHttp3Singletons.CONNECTION_ERROR_INTERCEPTOR); 38 | } 39 | if (!builder.networkInterceptors().contains(OkHttp3Singletons.TRACING_INTERCEPTOR)) { 40 | builder.addNetworkInterceptor(OkHttp3Singletons.TRACING_INTERCEPTOR); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/features/conditionaldrop/ConditionalDropLogRecordExporter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.features.conditionaldrop 20 | 21 | import co.elastic.otel.android.internal.opentelemetry.SignalType 22 | import io.opentelemetry.sdk.common.CompletableResultCode 23 | import io.opentelemetry.sdk.logs.data.LogRecordData 24 | import io.opentelemetry.sdk.logs.export.LogRecordExporter 25 | 26 | /** 27 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 28 | * any time. 29 | */ 30 | internal class ConditionalDropLogRecordExporter( 31 | private val delegate: LogRecordExporter, 32 | private val drop: (SignalType) -> Boolean 33 | ) : LogRecordExporter { 34 | 35 | override fun export(logs: MutableCollection): CompletableResultCode { 36 | if (drop(SignalType.LOG)) { 37 | return CompletableResultCode.ofSuccess() 38 | } 39 | return delegate.export(logs) 40 | } 41 | 42 | override fun flush(): CompletableResultCode { 43 | return delegate.flush() 44 | } 45 | 46 | override fun shutdown(): CompletableResultCode { 47 | return delegate.shutdown() 48 | } 49 | } -------------------------------------------------------------------------------- /instrumentation/okhttp/library/src/main/java/co/elastic/otel/android/okhttp/internal/delegate/InterceptorDelegator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.okhttp.internal.delegate 20 | 21 | import java.util.concurrent.atomic.AtomicReference 22 | import okhttp3.Interceptor 23 | import okhttp3.Response 24 | 25 | /** 26 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 27 | * any time. 28 | */ 29 | class InterceptorDelegator private constructor(private val initialValue: Interceptor) : 30 | Interceptor { 31 | private val delegate: AtomicReference = AtomicReference(initialValue) 32 | 33 | override fun intercept(chain: Interceptor.Chain): Response { 34 | return delegate.get().intercept(chain) 35 | } 36 | 37 | fun setDelegate(value: Interceptor) { 38 | delegate.set(value) 39 | } 40 | 41 | fun reset() { 42 | setDelegate(initialValue) 43 | } 44 | 45 | companion object { 46 | private val NOOP_INTERCEPTOR = Interceptor { chain -> chain.proceed(chain.request()) } 47 | 48 | @JvmStatic 49 | fun create(): InterceptorDelegator { 50 | return InterceptorDelegator(NOOP_INTERCEPTOR) 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/interceptor/Interceptor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.interceptor 20 | 21 | import co.elastic.otel.android.internal.utilities.interceptor.MultiInterceptor 22 | import co.elastic.otel.android.internal.utilities.interceptor.NoopInterceptor 23 | 24 | /** 25 | * Generic interface that allows to intercept an object. 26 | */ 27 | fun interface Interceptor { 28 | 29 | companion object { 30 | @JvmStatic 31 | fun composite(interceptors: List>): Interceptor { 32 | if (interceptors.isEmpty()) { 33 | return noop() 34 | } 35 | 36 | if (interceptors.size == 1) { 37 | return interceptors.first() 38 | } 39 | 40 | return MultiInterceptor(interceptors) 41 | } 42 | 43 | @JvmStatic 44 | fun noop(): Interceptor { 45 | return NoopInterceptor() 46 | } 47 | } 48 | 49 | /** 50 | * Intercepts an object of type [T]. 51 | * 52 | * @param item The intercepted object. 53 | * 54 | * @return An object of type [T], it doesn't have to be the one received as parameter. 55 | */ 56 | fun intercept(item: T): T 57 | } -------------------------------------------------------------------------------- /agent-common/src/main/java/co/elastic/otel/android/common/internal/logging/BaseELogger.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.common.internal.logging 20 | 21 | import org.slf4j.Marker 22 | import org.slf4j.event.Level 23 | import org.slf4j.helpers.LegacyAbstractLogger 24 | import org.slf4j.helpers.MessageFormatter 25 | 26 | /** 27 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 28 | * any time. 29 | */ 30 | abstract class BaseELogger protected constructor(tag: String) : LegacyAbstractLogger() { 31 | init { 32 | name = tag 33 | } 34 | 35 | override fun getFullyQualifiedCallerName(): String? { 36 | return null 37 | } 38 | 39 | override fun handleNormalizedLoggingCall( 40 | level: Level, 41 | marker: Marker?, 42 | msg: String, 43 | arguments: Array?, 44 | throwable: Throwable? 45 | ) { 46 | handleLoggingCall( 47 | level, 48 | MessageFormatter.arrayFormat(msg, arguments, throwable).message, 49 | throwable 50 | ) 51 | } 52 | 53 | protected abstract fun handleLoggingCall( 54 | level: Level, 55 | formattedMessage: String, 56 | throwable: Throwable? 57 | ) 58 | } -------------------------------------------------------------------------------- /agent-sdk/src/test/java/co/elastic/otel/android/testutils/TestUdpServer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.testutils 20 | 21 | import java.net.DatagramPacket 22 | import java.net.DatagramSocket 23 | import java.net.SocketException 24 | 25 | class TestUdpServer : Thread() { 26 | private val buf = ByteArray(256) 27 | val socket = DatagramSocket() 28 | 29 | @Volatile 30 | var responseHandler: (DatagramPacket) -> Unit = { clientPacket -> 31 | val response = "Server response".toByteArray() 32 | val packet = 33 | DatagramPacket(response, response.size, clientPacket.address, clientPacket.port) 34 | socket.send(packet) 35 | } 36 | 37 | override fun run() { 38 | while (true) { 39 | if (socket.isClosed) { 40 | continue 41 | } 42 | try { 43 | val packet = DatagramPacket(buf, buf.size) 44 | socket.receive(packet) 45 | 46 | responseHandler(packet) 47 | } catch (e: SocketException) { 48 | continue 49 | } 50 | } 51 | } 52 | 53 | fun close() { 54 | socket.close() 55 | } 56 | 57 | fun getPort(): Int { 58 | return socket.localPort 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /catalog-info.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # yaml-language-server: $schema=https://gist.githubusercontent.com/elasticmachine/988b80dae436cafea07d9a4a460a011d/raw/rre.schema.json 3 | apiVersion: backstage.io/v1alpha1 4 | kind: Resource 5 | metadata: 6 | name: buildkite-pipeline-apm-agent-android-release 7 | tags: 8 | - buildkite 9 | - gpg-sign 10 | - gradle-portal 11 | - maven-central 12 | - release 13 | spec: 14 | implementation: 15 | apiVersion: buildkite.elastic.dev/v1 16 | kind: Pipeline 17 | metadata: 18 | description: 'The APM Android Agent Release :pipeline:' 19 | name: apm-agent-android-release 20 | spec: 21 | pipeline_file: .buildkite/release.yml 22 | provider_settings: 23 | trigger_mode: none 24 | repository: elastic/apm-agent-android 25 | teams: 26 | apm-agent-android: {} 27 | everyone: 28 | access_level: READ_ONLY 29 | observablt-robots: {} 30 | observablt-robots-automation: {} 31 | owner: group:observablt-robots 32 | type: buildkite-pipeline 33 | 34 | --- 35 | # A Component for the release GitHub action 36 | # 37 | # yaml-language-server: $schema=https://json.schemastore.org/catalog-info.json 38 | apiVersion: backstage.io/v1alpha1 39 | kind: Resource 40 | metadata: 41 | name: apm-agent-android-release 42 | description: GitHub action to run the release process for the APM Agent Android 43 | annotations: 44 | backstage.io/source-location: url:https://github.com/elastic/apm-agent-android/blob/main/.github/workflows/release.yml 45 | github.com/project-slug: elastic/apm-agent-android 46 | github.com/team-slug: elastic/apm-agent-android 47 | tags: 48 | - github 49 | - gpg-sign 50 | - gradle-portal 51 | - maven-central 52 | - release 53 | - user:obltmachine 54 | links: 55 | - title: GitHub action 56 | url: https://github.com/elastic/apm-agent-android/actions/workflows/release.yml 57 | spec: 58 | type: github-actions 59 | owner: group:apm-agent-android 60 | lifecycle: production 61 | dependsOn: 62 | - "system:github-actions" 63 | - "user:obltmachine" 64 | -------------------------------------------------------------------------------- /instrumentation/okhttp/library/src/main/java/co/elastic/otel/android/okhttp/internal/OkHttpInstrumentation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.okhttp.internal 20 | 21 | import android.app.Application 22 | import co.elastic.otel.android.api.ElasticOtelAgent 23 | import co.elastic.otel.android.instrumentation.internal.Instrumentation 24 | import co.elastic.otel.android.instrumentation.okhttp.BuildConfig 25 | import co.elastic.otel.android.okhttp.internal.plugin.OkHttp3Singletons 26 | import com.google.auto.service.AutoService 27 | 28 | /** 29 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 30 | * any time. 31 | */ 32 | @AutoService(Instrumentation::class) 33 | class OkHttpInstrumentation : Instrumentation { 34 | 35 | override fun install( 36 | application: Application, 37 | agent: ElasticOtelAgent 38 | ): Instrumentation.Installation { 39 | OkHttp3Singletons.configure(agent.getOpenTelemetry()) 40 | return Instrumentation.Installation { OkHttp3Singletons.reset() } 41 | } 42 | 43 | override fun getId(): String { 44 | return BuildConfig.INSTRUMENTATION_ID 45 | } 46 | 47 | override fun getVersion(): String { 48 | return BuildConfig.INSTRUMENTATION_VERSION 49 | } 50 | } -------------------------------------------------------------------------------- /instrumentation/okhttp/library/src/main/java/co/elastic/otel/android/okhttp/internal/plugin/TracingCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.okhttp.internal.plugin; 20 | 21 | import java.io.IOException; 22 | 23 | import io.opentelemetry.context.Context; 24 | import io.opentelemetry.context.Scope; 25 | import okhttp3.Call; 26 | import okhttp3.Callback; 27 | import okhttp3.Response; 28 | 29 | /** 30 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 31 | * any time. 32 | */ 33 | public final class TracingCallback implements Callback { 34 | private final Callback delegate; 35 | private final Context callingContext; 36 | 37 | public TracingCallback(Callback delegate, Context callingContext) { 38 | this.delegate = delegate; 39 | this.callingContext = callingContext; 40 | } 41 | 42 | @Override 43 | public void onFailure(Call call, IOException e) { 44 | try (Scope scope = callingContext.makeCurrent()) { 45 | delegate.onFailure(call, e); 46 | } 47 | } 48 | 49 | @Override 50 | public void onResponse(Call call, Response response) throws IOException { 51 | try (Scope scope = callingContext.makeCurrent()) { 52 | delegate.onResponse(call, response); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /agent-sdk/src/test/java/co/elastic/otel/android/testutils/NtpUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.testutils 20 | 21 | import co.elastic.otel.android.internal.time.ntp.NtpPacket 22 | 23 | object NtpUtils { 24 | private const val NTP_EPOCH_DIFF_MILLIS = 2208988800000L // According to RFC-868. 25 | 26 | internal fun createNtpPacket( 27 | clientCurrentTime: Long, 28 | expectedOffset: Long = 100L, 29 | receiveServerTime: Long = clientCurrentTime + expectedOffset, 30 | transmitServerTime: Long = receiveServerTime + 5, 31 | originateTimestamp: Long = clientCurrentTime, 32 | responseLeapIndicator: Int = 0, 33 | requestVersionNumber: Int = 4, 34 | responseVersionNumber: Int = requestVersionNumber, 35 | responseMode: Int = 4, 36 | responseStratum: Int = 1 37 | ): NtpPacket { 38 | return NtpPacket( 39 | responseLeapIndicator, 40 | responseVersionNumber, 41 | responseMode, 42 | responseStratum, 43 | toNtpTime(originateTimestamp), 44 | toNtpTime(receiveServerTime), 45 | if (transmitServerTime != 0L) toNtpTime(transmitServerTime) else 0 46 | ) 47 | } 48 | 49 | fun toNtpTime(time: Long): Long { 50 | return time + NTP_EPOCH_DIFF_MILLIS 51 | } 52 | } -------------------------------------------------------------------------------- /agent-sdk/src/main/java/co/elastic/otel/android/internal/exporters/configurable/MutableSpanExporter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to Elasticsearch B.V. under one or more contributor 3 | * license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright 5 | * ownership. Elasticsearch B.V. licenses this file to you under 6 | * the Apache License, Version 2.0 (the "License"); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package co.elastic.otel.android.internal.exporters.configurable 20 | 21 | import io.opentelemetry.sdk.common.CompletableResultCode 22 | import io.opentelemetry.sdk.trace.data.SpanData 23 | import io.opentelemetry.sdk.trace.export.SpanExporter 24 | import java.util.concurrent.atomic.AtomicReference 25 | 26 | /** 27 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 28 | * any time. 29 | */ 30 | internal class MutableSpanExporter : SpanExporter { 31 | private val delegate = AtomicReference() 32 | 33 | override fun export(spans: MutableCollection): CompletableResultCode { 34 | return delegate.get()?.export(spans) ?: CompletableResultCode.ofSuccess() 35 | } 36 | 37 | override fun flush(): CompletableResultCode { 38 | return delegate.get()?.flush() ?: CompletableResultCode.ofSuccess() 39 | } 40 | 41 | override fun shutdown(): CompletableResultCode { 42 | return delegate.get()?.shutdown() ?: CompletableResultCode.ofSuccess() 43 | } 44 | 45 | fun getDelegate(): SpanExporter? { 46 | return delegate.get() 47 | } 48 | 49 | fun setDelegate(value: SpanExporter?) { 50 | delegate.set(value) 51 | } 52 | } --------------------------------------------------------------------------------