Skip to content

Commit 0beed5e

Browse files
authored
Merge pull request #96 from PandaTechAM/development
Log HTTP out and SignalR hub invocation failures that were previously…
2 parents f446f9f + fca5250 commit 0beed5e

File tree

3 files changed

+81
-10
lines changed

3 files changed

+81
-10
lines changed

src/SharedKernel/Logging/Middleware/OutboundLoggingHandler.cs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,44 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
1212

1313
var (reqHeaders, reqBody) = await CaptureRequestAsync(request, cancellationToken);
1414

15-
var response = await base.SendAsync(request, cancellationToken);
15+
HttpResponseMessage response;
16+
try
17+
{
18+
response = await base.SendAsync(request, cancellationToken);
19+
}
20+
catch (Exception ex)
21+
{
22+
var elapsedMs = Stopwatch.GetElapsedTime(timestamp).TotalMilliseconds;
23+
24+
var errorBody = new Dictionary<string, object?>
25+
{
26+
["exceptionType"] = ex.GetType().Name,
27+
["message"] = ex.Message
28+
};
29+
30+
LogHttpOutFailure(
31+
ex,
32+
request.Method.Method,
33+
request.RequestUri?.GetLeftPart(UriPartial.Path) ?? "",
34+
elapsedMs,
35+
"HttpOut",
36+
string.IsNullOrEmpty(request.RequestUri?.Query) ? null : request.RequestUri!.Query,
37+
LogFormatting.ToJsonString(reqHeaders),
38+
LogFormatting.ToJsonString(reqBody),
39+
LogFormatting.ToJsonString(errorBody));
40+
41+
throw;
42+
}
1643

17-
var elapsedMs = Stopwatch.GetElapsedTime(timestamp)
18-
.TotalMilliseconds;
44+
var elapsed = Stopwatch.GetElapsedTime(timestamp).TotalMilliseconds;
1945

2046
var (resHeaders, resBody) = await CaptureResponseAsync(response, cancellationToken);
2147

2248
LogHttpOut(
2349
request.Method.Method,
2450
request.RequestUri?.GetLeftPart(UriPartial.Path) ?? "",
2551
(int)response.StatusCode,
26-
elapsedMs,
52+
elapsed,
2753
"HttpOut",
2854
string.IsNullOrEmpty(request.RequestUri?.Query) ? null : request.RequestUri!.Query,
2955
LogFormatting.ToJsonString(reqHeaders),
@@ -150,4 +176,17 @@ private partial void LogHttpOut(string method,
150176
string requestBody,
151177
string responseHeaders,
152178
string responseBody);
179+
180+
[LoggerMessage(Level = LogLevel.Warning,
181+
Message = "[HTTP OUT] {Method} {HostPath} -> FAILED in {ElapsedMs}ms | " +
182+
"{Kind} query={Query} requestHeader={RequestHeaders} requestBody={RequestBody} error={ErrorBody}")]
183+
private partial void LogHttpOutFailure(Exception ex,
184+
string method,
185+
string hostPath,
186+
double elapsedMs,
187+
string kind,
188+
string? query,
189+
string requestHeaders,
190+
string requestBody,
191+
string errorBody);
153192
}

src/SharedKernel/Logging/Middleware/SignalRLoggingHubFilter.cs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,30 @@ internal sealed partial class SignalRLoggingHubFilter(ILogger<SignalRLoggingHubF
2121
var rawArgsJson = JsonSerializer.Serialize(invocationContext.HubMethodArguments);
2222
var redactedArgs = RedactionHelper.RedactBody("application/json", rawArgsJson);
2323

24-
var result = await next(invocationContext);
24+
object? result;
25+
try
26+
{
27+
result = await next(invocationContext);
28+
}
29+
catch (Exception ex)
30+
{
31+
var elapsedMs = Stopwatch.GetElapsedTime(timestamp).TotalMilliseconds;
2532

26-
var elapsedMs = Stopwatch.GetElapsedTime(timestamp).TotalMilliseconds;
33+
var errorBody = new Dictionary<string, object?>
34+
{
35+
["exceptionType"] = ex.GetType().Name,
36+
["message"] = ex.Message
37+
};
2738

28-
LogInvoke(hubName, methodName, elapsedMs, "SignalR", connectionId, userId, LogFormatting.ToJsonString(redactedArgs));
39+
LogInvokeFailure(ex, hubName, methodName, elapsedMs, "SignalR", connectionId, userId,
40+
LogFormatting.ToJsonString(redactedArgs), LogFormatting.ToJsonString(errorBody));
41+
42+
throw;
43+
}
44+
45+
var elapsed = Stopwatch.GetElapsedTime(timestamp).TotalMilliseconds;
46+
47+
LogInvoke(hubName, methodName, elapsed, "SignalR", connectionId, userId, LogFormatting.ToJsonString(redactedArgs));
2948

3049
return result;
3150
}
@@ -64,6 +83,19 @@ private partial void LogInvoke(
6483
string? userId,
6584
string args);
6685

86+
[LoggerMessage(Level = LogLevel.Warning,
87+
Message = "[SignalR] {Hub}.{HubMethod} FAILED in {ElapsedMs}ms | {Kind} connId={ConnId} userId={UserId} args={Args} error={ErrorBody}")]
88+
private partial void LogInvokeFailure(
89+
Exception ex,
90+
string hub,
91+
string hubMethod,
92+
double elapsedMs,
93+
string kind,
94+
string? connId,
95+
string? userId,
96+
string args,
97+
string errorBody);
98+
6799
[LoggerMessage(Level = LogLevel.Information,
68100
Message = "[Connected] SignalR {Hub} | {Kind} connId={ConnId} userId={UserId}")]
69101
private partial void LogConnected(

src/SharedKernel/SharedKernel.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
<PackageIcon>pandatech.png</PackageIcon>
2222
<PackageReadmeFile>README.md</PackageReadmeFile>
2323

24-
<Version>2.2.3</Version>
25-
<PackageReleaseNotes>Cors now will start to expose Content-Disposition header</PackageReleaseNotes>
24+
<Version>2.2.4</Version>
25+
<PackageReleaseNotes>Log HTTP out and SignalR hub invocation failures (timeout, connection errors, exceptions) that were previously silently lost</PackageReleaseNotes>
2626

2727
<GenerateDocumentationFile>true</GenerateDocumentationFile>
2828
<IncludeSymbols>true</IncludeSymbols>
@@ -71,7 +71,7 @@
7171
<PackageReference Include="Pandatech.FluentMinimalApiMapper" Version="4.0.0"/>
7272
<PackageReference Include="Pandatech.PandaVaultClient" Version="6.0.0"/>
7373
<PackageReference Include="Pandatech.ResponseCrafter" Version="7.0.0"/>
74-
<PackageReference Include="Scalar.AspNetCore" Version="2.13.1" />
74+
<PackageReference Include="Scalar.AspNetCore" Version="2.13.3" />
7575
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0"/>
7676
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0"/>
7777
<PackageReference Include="Serilog.Sinks.Grafana.Loki" Version="8.3.2"/>

0 commit comments

Comments
 (0)