AtatusTrace, built on the OpenTelemetry API.
Prerequisites
- RUM is set up in your application. See iOS Monitoring Setup.
- The backend services you call are instrumented with an Atatus APM agent, or with OpenTelemetry.
Connect requests to backend traces
Trace propagation is driven by the list of hosts you own. Set it on the RUM configuration, and every matching request carries trace headers that your backend reads:example.com covers api.example.com. A pattern such as *.example.com matches subdomains but not example.com itself.
Sampling
sampleRate is the percentage of first-party requests that carry a kept trace, and it combines with the RUM session sample rate. With a session rate of 80 and a trace rate of 20, about 16 percent of requests are traced. The decision is consistent within a session, so you do not get half a journey.
With the default traceControlInjection of .sampled, a request that is not sampled carries no trace headers at all. Set .all when your backend needs a trace context on every request, in which case unsampled requests are propagated with a “do not keep” decision:
Headers that are injected
.trace(hosts:) injects both the Atatus headers and W3C trace context:
To choose the formats per host, for example when a service only understands B3, use
.traceWithHeaders:
Requests from a native application are not subject to CORS, so there is nothing to allow on the browser side. Do check that a proxy, CDN, or WAF in front of your service is not stripping the
x-atatus-*, traceparent, or baggage headers, because that is the usual reason a trace stops at the edge.Record the mobile request as a span
RUM propagation gives you the backend side of the trace. To also see the request as a span from the device, enableAtatusTrace with the same hosts:
urlsession.request client span carrying the URL, method, and status code, using the same trace context RUM injected. RUM remains the owner of header injection, so there is one sampling decision and one trace context per request.
Requests to a host that is not listed in
firstPartyHostsTracing produce no span and no headers. List only the hosts you own, because trace headers are meaningless to a third-party API and expose your trace IDs to it.Trace configuration
urlSessionTracking also takes redactedStatusCodes, which replaces the resource name with the status code so that error responses group together. It defaults to [404], and an empty set turns the behavior off.
Span your own operations
Get the tracer, start a span, and finish it:childOf: span.context, or start a span that is always a trace root:
SpanTags holds the tag names the dashboard understands: resource, operation, service, manualKeep, and manualDrop.
Record an error on a span
setError and log write through the logging product. Without Logs.enable() the span is still sent, but the error details and logs attached to it are dropped with a console warning. Enable Log Collection if you use either.Use the OpenTelemetry API instead
If your code is already written against OpenTelemetry, register the provider and use the standard API. Both paths are backed by the same tracer:get are ignored, so set global tags through Trace.Configuration(tags:). The Atatus-specific helpers, such as keepTrace(), dropTrace(), setError, and setActive(), are only on the Tracer.shared() path.
Propagate trace context yourself
For a client that is notURLSession, inject the headers by hand:
W3CHTTPHeadersWriter() for traceparent and tracestate, or B3HTTPHeadersWriter(injectEncoding: .single) for B3. HTTPHeadersWriter requires the traceContextInjection argument, while the W3C and B3 writers default to .sampled.
Correlate logs and traces
A log written while a span is active carries that trace and span, becausebundleWithTraceEnabled is on by default for every logger. Nothing else is required. See Log Collection.
Next steps
- Report requests as resources with Network Tracking.
- Forward application logs with Log Collection.
- Review the rest of the SDK options in Configuration Options.