You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As stated here Otel support should implement yourself via Interceptors. But when doing so, it seems that while streaming, Otel seems to lose its Context and doesn't link the traces correctly.
Here is my implementation of it:
import{context,propagation,Span,SpanKind,trace}from'@opentelemetry/api';import{Interceptor}from'@connectrpc/connect';exporttypeCarrier={traceparent?: string;tracestate?: string;}consttracer=trace.getTracer('connect-rpc');typeInterceptorResponse=Awaited<ReturnType<ReturnType<Interceptor>>>;consthandleSpanEnd=(response: InterceptorResponse,span: Span)=>{if(!response.stream){span.end();returnresponse;}asyncfunction*stream(){if(!response.stream){thrownewError('Stream is not defined');}constactiveContext=context.active();// eslint-disable-next-line fp/no-loopsforawait(constmessageofresponse.message){yieldcontext.with(activeContext,()=>message);}span.end();}return{
...response,message: stream(),};};exportconstserverInterceptor: Interceptor[]=[(next)=>async(request)=>{constparentContext=propagation.extract(context.active(),Object.fromEntries(request.header.entries()),);constspan=tracer.startSpan(`${request.service.typeName}/${request.method.name}`,{kind: SpanKind.SERVER,},parentContext,);returncontext.with(trace.setSpan(parentContext,span),async()=>{constactiveContext=context.active();context.bind(activeContext,request);context.bind(activeContext,next);constresponse=awaitnext(request);context.bind(activeContext,response);returnhandleSpanEnd(response,span);});},];exportconstclientInterceptor: Interceptor[]=[(next)=>async(request)=>{constspan=tracer.startSpan(`${request.service.typeName}/${request.method.name}`,{kind: SpanKind.CLIENT,});constparentContext=context.active();returncontext.with(trace.setSpan(parentContext,span),async()=>{constactiveContext=context.active();context.bind(activeContext,request);constoutput: Carrier={};propagation.inject(activeContext,output);Object.entries(output).forEach(([key,value])=>{key&&value&&request.header.set(key,value);});context.bind(activeContext,next);constresponse=awaitnext(request);context.bind(activeContext,response);returnhandleSpanEnd(response,span);});},];
So the clientInterceptor should pick up on the context set by the serverInterceptor. Which works for unary requests but not for streaming requests.
The text was updated successfully, but these errors were encountered:
I noticed that while I see the request message in the client for unary and server-streaming RPCs, I don't see the request message in the server for server-streaming RPCs. We'll have to take a closer look, but this might be a bug in Connect.
As stated here Otel support should implement yourself via Interceptors. But when doing so, it seems that while streaming, Otel seems to lose its Context and doesn't link the traces correctly.
Here is my implementation of it:
So the clientInterceptor should pick up on the context set by the serverInterceptor. Which works for unary requests but not for streaming requests.
The text was updated successfully, but these errors were encountered: