@@ -23,27 +23,74 @@ public static void AddAPIs(WebApplication app)
2323 // Generate unique request ID for tracking
2424 var requestId = httpContext . TraceIdentifier ;
2525 telemetryHelper . SetActivityTag ( "requestId" , requestId ) ;
26+ var startTime = DateTimeOffset . UtcNow ;
27+
28+ // Trace: Request received
29+ logger . LogInformation ( "[{RequestId}] Chat request received. Endpoint: /chat, HasSessionId: {HasSessionId}, DocumentIds: {DocumentCount}" ,
30+ requestId ,
31+ ! string . IsNullOrEmpty ( request . ChatSessionId ) ,
32+ request . DocumentIds ? . Length ?? 0 ) ;
33+
34+ // Track request started
35+ telemetryHelper . TrackEvent ( "ChatRequestStarted" , new Dictionary < string , string >
36+ {
37+ { "requestId" , requestId } ,
38+ { "endpoint" , "/chat" } ,
39+ { "hasSessionId" , ( ! string . IsNullOrEmpty ( request . ChatSessionId ) ) . ToString ( ) } ,
40+ { "documentCount" , ( request . DocumentIds ? . Length ?? 0 ) . ToString ( ) }
41+ } ) ;
2642
2743 try
2844 {
29- if ( ! validator . Validate ( request ) . IsValid )
45+ // Trace: Starting validation
46+ logger . LogDebug ( "[{RequestId}] Validating chat request" , requestId ) ;
47+
48+ // Validate request
49+ var validationResult = validator . Validate ( request ) ;
50+ if ( ! validationResult . IsValid )
3051 {
52+ var errors = string . Join ( "; " , validationResult . Errors . Select ( e => e . ErrorMessage ) ) ;
53+
54+ // Trace: Validation failed
55+ logger . LogWarning ( "[{RequestId}] Chat request validation failed. Errors: {ValidationErrors}" ,
56+ requestId , errors ) ;
57+
3158 telemetryHelper . TrackEvent ( "ChatRequestValidationFailed" , new Dictionary < string , string >
3259 {
60+ { "requestId" , requestId } ,
3361 { "endpoint" , "/chat" } ,
34- { "requestId " , requestId }
62+ { "validationErrors " , errors }
3563 } ) ;
3664 return Results . BadRequest ( ) ;
3765 }
66+
67+ // Trace: Validation passed, processing request
68+ logger . LogInformation ( "[{RequestId}] Request validation passed. Calling chat host..." , requestId ) ;
3869
3970 var result = await chatHost . Chat ( request ) ;
71+ var duration = ( DateTimeOffset . UtcNow - startTime ) . TotalSeconds ;
4072
41- // Track successful chat request
73+ // Trace: Request completed successfully
74+ logger . LogInformation ( "[{RequestId}] Chat request completed successfully. Duration: {Duration}s, ChatSessionId: {ChatSessionId}, Documents: {DocumentCount}, AnswerLength: {AnswerLength}" ,
75+ requestId ,
76+ duration . ToString ( "F2" ) ,
77+ result . ChatSessionId ?? "unknown" ,
78+ result . DocumentIds ? . Length ?? 0 ,
79+ result . Answer ? . Length ?? 0 ) ;
80+
81+ // Track successful chat request with metrics
4282 telemetryHelper . TrackEvent ( "ChatRequestSuccess" , new Dictionary < string , string >
4383 {
4484 { "requestId" , requestId } ,
4585 { "chatSessionId" , result . ChatSessionId ?? "unknown" } ,
46- { "documentCount" , result . DocumentIds ? . Length . ToString ( ) ?? "0" }
86+ { "documentCount" , result . DocumentIds ? . Length . ToString ( ) ?? "0" } ,
87+ { "hasSuggestedQuestions" , ( result . SuggestingQuestions ? . Length > 0 ) . ToString ( ) } ,
88+ { "answerLength" , result . Answer ? . Length . ToString ( ) ?? "0" } ,
89+ { "duration" , duration . ToString ( "F2" ) }
90+ } , new Dictionary < string , double >
91+ {
92+ { "ResponseTimeSeconds" , duration } ,
93+ { "DocumentsReferenced" , result . DocumentIds ? . Length ?? 0 }
4794 } ) ;
4895
4996 // Set correlation ID for tracing
@@ -52,11 +99,100 @@ public static void AddAPIs(WebApplication app)
5299 telemetryHelper . SetActivityTag ( "chatSessionId" , result . ChatSessionId ) ;
53100 }
54101
102+ // Track performance metrics
103+ if ( duration > 60 )
104+ {
105+ // Trace: Slow response warning
106+ logger . LogWarning ( "[{RequestId}] SLOW RESPONSE DETECTED: Chat request took {Duration}s (threshold: 60s). DocumentCount: {DocumentCount}" ,
107+ requestId ,
108+ duration . ToString ( "F2" ) ,
109+ result . DocumentIds ? . Length ?? 0 ) ;
110+
111+ telemetryHelper . TrackEvent ( "ChatRequestSlowResponse" , new Dictionary < string , string >
112+ {
113+ { "requestId" , requestId } ,
114+ { "duration" , duration . ToString ( "F2" ) } ,
115+ { "documentCount" , result . DocumentIds ? . Length . ToString ( ) ?? "0" }
116+ } ) ;
117+ }
118+ else if ( duration > 30 )
119+ {
120+ // Trace: Performance warning for moderately slow requests
121+ logger . LogInformation ( "[{RequestId}] Moderate response time: {Duration}s" ,
122+ requestId , duration . ToString ( "F2" ) ) ;
123+ }
124+
55125 return Results . Ok < ChatResponse > ( result ) ;
56126 }
127+ catch ( TimeoutException ex )
128+ {
129+ var elapsedTime = ( DateTimeOffset . UtcNow - startTime ) . TotalSeconds ;
130+
131+ // Trace: Timeout with details
132+ logger . LogError ( ex , "[{RequestId}] TIMEOUT: Chat request timed out after {ElapsedTime}s. Endpoint: /chat, Message: {ErrorMessage}" ,
133+ requestId ,
134+ elapsedTime . ToString ( "F2" ) ,
135+ ex . Message ) ;
136+
137+ telemetryHelper . TrackEvent ( "ChatRequestTimeout" , new Dictionary < string , string >
138+ {
139+ { "requestId" , requestId } ,
140+ { "endpoint" , "/chat" } ,
141+ { "elapsedTime" , elapsedTime . ToString ( "F2" ) } ,
142+ { "errorMessage" , ex . Message }
143+ } ) ;
144+ telemetryHelper . TrackException ( ex , new Dictionary < string , string >
145+ {
146+ { "requestId" , requestId } ,
147+ { "endpoint" , "/chat" } ,
148+ { "errorType" , "TimeoutException" }
149+ } ) ;
150+ throw ;
151+ }
152+ catch ( ArgumentException ex )
153+ {
154+ // Trace: Invalid argument with parameter details
155+ logger . LogError ( ex , "[{RequestId}] INVALID ARGUMENT: Chat request failed due to invalid parameter. Endpoint: /chat, Parameter: {ParamName}, Message: {ErrorMessage}" ,
156+ requestId ,
157+ ex . ParamName ?? "unknown" ,
158+ ex . Message ) ;
159+
160+ telemetryHelper . TrackEvent ( "ChatRequestInvalidArgument" , new Dictionary < string , string >
161+ {
162+ { "requestId" , requestId } ,
163+ { "endpoint" , "/chat" } ,
164+ { "paramName" , ex . ParamName ?? "unknown" } ,
165+ { "errorMessage" , ex . Message }
166+ } ) ;
167+ telemetryHelper . TrackException ( ex , new Dictionary < string , string >
168+ {
169+ { "requestId" , requestId } ,
170+ { "endpoint" , "/chat" } ,
171+ { "errorType" , "ArgumentException" }
172+ } ) ;
173+ throw ;
174+ }
57175 catch ( Exception ex )
58176 {
59- logger . LogError ( ex , "Error processing chat request. RequestId: {RequestId}" , requestId ) ;
177+ var elapsedTime = ( DateTimeOffset . UtcNow - startTime ) . TotalSeconds ;
178+
179+ // Trace: General error with full context
180+ logger . LogError ( ex , "[{RequestId}] CHAT REQUEST FAILED: Unexpected error after {ElapsedTime}s. Endpoint: /chat, ErrorType: {ErrorType}, Message: {ErrorMessage}, StackTrace: {StackTrace}" ,
181+ requestId ,
182+ elapsedTime . ToString ( "F2" ) ,
183+ ex . GetType ( ) . Name ,
184+ ex . Message ,
185+ ex . StackTrace ? . Substring ( 0 , Math . Min ( 500 , ex . StackTrace ? . Length ?? 0 ) ) ?? "N/A" ) ;
186+
187+ telemetryHelper . TrackEvent ( "ChatRequestFailed" , new Dictionary < string , string >
188+ {
189+ { "requestId" , requestId } ,
190+ { "endpoint" , "/chat" } ,
191+ { "errorType" , ex . GetType ( ) . Name } ,
192+ { "errorMessage" , ex . Message } ,
193+ { "elapsedTime" , elapsedTime . ToString ( "F2" ) } ,
194+ { "innerException" , ex . InnerException ? . Message ?? "none" }
195+ } ) ;
60196 telemetryHelper . TrackException ( ex , new Dictionary < string , string >
61197 {
62198 { "requestId" , requestId } ,
@@ -82,23 +218,61 @@ public static void AddAPIs(WebApplication app)
82218 // Generate unique request ID for tracking
83219 var requestId = ctx . TraceIdentifier ;
84220 telemetryHelper . SetActivityTag ( "requestId" , requestId ) ;
221+ var startTime = DateTimeOffset . UtcNow ;
222+
223+ // Trace: Async request received
224+ logger . LogInformation ( "[{RequestId}] Chat ASYNC request received. Endpoint: /chatAsync, HasSessionId: {HasSessionId}, DocumentIds: {DocumentCount}" ,
225+ requestId ,
226+ ! string . IsNullOrEmpty ( request . ChatSessionId ) ,
227+ request . DocumentIds ? . Length ?? 0 ) ;
228+
229+ // Track async request started
230+ telemetryHelper . TrackEvent ( "ChatAsyncRequestStarted" , new Dictionary < string , string >
231+ {
232+ { "requestId" , requestId } ,
233+ { "endpoint" , "/chatAsync" } ,
234+ { "hasSessionId" , ( ! string . IsNullOrEmpty ( request . ChatSessionId ) ) . ToString ( ) } ,
235+ { "documentCount" , ( request . DocumentIds ? . Length ?? 0 ) . ToString ( ) }
236+ } ) ;
85237
86238 try
87239 {
88- if ( ! validator . Validate ( request ) . IsValid )
240+ // Trace: Starting validation
241+ logger . LogDebug ( "[{RequestId}] Validating chat async request" , requestId ) ;
242+
243+ var validationResult = validator . Validate ( request ) ;
244+ if ( ! validationResult . IsValid )
89245 {
246+ var errors = string . Join ( "; " , validationResult . Errors . Select ( e => e . ErrorMessage ) ) ;
247+
248+ // Trace: Validation failed
249+ logger . LogWarning ( "[{RequestId}] Chat async request validation failed. Errors: {ValidationErrors}" ,
250+ requestId , errors ) ;
251+
90252 telemetryHelper . TrackEvent ( "ChatAsyncRequestValidationFailed" , new Dictionary < string , string >
91253 {
254+ { "requestId" , requestId } ,
92255 { "endpoint" , "/chatAsync" } ,
93- { "requestId " , requestId }
256+ { "validationErrors " , errors }
94257 } ) ;
95258 return Results . BadRequest ( ) ;
96259 }
97260
261+ // Trace: Validation passed, preparing streaming response
262+ logger . LogInformation ( "[{RequestId}] Request validation passed. Preparing streaming response..." , requestId ) ;
263+
98264 ctx . Response . ContentType = "text/plain" ;
99265
100266 //Make a response as a stream
101267 var result = chatHost . ChatAsync ( request ) . Result ;
268+ var duration = ( DateTimeOffset . UtcNow - startTime ) . TotalSeconds ;
269+
270+ // Trace: Response metadata ready
271+ logger . LogInformation ( "[{RequestId}] Chat async response ready. Duration: {Duration}s, ChatSessionId: {ChatSessionId}, Documents: {DocumentCount}" ,
272+ requestId ,
273+ duration . ToString ( "F2" ) ,
274+ result . ChatSessionId ?? "unknown" ,
275+ result . DocumentIds ? . Length ?? 0 ) ;
102276
103277 //Create a dynamic object to store the response
104278 var response = new
@@ -111,12 +285,19 @@ public static void AddAPIs(WebApplication app)
111285 //Add the response to the header
112286 ctx . Response . Headers . Add ( "RESPONSE" , JsonSerializer . Serialize ( response ) ) ;
113287
114- // Track successful chat async request
288+ // Track successful chat async request with metrics
115289 telemetryHelper . TrackEvent ( "ChatAsyncRequestSuccess" , new Dictionary < string , string >
116290 {
117291 { "requestId" , requestId } ,
118292 { "chatSessionId" , result . ChatSessionId ?? "unknown" } ,
119- { "documentCount" , result . DocumentIds ? . Length . ToString ( ) ?? "0" }
293+ { "documentCount" , result . DocumentIds ? . Length . ToString ( ) ?? "0" } ,
294+ { "hasSuggestedQuestions" , ( result . SuggestingQuestions ? . Length > 0 ) . ToString ( ) } ,
295+ { "streamingResponse" , "true" } ,
296+ { "duration" , duration . ToString ( "F2" ) }
297+ } , new Dictionary < string , double >
298+ {
299+ { "ResponseTimeSeconds" , duration } ,
300+ { "DocumentsReferenced" , result . DocumentIds ? . Length ?? 0 }
120301 } ) ;
121302
122303 // Set correlation ID for tracing
@@ -125,17 +306,70 @@ public static void AddAPIs(WebApplication app)
125306 telemetryHelper . SetActivityTag ( "chatSessionId" , result . ChatSessionId ) ;
126307 }
127308
309+ // Trace: Beginning streaming
310+ logger . LogDebug ( "[{RequestId}] Starting to stream response words..." , requestId ) ;
311+
128312 // Stream the response
313+ var wordCount = 0 ;
129314 await foreach ( var word in result . AnswerWords )
130315 {
131316 await ctx . Response . WriteAsync ( word ) ;
132317 await ctx . Response . WriteAsync ( " " ) ;
318+ wordCount ++ ;
133319 }
320+
321+ // Trace: Streaming completed
322+ logger . LogInformation ( "[{RequestId}] Streaming completed. Total words streamed: {WordCount}" ,
323+ requestId , wordCount ) ;
324+
134325 return Results . Ok ( ) ;
135326 }
327+ catch ( TimeoutException ex )
328+ {
329+ var elapsedTime = ( DateTimeOffset . UtcNow - startTime ) . TotalSeconds ;
330+
331+ // Trace: Timeout with details
332+ logger . LogError ( ex , "[{RequestId}] TIMEOUT: Chat async request timed out after {ElapsedTime}s. Endpoint: /chatAsync, Message: {ErrorMessage}" ,
333+ requestId ,
334+ elapsedTime . ToString ( "F2" ) ,
335+ ex . Message ) ;
336+
337+ telemetryHelper . TrackEvent ( "ChatAsyncRequestTimeout" , new Dictionary < string , string >
338+ {
339+ { "requestId" , requestId } ,
340+ { "endpoint" , "/chatAsync" } ,
341+ { "elapsedTime" , elapsedTime . ToString ( "F2" ) } ,
342+ { "errorMessage" , ex . Message }
343+ } ) ;
344+ telemetryHelper . TrackException ( ex , new Dictionary < string , string >
345+ {
346+ { "requestId" , requestId } ,
347+ { "endpoint" , "/chatAsync" } ,
348+ { "errorType" , "TimeoutException" }
349+ } ) ;
350+ throw ;
351+ }
136352 catch ( Exception ex )
137353 {
138- logger . LogError ( ex , "Error processing chat async request. RequestId: {RequestId}" , requestId ) ;
354+ var elapsedTime = ( DateTimeOffset . UtcNow - startTime ) . TotalSeconds ;
355+
356+ // Trace: General error with full context
357+ logger . LogError ( ex , "[{RequestId}] CHAT ASYNC REQUEST FAILED: Unexpected error after {ElapsedTime}s. Endpoint: /chatAsync, ErrorType: {ErrorType}, Message: {ErrorMessage}, StackTrace: {StackTrace}" ,
358+ requestId ,
359+ elapsedTime . ToString ( "F2" ) ,
360+ ex . GetType ( ) . Name ,
361+ ex . Message ,
362+ ex . StackTrace ? . Substring ( 0 , Math . Min ( 500 , ex . StackTrace ? . Length ?? 0 ) ) ?? "N/A" ) ;
363+
364+ telemetryHelper . TrackEvent ( "ChatAsyncRequestFailed" , new Dictionary < string , string >
365+ {
366+ { "requestId" , requestId } ,
367+ { "endpoint" , "/chatAsync" } ,
368+ { "errorType" , ex . GetType ( ) . Name } ,
369+ { "errorMessage" , ex . Message } ,
370+ { "elapsedTime" , elapsedTime . ToString ( "F2" ) } ,
371+ { "innerException" , ex . InnerException ? . Message ?? "none" }
372+ } ) ;
139373 telemetryHelper . TrackException ( ex , new Dictionary < string , string >
140374 {
141375 { "requestId" , requestId } ,
0 commit comments