Skip to content

Commit c49594b

Browse files
evgenyfedorov2evgenyfedorov2
andauthored
Add buffering readme (#6403)
Co-authored-by: evgenyfedorov2 <[email protected]>
1 parent 25d2dd4 commit c49594b

File tree

2 files changed

+124
-1
lines changed
  • src/Libraries
    • Microsoft.AspNetCore.Diagnostics.Middleware
    • Microsoft.Extensions.Telemetry

2 files changed

+124
-1
lines changed

src/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware/README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,60 @@ Or directly in the C# project file:
2020

2121
## Usage Example
2222

23+
### Log Buffering
24+
25+
Provides a buffering mechanism for logs, allowing you to store logs in temporary circular buffers in memory. If the buffer is full, the oldest logs will be dropped. If you want to emit the buffered logs, you can call `Flush()` on the buffer. That way, if you don't flush buffers, all buffered logs will eventually be dropped and that makes sense - if you don't flush buffers, chances are
26+
those logs are not important. At the same time, you can trigger a flush on the buffer when certain conditions are met, such as when an exception occurs.
27+
28+
#### Per-request Buffering
29+
30+
Provides HTTP request-scoped buffering for web applications:
31+
32+
```csharp
33+
// Simple configuration with log level
34+
builder.Logging.AddPerIncomingRequestBuffer(LogLevel.Warning); // Buffer Warning and lower level logs per request
35+
36+
// Configuration using options
37+
builder.Logging.AddPerIncomingRequestBuffer(options =>
38+
{
39+
options.Rules.Add(new LogBufferingFilterRule(logLevel: LogLevel.Information)); // Buffer Information and lower level logs
40+
options.Rules.Add(new LogBufferingFilterRule(categoryName: "Microsoft.*")); // Buffer logs from Microsoft namespaces
41+
});
42+
43+
// Configuration using IConfiguration
44+
builder.Logging.AddPerIncomingRequestBuffer(configuration.GetSection("Logging:RequestBuffering"));
45+
```
46+
47+
Then, to flush the buffers when a bad thing happens, call the `Flush()` method on the injected `PerRequestLogBuffer` instance:
48+
49+
```csharp
50+
public class MyService
51+
{
52+
private readonly PerRequestLogBuffer _perRequestLogBuffer;
53+
54+
public MyService(PerRequestLogBuffer perRequestLogBuffer)
55+
{
56+
_perRequestLogBuffer = perRequestLogBuffer;
57+
}
58+
59+
public void DoSomething()
60+
{
61+
try
62+
{
63+
// ...
64+
}
65+
catch (Exception ex)
66+
{
67+
// Flush all buffers
68+
_perRequestLogBuffer.Flush();
69+
}
70+
}
71+
}
72+
```
73+
74+
Per-request buffering is especially useful for capturing all logs related to a specific HTTP request and making decisions about them collectively based on request outcomes.
75+
Per-request buffering is tightly coupled with [Global Buffering](https://github.com/dotnet/extensions/blob/main/src/Libraries/Microsoft.Extensions.Telemetry/README.md#log-buffering). If a log entry is supposed to be buffered to a per-request buffer, but there is no active HTTP context, it will be buffered to the global buffer instead. If buffer flush is triggered, the per-request buffer will be flushed first, followed by the global buffer.
76+
2377
### Tracking HTTP Request Latency
2478

2579
These components enable tracking and reporting the latency of HTTP request processing.

src/Libraries/Microsoft.Extensions.Telemetry/README.md

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Or directly in the C# project file:
2020

2121
## Usage
2222

23-
### Logging Sampling
23+
### Log Sampling
2424

2525
The library provides two types of log sampling mechanisms: **Random Probabilistic Sampling** and **Trace-based Sampling**.
2626

@@ -46,6 +46,74 @@ builder.Logging.AddRandomProbabilisticSampler(configuration.GetSection("Logging:
4646

4747
The Random Probabilistic Sampler supports the `IOptionsMonitor<T>` pattern, allowing for dynamic configuration updates. This means you can change the sampling rules at runtime without needing to restart your application.
4848

49+
### Log Buffering
50+
51+
Provides a buffering mechanism for logs, allowing you to store logs in temporary circular buffers in memory. If the buffer is full, the oldest logs will be dropped. If you want to emit the buffered logs, you can call `Flush()` on the buffer. That way, if you don't flush buffers, all buffered logs will eventually be dropped and that makes sense - if you don't flush buffers, chances are
52+
those logs are not important. At the same time, you can trigger a flush on the buffer when certain conditions are met, such as when an exception occurs.
53+
54+
This library works with all logger providers, even if they do not implement the `Microsoft.Extensions.Logging.Abstractions.IBufferedLogger` interface. In that case, the library will
55+
be calling `ILogger.Log()` method directly on every single buffered log record when flushing the buffer.
56+
57+
#### Global Buffering
58+
59+
Provides application-wide log buffering with configurable rules:
60+
61+
```csharp
62+
// Simple configuration with log level
63+
builder.Logging.AddGlobalBuffer(LogLevel.Warning); // Buffer Warning and lower level logs
64+
65+
// Configuration using options
66+
builder.Logging.AddGlobalBuffer(options =>
67+
{
68+
options.Rules.Add(new LogBufferingFilterRule(logLevel: LogLevel.Information)); // Buffer Information and lower level logs
69+
options.Rules.Add(new LogBufferingFilterRule(categoryName: "Microsoft.*")); // Buffer logs from Microsoft namespaces
70+
});
71+
72+
// Configuration using IConfiguration
73+
builder.Logging.AddGlobalBuffer(configuration.GetSection("Logging:Buffering"));
74+
```
75+
76+
Then, to flush the global buffer when a bad thing happens, call the `Flush()` method on the injected GlobalLogBuffer instance:
77+
78+
```csharp
79+
public class MyService
80+
{
81+
private readonly GlobalLogBuffer _globalLogBuffer;
82+
83+
public MyService(GlobalLogBuffer globalLogBuffer)
84+
{
85+
_globalLogBuffer = globalLogBuffer;
86+
}
87+
88+
public void DoSomething()
89+
{
90+
try
91+
{
92+
// ...
93+
}
94+
catch (Exception ex)
95+
{
96+
// Flush the global buffer when an exception occurs
97+
_globalLogBuffer.Flush();
98+
}
99+
}
100+
}
101+
```
102+
103+
The Global Log Buffer supports the `IOptionsMonitor<T>` pattern, allowing for dynamic configuration updates. This means you can change the buffering rules at runtime without needing to restart your application.
104+
105+
##### Limitations
106+
107+
1. This library does not preserve the order of log records. However, original timestamps are preserved.
108+
1. The library does not support custom configuration per each logger provider. Same configuration is applied to all logger providers.
109+
1. When buffering and then flushing buffers, not all information of the original log record is preserved. This is due to serialing/deserialing limitation, but can be
110+
revisited in future. Namely, this library uses `Microsoft.Extensions.Logging.Abstractions.BufferedLogRecord` class when converting buffered log records to actual log records, but omits following properties:
111+
112+
- `Microsoft.Extensions.Logging.Abstractions.BufferedLogRecord.ActivitySpanId`
113+
- `Microsoft.Extensions.Logging.Abstractions.BufferedLogRecord.ActivityTraceId`
114+
- `Microsoft.Extensions.Logging.Abstractions.BufferedLogRecord.ManagedThreadId`
115+
- `Microsoft.Extensions.Logging.Abstractions.BufferedLogRecord.MessageTemplate`
116+
49117
#### Trace-Based Sampling
50118

51119
Matches logging sampling decisions with the underlying [Distributed Tracing sampling decisions](https://learn.microsoft.com/dotnet/core/diagnostics/distributed-tracing-concepts#sampling):
@@ -54,6 +122,7 @@ Matches logging sampling decisions with the underlying [Distributed Tracing samp
54122
// Add trace-based sampler
55123
builder.Logging.AddTraceBasedSampler();
56124
```
125+
57126
This comes in handy when you already use OpenTelemetry .NET Tracing and would like to see sampling decisions being consistent across both logs and their underlying [`Activity`](https://learn.microsoft.com/dotnet/core/diagnostics/distributed-tracing-concepts#sampling).
58127

59128
### Service Log Enrichment

0 commit comments

Comments
 (0)