For the complete documentation index, see llms.txt. Markdown versions are available by appending .md to documentation URLs.

Android app in Kotlin instrumentation

SigNoz Cloud - This page applies to SigNoz Cloud editions.
Self-Host - This page applies to self-hosted SigNoz editions.

Overview

This document contains instructions on how to set up OpenTelemetry instrumentation in your Android applications built using Kotlin and view your application traces in SigNoz.

Prerequisites

  • Kotlin support in your Android app project.
  • Kotlin toolchain installed; see the Kotlin documentation.
  • Access to a SigNoz Cloud account or self-hosted SigNoz instance.

Send traces to SigNoz

Step 1: Add OpenTelemetry dependencies

Add these to your module build.gradle:

app/build.gradle
implementation platform("io.opentelemetry:opentelemetry-bom:1.25.0")
implementation("io.opentelemetry:opentelemetry-api")
implementation("io.opentelemetry:opentelemetry-context")
implementation("io.opentelemetry:opentelemetry-exporter-otlp")
implementation("io.opentelemetry:opentelemetry-exporter-logging")
implementation("io.opentelemetry:opentelemetry-extension-kotlin")
implementation("io.opentelemetry:opentelemetry-sdk")
implementation("io.opentelemetry:opentelemetry-semconv")

Step 2: Configure network settings

app/src/main/res/xml/network_security_config.xml:

app/src/main/res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">ingest.<region>.signoz.cloud</domain>
    </domain-config>
</network-security-config>

app/src/main/AndroidManifest.xml:

app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
  <uses-permission android:name="android.permission.INTERNET" />
 
  <application
    ...
    android:networkSecurityConfig="@xml/network_security_config">
    ...
  </application>
 
</manifest>

For self-hosted, replace the domain with your collector host (emulator often 10.0.2.2). Allow cleartext only when you use http://.

Step 3: Initialize OpenTelemetry

Create OpentelemetryUtil.kt:

app/src/main/java/com/example/androidkotlindemo/OpenTelemetryUtil.kt
package com.example.androidkotlindemo
 
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator
import io.opentelemetry.context.propagation.ContextPropagators
import io.opentelemetry.exporter.logging.LoggingSpanExporter
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
import io.opentelemetry.sdk.OpenTelemetrySdk
import io.opentelemetry.sdk.resources.Resource
import io.opentelemetry.sdk.trace.SdkTracerProvider
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes
 
class OpenTelemetryUtil {
    companion object {
        @JvmStatic
        fun init() {
            val otelResource = Resource.getDefault().merge(
                Resource.create(
                    Attributes.of(
                        ResourceAttributes.SERVICE_NAME, "<service_name>",
                        ResourceAttributes.SERVICE_VERSION, "<service_version>",
                        ResourceAttributes.HOST_NAME, "<service_name>"
                    )
                )
            )
 
            val sdkTracerProvider = SdkTracerProvider.builder()
                .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create()))
                .addSpanProcessor(
                    BatchSpanProcessor.builder(
                        OtlpGrpcSpanExporter.builder()
                            .setEndpoint("ingest.<region>.signoz.cloud:443/v1/traces")
                            .addHeader("signoz-ingestion-key", "<your-ingestion-key>")
                            .build()
                    ).build()
                )
                .setResource(otelResource)
                .build()
 
            val openTelemetry: OpenTelemetry = OpenTelemetrySdk.builder()
                .setTracerProvider(sdkTracerProvider)
                .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
                .buildAndRegisterGlobal()
 
            tracer = openTelemetry.getTracer("android-tracer", "1.0.0")
        }
 
        private var tracer: Tracer? = null
 
        @JvmStatic
        fun getTracer(): Tracer? {
            return tracer
        }
    }
}

Verify these values:

  • <service_name>: logical name of your mobile service; this is what you will see in SigNoz.
  • <service_version> (optional): Your release version, image tag, or git SHA (e.g., 1.4.2, a01dbef8).
  • <region>: Your SigNoz Cloud region
  • <your-ingestion-key>: Your SigNoz ingestion key

Initialize OpenTelemetry in MainActivity.kt:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        OpenTelemetryUtil.init()
        ...
    }
}

Step 4: Send telemetry data

Add the tracer imports where you create spans:

app/src/main/java/com/example/androidkotlindemo/MainActivity.kt
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.api.trace.Span
import io.opentelemetry.context.Scope

Create spans:

app/src/main/java/com/example/androidkotlindemo/MainActivity.kt
fun parentSpan() {
    val tracer: Tracer = OpenTelemetryUtil.getTracer()!!
    val span = tracer.spanBuilder("Parent Span").startSpan()
    try {
        span.makeCurrent().use {
            childSpan()
        }
    } finally {
        span.end()
    }
}
 
fun childSpan() {
    val tracer: Tracer = OpenTelemetryUtil.getTracer()!!
    val span = tracer.spanBuilder("Child Span").startSpan()
    try {
        span.makeCurrent().use {
            // add attributes/events as needed
        }
    } finally {
        span.end()
    }
}

Step 5: Run the app

Run your application from Android Studio.

Validate

  • In SigNoz, go to Traces Explorer and confirm that the traces for your service (for example <service_name>) are present.
  • Open a recent trace and verify that spans from your Kotlin Android app are present with the attributes you set.

Troubleshooting

Still not seeing data in SigNoz? Work through Debug missing traces, logs, and metrics, which covers SDK diagnostics, Collector connectivity, and the common ingestion errors for all three signals.

  • If spans are missing, verify that the ingest.<region>.signoz.cloud or your self-hosted collector endpoint is reachable from the emulator/device and that the ingestion key (for Cloud) is correct.

Next steps

Is this page helpful

Last updatedAugust 27, 2026

Edit on GitHub