@@ -48,36 +48,105 @@ export const createCallerFactory = t.createCallerFactory;
4848
4949/**
5050 * Middleware to log the start, end, and duration of a procedure.
51+ * All logs are structured JSON for better parsing by log aggregators.
52+ * Errors are tracked in PostHog for centralized monitoring.
5153 * @param path - The path of the procedure
5254 * @param type - The type of the procedure
55+ * @param input - The input to the procedure
5356 * @param next - The next middleware
5457 * @returns The result of the next middleware
5558 */
56- const withLogging = t . middleware ( async ( { path, type, next } ) => {
59+ const withLogging = t . middleware ( async ( { path, type, input , next } ) => {
5760 const start = performance . now ( ) ;
58- console . debug ( `[trpc] start ${ path } (${ type } )` ) ;
61+
62+ // Sample input for debugging (only log safe fields, avoid PII)
63+ const inputSample =
64+ input && typeof input === "object"
65+ ? Object . keys ( input ) . reduce (
66+ ( acc , key ) => {
67+ // Log only safe fields, truncate long values
68+ if (
69+ key === "domain" ||
70+ key === "type" ||
71+ key === "types" ||
72+ key === "limit"
73+ ) {
74+ const value = ( input as Record < string , unknown > ) [ key ] ;
75+ acc [ key ] = String ( value ) . slice ( 0 , 100 ) ;
76+ }
77+ return acc ;
78+ } ,
79+ { } as Record < string , string > ,
80+ )
81+ : undefined ;
82+
83+ console . debug (
84+ JSON . stringify ( {
85+ level : "debug" ,
86+ message : "[trpc] start" ,
87+ path,
88+ type,
89+ input : inputSample ,
90+ timestamp : new Date ( ) . toISOString ( ) ,
91+ } ) ,
92+ ) ;
93+
5994 try {
6095 const result = await next ( ) ;
6196 const durationMs = Math . round ( performance . now ( ) - start ) ;
62- console . info ( `[trpc] ok ${ path } (${ type } ) ${ durationMs } ms` ) ;
97+
98+ console . info (
99+ JSON . stringify ( {
100+ level : "info" ,
101+ message : "[trpc] ok" ,
102+ path,
103+ type,
104+ durationMs,
105+ timestamp : new Date ( ) . toISOString ( ) ,
106+ } ) ,
107+ ) ;
108+
109+ // Track slow requests (>5s threshold) in PostHog
110+ if ( durationMs > 5000 ) {
111+ const { analytics } = await import ( "@/lib/analytics/server" ) ;
112+ analytics . track ( "trpc_slow_request" , {
113+ path,
114+ type,
115+ durationMs,
116+ } ) ;
117+ }
118+
63119 return result ;
64120 } catch ( err ) {
65121 const durationMs = Math . round ( performance . now ( ) - start ) ;
66122 const error = err instanceof Error ? err : new Error ( String ( err ) ) ;
123+
67124 console . error (
68125 JSON . stringify ( {
69126 level : "error" ,
70- message : ` [trpc] error ${ path } ( ${ type } )` ,
127+ message : " [trpc] error" ,
71128 path,
72129 type,
73130 durationMs,
131+ timestamp : new Date ( ) . toISOString ( ) ,
74132 error : {
75133 message : error . message ,
134+ name : error . name ,
76135 stack : error . stack ,
77136 cause : error . cause ,
78137 } ,
79138 } ) ,
80139 ) ;
140+
141+ // Track exceptions in PostHog for centralized monitoring
142+ const { analytics } = await import ( "@/lib/analytics/server" ) ;
143+ analytics . trackException ( error , {
144+ path,
145+ type,
146+ durationMs,
147+ source : "trpc" ,
148+ } ) ;
149+
81150 throw err ;
82151 }
83152} ) ;
@@ -97,7 +166,14 @@ const withDomainAccessUpdate = t.middleware(async ({ input, next }) => {
97166 ) {
98167 const registrable = toRegistrableDomain ( input . domain ) ;
99168 if ( registrable ) {
100- console . debug ( `[trpc] recording access for domain: ${ registrable } ` ) ;
169+ console . debug (
170+ JSON . stringify ( {
171+ level : "debug" ,
172+ message : "[trpc] recording access for domain" ,
173+ domain : registrable ,
174+ timestamp : new Date ( ) . toISOString ( ) ,
175+ } ) ,
176+ ) ;
101177 after ( ( ) => updateLastAccessed ( registrable ) ) ;
102178 }
103179 }
0 commit comments