Review

Propagate member identity via OTel baggage for barrel redemptions

CaskShare's redemption service hops across inventory, cooperage, and Shippo for barrel-share pours. Product wants every downstream span tagged with the member so support can open one Honeycomb trace and see who claimed the 12-year rye. Inject email and account_id into W3C baggage in the FastAPI auth middleware and promote baggage onto spans with BaggageSpanProcessor before the OTLP export to our managed Honeycomb collector.

OpenTelemetryTier 4opentelemetrybaggagepiiprivacy

Click a line to flag it, pick one or more labels, then submit. If the change looks correct, approve it.

services/redemption/telemetry/identity_baggage.py+17-0
11from opentelemetry import baggage, context, trace
22from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
33from opentelemetry.sdk.resources import Resource
44from opentelemetry.sdk.trace import TracerProvider
55from opentelemetry.sdk.trace.export import BatchSpanProcessor
6+from opentelemetry.processor.baggage import BaggageSpanProcessor
67from starlette.middleware.base import BaseHTTPMiddleware
78from starlette.requests import Request
89
910def configure_tracing(otlp_endpoint: str) -> None:
1011 provider = TracerProvider(
1112 resource=Resource.create({"service.name": "caskshare-redemption"}),
1213 )
14+ # Copy baggage keys onto every span so Honeycomb can filter by member
15+ provider.add_span_processor(BaggageSpanProcessor())
1316 provider.add_span_processor(
1417 BatchSpanProcessor(OTLPSpanExporter(endpoint=otlp_endpoint))
1518 )
1619 trace.set_tracer_provider(provider)
1720
1821
22+class MemberBaggageMiddleware(BaseHTTPMiddleware):
23+ async def dispatch(self, request: Request, call_next):
24+ member = getattr(request.state, "member", None)
25+ if member is None:
26+ return await call_next(request)
27+
28+ ctx = baggage.set_baggage("user.email", member.email)
29+ ctx = baggage.set_baggage("account.id", str(member.account_id), context=ctx)
30+ token = context.attach(ctx)
31+ try:
32+ return await call_next(request)
33+ finally:
34+ context.detach(token)
35+