Distributed tracing mobile
Agent skills for logging, metrics, tracing, crash reporting, and analytics in mobile apps.
npx -y skills add almasumdev/awesome-mobile-observability-agent-skills --skill distributed-tracing-mobileAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Instrument mobile apps with OpenTelemetry client SDKs so traces start on the device and propagate to the backend. Use when wiring up tracing on Android, iOS, Flutter, or React Native.
SKILL.md
7.1 KB, as published. Nobody here has run it
Distributed Tracing on Mobile
Instructions
A mobile trace is only useful if it connects to the backend trace. Use OpenTelemetry, start the root span on the client for the user-visible operation, and propagate via W3C headers.
1. Model: the Root Span Lives on the Client
For any user-initiated flow (tap -> network -> render), the root span starts on the device. Backend spans become children via the propagated context.
ui.loadorui.actionis the root.- Each outbound HTTP call is a child
http.clientspan. - Backend spans become children of those
http.clientspans.
Do not start the root span in the backend and try to "attach" the client later; the client view is half of the latency that matters.
2. Android (Kotlin)
val tracerProvider = SdkTracerProvider.builder()
.addSpanProcessor(
BatchSpanProcessor.builder(
OtlpHttpSpanExporter.builder()
.setEndpoint("https://otel.example.com/v1/traces")
.addHeader("Authorization", "Bearer ${BuildConfig.OTEL_TOKEN}")
.build()
).build()
)
.setResource(Resource.create(Attributes.of(
AttributeKey.stringKey("service.name"), "my-app-android",
AttributeKey.stringKey("service.version"), BuildConfig.VERSION_NAME,
AttributeKey.stringKey("deployment.environment"), BuildConfig.FLAVOR,
AttributeKey.stringKey("device.model"), Build.MODEL
)))
.setSampler(Sampler.parentBased(Sampler.traceIdRatioBased(0.15)))
.build()
val otel = OpenTelemetrySdk.builder()
.setTracerProvider(tracerProvider)
.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
.buildAndRegisterGlobal()
Consider io.opentelemetry.android:android-agent for auto-instrumentation of activity lifecycle, network, and crashes.
3. iOS (Swift)
let exporter = OtlpHttpTraceExporter(endpoint: URL(string: "https://otel.example.com/v1/traces")!,
headers: ["Authorization": "Bearer \(otelToken)"])
let processor = BatchSpanProcessor(spanExporter: exporter,
scheduleDelay: 30,
maxQueueSize: 2048,
maxExportBatchSize: 512)
let provider = TracerProviderBuilder()
.add(spanProcessor: processor)
.with(sampler: ParentBasedSampler(root: TraceIdRatioBasedSampler(ratio: 0.15)))
.with(resource: Resource(attributes: [
"service.name": .string("my-app-ios"),
"service.version": .string(Bundle.main.version),
"deployment.environment": .string(env),
"device.model": .string(UIDevice.current.modelIdentifier)
]))
.build()
OpenTelemetry.registerTracerProvider(tracerProvider: provider)
OpenTelemetry.registerPropagators(textPropagators: [W3CTraceContextPropagator()], baggagePropagator: W3CBaggagePropagator())
4. Flutter (Dart)
The official opentelemetry package works in Dart; for HTTP exporter use opentelemetry_sdk + opentelemetry_exporter_otlp_http. A lighter alternative is Sentry's performance SDK which exposes OTel-compatible APIs.
final provider = TracerProviderBase(
resource: Resource([
Attribute.fromString('service.name', 'my-app-flutter'),
Attribute.fromString('service.version', appVersion),
Attribute.fromString('deployment.environment', env),
]),
sampler: ParentBasedSampler(TraceIdRatioBasedSampler(0.15)),
processors: [BatchSpanProcessor(OtlpHttpSpanExporter(
uri: Uri.parse('https://otel.example.com/v1/traces'),
headers: {'Authorization': 'Bearer $token'}))],
);
registerGlobalTracerProvider(provider);
5. React Native (TypeScript)
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { W3CTraceContextPropagator } from '@opentelemetry/core';
import { Resource } from '@opentelemetry/resources';
const provider = new WebTracerProvider({
resource: new Resource({
'service.name': 'my-app-rn',
'service.version': pkg.version,
'deployment.environment': Config.ENV,
}),
});
provider.addSpanProcessor(new BatchSpanProcessor(new OTLPTraceExporter({
url: 'https://otel.example.com/v1/traces',
headers: { Authorization: `Bearer ${Config.OTEL_TOKEN}` },
})));
provider.register({ propagator: new W3CTraceContextPropagator() });
Patch global.fetch and XMLHttpRequest via the OTel instrumentations so HTTP calls are traced automatically.
6. Start Spans Around User Intents
val tracer = GlobalOpenTelemetry.getTracer("my-app")
suspend fun loadHome() {
val span = tracer.spanBuilder("home.load").setSpanKind(SpanKind.INTERNAL).startSpan()
try {
withContext(span.asContextElement()) {
val feed = feedApi.fetch() // http.client span is auto-created
homeView.render(feed) // record render duration as event
span.addEvent("first_frame_rendered")
}
} catch (t: Throwable) {
span.recordException(t); span.setStatus(StatusCode.ERROR); throw t
} finally { span.end() }
}
7. Sampling
ParentBased(TraceIdRatioBased(0.15))in production,AlwaysOnin debug.- Override to 100% for transactions that end in error: use a
TailSampler-style composite, or mark the transactionsampled = truemanually when catching an exception. - Fresh-release boost: 100% for the first 24 hours after a release, then taper.
8. Resource Attributes (mandatory)
Every span must carry:
service.name,service.version,deployment.environmenttelemetry.sdk.name,telemetry.sdk.version(auto)device.model,os.name,os.versionapp.release(same string as Sentry/Crashlytics release)
9. Cost Control
- Spans are the most expensive telemetry. Cap spans per transaction to a reasonable number (~50) and use span events for finer granularity.
- Use
SpanLimitsto cap attribute count (32), attribute length (1 KB), and events (128). - Drop spans shorter than 1 ms in chatty instrumentations (this is usually wall-clock noise).
10. Verification
- A manual golden flow (launch -> search -> checkout) produces one trace that spans client + backend with the same
trace_id. - In the vendor UI the trace waterfall shows both client and backend spans, ordered correctly.
Checklist
- OTel SDK initialized with resource attributes and W3C propagators.
-
ParentBased(TraceIdRatioBased(0.15))sampler in production; 100% in debug. - Every user intent has a root span that wraps its network calls.
- Exporters use OTLP/HTTP with batching tuned for mobile (30 s foreground).
- Span limits are configured to cap attributes and events.
- Golden flow verifies end-to-end trace correlation with the backend.
- Release boost to 100% for the first 24 hours is configured.