aws_xray_sdk 0.3.1
aws_xray_sdk: ^0.3.1 copied to clipboard
AWS X-Ray distributed tracing for Dart. Auto-traces dart:io HTTP and Smithy SDK clients, propagates X-Amzn-Trace-Id, and sends segments via UDP. First-class Lambda support.
Changelog #
0.3.1 #
Added #
package:httpAWS tracing now recognizes the Lambda data-planeInvokecall.XRayBaseClientreads the operation (Invoke) and target function from the REST path (/2015-03-31/functions/{name}/invocations), recording it asaws.function_nameand adding the function toaws.resource_namesso the invoked Lambda appears as its own node in the X-Ray service map.AwsData.functionName, serialized asfunction_namein theawsblock per the X-Ray segment schema.
0.3.0 #
Stable release of the 0.3.0 line. Functionally identical to 0.3.0-beta.2 —
no API or behavior changes since the beta — with documentation and example
polish. For the full set of changes since 0.2.1, see the 0.3.0-beta.1 and
0.3.0-beta.2 sections below. Headline additions across the line:
- Zero-config setup.
XRay.configure()builds a tracer from the AWS environment, installs a process-wide default (XRay.tracer), and patches HTTP in one idempotent call;XRay.reset()returns to the unconfigured no-op state. package:httptracing.XRay.aws()/XRay.httpClientFor()wrap anhttp.Clientforaws_client/aws_*_apiSDKs, resolving the global tracer per request.- Lambda ergonomics.
LambdaTraceCapturecaptures theLambda-Runtime-Trace-Idheader per invocation andXRay.runLambdaInvocationcollapses the parent-decision branch into one call. InMemorySenderfor asserting on emitted segments and Lambda packets in tests, plusXRayTracer.onSampledDrop/onSendErrordiagnostics.
Changed #
- Examples and docs updated: the AWS SDK client example now prints the
subsegments it produces (via
InMemorySender), and the README/AGENT docs were corrected to match the shipped API surface.
0.3.0-beta.2 #
Second beta of the 0.3.0 line. This release tightens the beta.1 APIs and fixes trace-fidelity edge cases found during integration testing.
Added #
InMemorySender, exported from the package barrel, for tests that need to assert on emitted segments or Lambda packets without UDP or tracer mocks.XRay.annotate(Map<String, Object>)andXRay.metadata(key, value)facade helpers for adding data through the process-wide tracer.TraceId.parseRootString(header)for log-enrichment callers that only need the validated root trace id as a string.XRayTracer.onSampledDropandXRayTracer.onSendErrorhooks to distinguish intentional sampled-out drops from send failures without faulting traced code.
Changed #
XRay.aws()andXRayBaseClient(inner)now resolve the global tracer per request when no explicit tracer is passed. Clients created beforeXRay.configure()now trace after configuration.- The unconfigured no-op tracer reports
isSampled == falseoutside a trace zone, so it does not advertiseSampled=1for traces it will never emit. contextMissingPolicyis mutable onXRayTracerfor runtime diagnostics and tests.ReservoirSamplernow uses a monotonicStopwatchclock instead of wall time, avoiding sampling-window resets from clock adjustments.- Oversized segment encoding recursively splits large subsegment trees into independent subsegment documents where possible.
- Child subsegments are serialized in start-time order for clearer timelines when concurrent work closes out of order.
Fixed #
- AWS endpoint detection now covers standard, China, ISO, and ISO-B partitions,
matching region extraction and preserving AWS metadata/error parsing outside
.amazonaws.com. - AWS query-protocol XML error parsing now handles namespace prefixes, tag attributes, CDATA, XML entities, malformed UTF-8, and out-of-range numeric entities without crashing the request path.
LambdaTraceCapturestores captured runtime trace headers in a zone-local slot duringrun(), preventing interleaved invocations from reading each other's header.- Unsampled
runLambdainvocations now skip subsegment serialization and notifyonSampledDropbefore any send/encoding work. - Annotation key sanitization now emits a warn-once diagnostic when keys are changed, making lossy collisions visible.
0.3.0-beta.1 #
First beta of the 0.3.0 line. Themes: zero-config setup ergonomics, segment-level HTTP recording for the server middleware, and a packaged Lambda trace-header capture. Pre-release — published for integration testing.
Added #
- Zero-config setup.
XRay.configure({fromEnv, serviceName, sampling, tracer, patchDartIoHttp})builds a tracer from the standard AWS environment (AWS_XRAY_DAEMON_ADDRESS, IPv6-literal safe;AWS_LAMBDA_FUNCTION_NAME), installs it as the process-wide default, and patches HTTP — in one idempotent call.XRay.reset()returns to the unconfigured state. - Global default tracer.
XRay.tracergetter/setter andXRay.isConfigured. Until configured, the default is a no-op that discards everything, so instrumentation runs unconditionally without null checks. XRay.aws({inner})and an optional-tracerXRay.httpClientForreturn a pre-wrappedpackage:httpclient (using the global tracer) foraws_client/aws_*_apiconstructors.XRayBaseClient(inner)now accepts an optional tracer, defaulting to the global default tracer.XRay.runLambdaInvocation(capture, name, fn)runs one Lambda invocation, parenting under theAWS::Lambda::Functionfacade when a trace header was captured or starting a fresh segment otherwise.LambdaTraceCapturepackages theLambda-Runtime-Trace-Idcapture (http.runWithClient-based) and exposes a parsedLambdaTraceContext(traceId,parentId,sampled) — no runtime fork needed.XRayTracer.annotateAll(Map)adds many annotations in one call.XRayTracer.currentTraceIdconvenience getter for the active trace id.- Segment HTTP data.
Segment.http(withSegment.withHttp);handleTracednow records the request (method, url, traced) and response (status, content_length) on the segment for the X-Ray service map, and forwards the request method/path into the sampling decision.Segment.httpwas removed in 0.2.0 as structurally unusable; it is reintroduced now that the middleware populates it.
Changed #
handleTracedreads the sampling decision inside the run zone, so an unsampled trace is correctly markedSampled=0on the outgoing header (previously could fail open toSampled=1).- A handler that throws before setting a status no longer records a misleading
200; the response block is omitted so the faulted segment stands alone.
Documentation #
- README: zero-config setup, the
aws_client/aws_*_apirecipe, and theLambdaTraceCapture-based Lambda example (replacing a hand-rolled shim). doc/architecture.md: updated for the new facade/tracer API surface.
0.2.1 #
Documentation #
- Consolidated the two overlapping HTTP sections in the README into one
HTTP tracingsection (dart:iopatch,package:httpclient, response-body lifecycle), added a contents nav, and removed a duplicate daemon-setup section. - Corrected the
AOT-safefeature claim and dropped the misleadingFlutter safelabel — the package usesdart:ioand is not Flutter-web compatible (matchingdoc/tracing-behavior.md).
0.2.0 #
First release since 0.1.0. Contains breaking changes (allowed pre-1.0).
Major themes: nested/live tracing, package:http and server-side support,
automatic double-trace suppression, a hardened non-faulting transport, annotation
validation, and a dead-code cleanup.
Breaking changes #
- Removed uninstrumented / dead API. Each can be restored from git history
once the matching instrumentation exists:
SqlDataandSubsegment.withSql(no SQL instrumentation existed).HttpRequestData.userAgent,clientIp, andxForwardedFor(never populated).Cause.workingDirectory(never populated).Segment.service,Segment.http, andSegment.aws(structurally always null —Segmentexposed no way to set them).- The unused helpers
namespaceForClientandnamespaceFor<T>.
HttpApiSenderwas removed — SigV4 signing is not yet implemented; useUdpSender(the default) for all deployments.- The stale
awsServiceNamespacesmap was removed — Smithy client registration now defaults directly to the valid X-Ray namespaceaws. - Registry internals are no longer exported from the package barrel. Use
XRay.registerClient/XRay.fromClient; direct access toclientRegistry,descriptorFor, andClientDescriptorwas an implementation detail. - Annotation values are now sanitized.
annotatekeeps the same signature but no longer stores arbitrary keys/values verbatim (see Annotation validation below) — a caller relying on invalid keys/values reaching X-Ray unchanged will see different output. SmithyResponseAdapternow returns AWS response metadata. Adapter records must include nullablerequestId,region, anderrorCodefields in addition tostatusCodeandcontentLength. This letsXRay.fromClientpopulateaws.request_id,aws.region, and AWS throttling flags.
New features #
Nested & live tracing
XRayTracer.captureAsync(name, fn)runs a block as a nested subsegment. Manual subsegments and auto-instrumented HTTP/AWS calls opened inside it become its children, so traces reflect the real call tree (previously all subsegments were flat siblings). Each scope is bound to a forkedZone, so concurrent captures stay independent.XRayTracer.annotate(key, value)/addMetadata(key, value)mutate the entity currently being traced (the activecaptureAsyncsubsegment, or the segment itself). Previously annotations could only be set atSegment.begintime.TraceContext— the live handle passed to acaptureAsyncblock (annotate/addMetadata/setError/setFault).- An uncaught error from
run/runLambda/captureAsyncnow marks the enclosing entity as faulted with a cause.
package:http and server-side tracing
XRayBaseClientwraps apackage:httpBaseClient, tracing each request with the same subsegment + AWS metadata extraction as thedart:iopath.- HTTP instrumentation now sets
http.request.traced = truewhen the SDK injectsX-Amzn-Trace-Id, allowing downstream service-to-service linkage in X-Ray. handleTraced(request, tracer, handler)—dart:ioHttpServermiddleware that continues an incomingX-Amzn-Trace-Id, runs the handler in a trace zone, and injects the trace header into the response for downstream propagation.XRay.untracedHttpClient()builds anHttpClientthat is never wrapped bypatchHttp, for calls that should emit no subsegment.
Automatic double-trace suppression
XRayBaseClientandXRay.fromClientrun their inner send insiderunWithoutDartIoTracing(a zone flag);XRayHttpClientstands down when it is set. A request passing through both a wrapper and apatchHttp-patcheddart:ioclient is now traced exactly once.- Smithy client namespaces are normalized to X-Ray schema values (
awsorremote) so custom orAWS::...registration values cannot produce invalid subsegment namespaces.
AWS trace fidelity
- Smithy client wrappers record
aws.request_idwhen the response adapter supplies it and recordaws.regionfrom the adapter or request URL. - AWS throttles are detected from known AWS error codes such as
ProvisionedThroughputExceededException,ThrottlingException,RequestLimitExceeded,TooManyRequestsException, andSlowDown, not only from HTTP429. - Error-status responses that do not throw now synthesize a remote HTTP
causeso 4xx/5xx subsegments have diagnostic detail.
Transport & sampling
UdpSendergained an optionalonError(Object)callback (silent by default) and a re-openableclose(); it resolves + binds once (memoized), uses an IP-literal fast path, and contains all resolution/bind/send errors.XRayTracergaineddaemonHost/daemonPortconstructor parameters and acontextMissingPolicy(ContextMissingPolicy.ignore/logError/runtimeError) controlling what happens when trace data is recorded with no active trace zone.ReservoirSampleraccepts an injectablenowclock (DateTime Function()) for deterministic tests.
Annotation validation (X-Ray best practices)
- Annotation keys and values are validated at every entry point
(
XRayTracer.annotate, theTraceContexthandle,Segment.annotate,Subsegment.annotate) by sanitizing, never throwing: invalid key characters (outside[A-Za-z0-9_]) become_, and a non-scalar value (notString/bool/int/double) is coerced to itstoString(). A malformed annotation never drops the trace or faults the traced operation. Metadata remains unvalidated (any JSON-serializable value) by design.
Fixes #
- Non-faulting transport guarantee. A
Sender(or scope-serialization) failure during finalization can no longer fault or mask the traced operation —run/runLambda/closeSegment/close()contain transport errors for anySender, not justUdpSender. Fixes a throw in the finalizationfinallysupersedingfn's return value or original exception. UdpSendercould fault the traced operation. Removed a per-send DNSlookup+bind, a socket-bind race under concurrency, and unguardedlookup/binderrors escaping into the awaitedrun().XRayHttpClientdouble-recorded a subsegment when a response body stream errored then completed (consumed withcancelOnError: false). The fault path and the done path are now mutually exclusive.- Undrained HTTP responses no longer drop spans. If an instrumented
dart:ioorpackage:httpresponse body is never consumed, trace finalization emits the subsegment once withmetadata.xray.incomplete = trueand the request/response data known so far. - Manual subsegment close is idempotent. Re-closing a subsegment, including a late close after an incomplete-response sweep, records the first outcome once.
handleTracedreported the wrongSampled=flag. The response header's sampling flag was read after the trace zone closed (fail-opentrue), so it always emittedSampled=1; it now reports the real decision.Segment.withFault(err)/Segment.withError(err)record exceptions directly on segments (previously onlySubsegmentsupported this).Segment.close()is idempotent — calling it on an already-closed segment preserves the original timing.XRayHttpClientpreserves the request scheme for host/port overloads (get/post/openusehttp, not an unconditionalhttps) and closes the traced subsegment ondetachSocket()raw-socket upgrades.- Removed debug
stderr.writelnlogging fromrunLambdaand per-packetdart:developerlogging fromUdpSender.
Internal & architecture #
- Runtime trace state is a mutable
TraceScopeentity tree (internal), serialized to the immutableSegment/Subsegmentdocuments at scope close;Subsegment.open(...)materializes an accumulated scope. runLambdaemits its handler span via the subsegment model (consistentnowSeconds()timing, nested children, fault capture) instead of a hand-built document.- Extracted
_runZonedintracer.dart(shared byrun/runLambda); reusedencodeSubsegmentDocin the encoder's oversize-split path; removed the unimplemented HTTP API sender stub; de-duplicated HTTP metadata, AWS region, throttle-code, and trace-header helpers.
Documentation & tests #
- Documented X-Ray annotation/metadata constraints, the
ContextMissingPolicyoptions, local sampler semantics + no-centralized-fallback behavior, the double-trace suppression model, and the Lambda subsegment contract (README +doc/architecture.md). - Documented the HTTP tracing lifecycle, including incomplete spans for
undrained responses and the single-use request expectation for
XRayBaseClient. - Added a
Segment/SubsegmentJSON golden test and broad coverage for the HTTP clients,runLambda, transport containment,UdpSenderrobustness, annotation validation,handleTraced, and the resource extractors.
0.1.0 #
Initial release.
Core tracing #
XRayTracerwith Zone-based context propagation (run,runLambda)- Immutable
SegmentandSubsegmentvalue objects with annotation and metadata support TraceIdgeneration and parsing (Root/Parent/Sampledheader fields)FixedRateSamplerandReservoirSampler
Transport #
UdpSender— fire-and-forget UDP to the X-Ray daemon (IPv4 / IPv6, 64 KB split)encodeSubsegmentDoc— encode an independent subsegment document for LambdaNoopSenderfor tests and local development
HTTP instrumentation #
XRayHttpClientwrapsdart:ioHttpClient; auto-traces every requestXRay.patchHttp/XRay.unpatchHttpfor globaldart:iopatching- Automatic
namespace='aws'for*.amazonaws.comhosts
AWS SDK wrappers #
XRay.registerClient<T>/XRay.fromClient<T>for Smithy-generated clientsResourceExtractorbuilt-ins for DynamoDB, S3, KMS, SQS, and SNS
Lambda support #
XRayTracer.runLambdaemits a subsegment document parented to the auto-createdAWS::Lambda::Functionsegment instead of a competing top-level segmentAWS_XRAY_DAEMON_ADDRESSenv-var parsing for link-local daemon address