@@ -4,11 +4,13 @@ import {
44 appRouter ,
55 createAbortSignalInterceptor ,
66 createRPCContext ,
7+ recordORPCError ,
78 setupUncaughtErrorHandlers ,
89} from "@databuddy/rpc" ;
910import { logger } from "@databuddy/shared/logger" ;
1011import cors from "@elysiajs/cors" ;
11- import { onError } from "@orpc/server" ;
12+ import { context } from "@opentelemetry/api" ;
13+ import { ORPCError , onError } from "@orpc/server" ;
1214import { RPCHandler } from "@orpc/server/fetch" ;
1315import { autumnHandler } from "autumn-js/elysia" ;
1416import { Elysia } from "elysia" ;
@@ -39,7 +41,8 @@ const rpcHandler = new RPCHandler(appRouter, {
3941
4042const app = new Elysia ( )
4143 . state ( "tracing" , {
42- span : null as ReturnType < typeof startRequestSpan > | null ,
44+ span : null as ReturnType < typeof startRequestSpan > [ "span" ] | null ,
45+ activeContext : null as ReturnType < typeof context . active > | null | undefined ,
4346 startTime : 0 ,
4447 } )
4548 . use ( publicApi )
@@ -58,11 +61,19 @@ const app = new Elysia()
5861 . onBeforeHandle ( function startTrace ( { request, path, store } ) {
5962 const method = request . method ;
6063 const startTime = Date . now ( ) ;
61- const span = startRequestSpan ( method , request . url , path ) ;
6264
63- // Store span and start time in Elysia store
65+ // Extract route from path (e.g., "/rpc/websites.list" -> "websites.list")
66+ const route = path . startsWith ( "/rpc/" ) ? path . slice ( 5 ) : path ;
67+ const { span, activeContext } = startRequestSpan (
68+ method ,
69+ request . url ,
70+ route
71+ ) ;
72+
73+ // Store span, context, and start time in Elysia store
6474 store . tracing = {
6575 span,
76+ activeContext,
6677 startTime,
6778 } ;
6879 } )
@@ -99,15 +110,35 @@ const app = new Elysia()
99110 . use ( exportRoute )
100111 . all (
101112 "/rpc/*" ,
102- async ( { request } : { request : Request } ) => {
113+ async ( { request, store } ) => {
103114 try {
104- const context = await createRPCContext ( { headers : request . headers } ) ;
105- const { response } = await rpcHandler . handle ( request , {
106- prefix : "/rpc" ,
107- context,
108- } ) ;
115+ // Run RPC handler within the active trace context if available
116+ const handler = async ( ) => {
117+ const rpcContext = await createRPCContext ( {
118+ headers : request . headers ,
119+ } ) ;
120+ const { response } = await rpcHandler . handle ( request , {
121+ prefix : "/rpc" ,
122+ context : rpcContext ,
123+ } ) ;
124+ return response ;
125+ } ;
126+
127+ const activeContext = store . tracing ?. activeContext ;
128+ const response = activeContext
129+ ? await context . with ( activeContext , handler )
130+ : await handler ( ) ;
131+
109132 return response ?? new Response ( "Not Found" , { status : 404 } ) ;
110133 } catch ( error ) {
134+ // Record ORPC errors in OpenTelemetry
135+ if ( error instanceof ORPCError ) {
136+ recordORPCError ( {
137+ code : error . code ,
138+ message : error . message ,
139+ } ) ;
140+ }
141+
111142 logger . error ( { error } , "RPC handler failed" ) ;
112143 return new Response ( "Internal Server Error" , { status : 500 } ) ;
113144 }
0 commit comments