Status: development
The OpenTelemetry HttpUrlConnection instrumentation for Android will automatically instrument client-side usage of:
The instrumentation operates by intercepting application calls to the APIs that initiate or read from network connections. It performs three primary actions:
- adds distributed tracing context to outgoing requests
- creates and ends client HTTP spans
- records request/response metadata and exceptions
See the Android URLConnection documentation for reference.
This instrumentation produces HTTP client spans using the OpenTelemetry HTTP semantic
conventions. The instrumentation scope (instrumentation library name) is
io.opentelemetry.android.http-url-connection.
This instrumentation creates a span for each HTTP request. Spans are ended when one of
the following occurs: the response stream is fully read, the stream is closed,
disconnect() is called, or an exception occurs while interacting with the connection.
- Type: Span
- Name: Determined by the HTTP span name extractor (typically
HTTP {method}or derived from the URL) - Description: Client-side HTTP request
- Attributes (following OpenTelemetry HTTP semantic conventions):
http.request.method— request method (GET, POST, etc.)url.full— full request URLurl.scheme,url.path,url.query— parts of the request URL when availablehttp.response.status_code— response status codenetwork.protocol.version— protocol version (e.g.1.1,2for HTTP/2)server.address— logical server hostserver.port— logical server portnetwork.peer.address/network.peer.port— connection endpoint, when available- Request and response headers captured according to configuration:
http.request.header.<name>/http.response.header.<name>
If the request throws an IOException, the span is ended and the exception is recorded.
You can customize which request and response headers are captured and other behavior via
the HttpUrlInstrumentation setters exposed through AndroidInstrumentationLoader.
These settings are applied when HttpUrlConnectionSingletons.configure(...) is called
during instrumentation setup. See the Configurations section above for how to access
the instrumentation instance.
The instrumentation injects the configured context propagators into the request using request properties (via a TextMap setter), allowing distributed tracing across services.
This plugin enhances the Android application host code by instrumenting all critical APIs (specifically those that initiate a connection). It intercepts calls to these APIs to ensure the following actions are performed:
- Context is added for distributed tracing before actual API is called (i.e before connection is initiated).
- Traces and spans are generated and properly closed.
- Any exceptions thrown are recorded.
A span associated with a given request is concluded in the following scenarios:
- When the getInputStream()/getErrorStream() APIs are called, the span concludes after the stream is fully read, an IOException is encountered, or the stream is closed.
- When the disconnect API is called.
Spans won't be automatically ended and reported otherwise. If any of your URLConnection requests do not call the span concluding APIs mentioned above, refer the section entitled "Scheduling Harvester Thread". This section provides guidance on setting up a recurring thread that identifies unreported, idle connections and ends/reports any open spans associated with them. Idle connections are those that have been read from previously but have been inactive for a particular configurable time interval (defaults to 10 seconds).
The minimum supported Android SDK version is 23, though it will also instrument APIs added in the Android SDK version 26 when running on devices with API level 26 and above. If your project's minSdk is lower than 26, then you must enable corelib desugaring.
Further, in order to run the app built on debug, you need to add the following property in
gradle.propertiesfile:
- If AGP <= 8.3.0, set
android.enableDexingArtifactTransform=false- If AGP > 8.3.0, set
android.useFullClasspathForDexingTransform=trueFor the full context for these workaround, please see this issue for AGP <= 8.3.0 or this issue for AGP > 8.3.0.
Replace BYTEBUDDY_VERSION with the latest release.
This plugin leverages Android's Transform API to instrument bytecode at compile time. You can find more info on its repo page.
plugins {
id 'net.bytebuddy.byte-buddy-gradle-plugin' version 'BYTEBUDDY_VERSION'
}implementation("io.opentelemetry.android.instrumentation:httpurlconnection-library:1.3.0-alpha")
byteBuddy("io.opentelemetry.android.instrumentation:httpurlconnection-agent:1.3.0-alpha")To schedule a periodically running thread to conclude/report spans on any unreported, idle connections, add the below code in the function where your application starts ( that could be onCreate() method of first Activity/Fragment/Service):
HttpUrlInstrumentation instrumentation = AndroidInstrumentationLoader.getInstrumentation(HttpUrlInstrumentation.class);
instrumentation.setConnectionInactivityTimeoutMs(customTimeoutValue); //This is optional. Replace customTimeoutValue with a long data type value which denotes the connection inactivity timeout in milli seconds. Defaults to 10000ms
Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(instrumentation.getReportIdleConnectionRunnable(), 0, instrumentation.getReportIdleConnectionInterval(), TimeUnit.MILLISECONDS);instrumentation.getReportIdleConnectionRunnable()is the API to get the runnable.- By default, connections inactive for 10000ms are reported. To optionally change the connection inactivity timeout call
instrumentation.setConnectionInactivityTimeoutMs(customTimeoutValue)API as shown in above code snippet. - It is efficient to run the harvester thread at the same time interval as the connection inactivity timeout used to identify the connections to be reported.
instrumentation.getReportIdleConnectionInterval()is the API to get the same connection inactivity timeout interval (milliseconds) you have configured or the default value of 10000ms if not configured.
You can optionally configure the automatic instrumentation by using the setters from HttpUrlInstrumentation instance provided via the AndroidInstrumentationLoader as shown below:
HttpUrlInstrumentation instrumentation = AndroidInstrumentationLoader.getInstrumentation(HttpUrlInstrumentation.class);
// Call `instrumentation` setters.Note
You must make sure to apply any configurations before initializing your OpenTelemetryRum instance (i.e. calling OpenTelemetryRum.builder()...build()). Otherwise your configs won't be taken into account during the RUM initialization process.
After adding the plugin and the dependencies to your project, and after doing the required configurations, your requests will be traced automatically.