agentsclimarketplace

Distributed tracing mobile

Skill almasumdev/awesome-mobile-observability-agent-skills/.github/skills/tracing/distributed-tracing-mobile

Agent skills for logging, metrics, tracing, crash reporting, and analytics in mobile apps.

Install
npx -y skills add almasumdev/awesome-mobile-observability-agent-skills --skill distributed-tracing-mobile

Assembled 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.load or ui.action is the root.
  • Each outbound HTTP call is a child http.client span.
  • Backend spans become children of those http.client spans.

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, AlwaysOn in debug.
  • Override to 100% for transactions that end in error: use a TailSampler-style composite, or mark the transaction sampled = true manually 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.environment
  • telemetry.sdk.name, telemetry.sdk.version (auto)
  • device.model, os.name, os.version
  • app.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 SpanLimits to 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.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.