Skip to content

Commit f3aa107

Browse files
hjgracaCopilot
andauthored
feat(logging): add Enabled property to LogBuffering configuration (#1125)
Signed-off-by: Henrique Graca <999396+hjgraca@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent b977315 commit f3aa107

17 files changed

Lines changed: 406 additions & 162 deletions

File tree

docs/core/logging.md

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,26 +1075,24 @@ inheriting the ``ILogFormatter`` class and implementing the ``object FormatLogEn
10751075

10761076
### Buffering logs
10771077

1078-
Log buffering enables you to buffer logs for a specific request or invocation. Enable log buffering by passing `LogBufferingOptions` when configuring a Logger instance. You can buffer logs at the `Warning`, `Information`, `Debug` or `Trace` level, and flush them automatically on error or manually as needed.
1078+
Log buffering enables you to buffer logs for a specific request or invocation. Enable log buffering by setting `LogBuffering.Enabled = true` when configuring a Logger instance. You can buffer logs at the `Warning`, `Information`, `Debug` or `Trace` level, and flush them automatically on error or manually as needed.
10791079

10801080
!!! tip "This is useful when you want to reduce the number of log messages emitted while still having detailed logs when needed, such as when troubleshooting issues."
10811081

10821082
=== "LogBufferingOptions"
10831083

1084-
```csharp hl_lines="5-14"
1084+
```csharp hl_lines="5-12"
10851085
public class Function
10861086
{
10871087
public Function()
10881088
{
10891089
Logger.Configure(logger =>
10901090
{
10911091
logger.Service = "MyServiceName";
1092-
logger.LogBuffering = new LogBufferingOptions
1093-
{
1094-
BufferAtLogLevel = LogLevel.Debug,
1095-
MaxBytes = 20480, // Default is 20KB (20480 bytes)
1096-
FlushOnErrorLog = true // default true
1097-
};
1092+
logger.LogBuffering.Enabled = true;
1093+
logger.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
1094+
logger.LogBuffering.MaxBytes = 20480; // Default is 20KB (20480 bytes)
1095+
logger.LogBuffering.FlushOnErrorLog = true; // default true
10981096
});
10991097

11001098
Logger.LogDebug('This is a debug message'); // This is NOT buffered
@@ -1117,28 +1115,27 @@ Log buffering enables you to buffer logs for a specific request or invocation. E
11171115

11181116
#### Configuring the buffer
11191117

1120-
When configuring the buffer, you can set the following options to fine-tune how logs are captured, stored, and emitted. You can configure the following options in the `logBufferOptions` constructor parameter:
1118+
When configuring the buffer, you can set the following options to fine-tune how logs are captured, stored, and emitted. You can configure the following options in the `LogBuffering` property:
11211119

11221120
| Parameter | Description | Configuration | Default |
11231121
|---------------------|------------------------------------------------- |--------------------------------------------|---------|
1122+
| `Enabled` | Enable or disable log buffering | `True`, `False` | `False` |
11241123
| `MaxBytes` | Maximum size of the log buffer in bytes | `number` | `20480` |
11251124
| `BufferAtLogLevel` | Minimum log level to buffer | `Trace`, `Debug`, `Information`, `Warning` | `Debug` |
11261125
| `FlushOnErrorLog` | Automatically flush buffer when logging an error | `True`, `False` | `True` |
11271126

11281127
=== "BufferAtLogLevel"
11291128

1130-
```csharp hl_lines="10"
1129+
```csharp hl_lines="10 11"
11311130
public class Function
11321131
{
11331132
public Function()
11341133
{
11351134
Logger.Configure(logger =>
11361135
{
11371136
logger.Service = "MyServiceName";
1138-
logger.LogBuffering = new LogBufferingOptions
1139-
{
1140-
BufferAtLogLevel = LogLevel.Warning
1141-
};
1137+
logger.LogBuffering.Enabled = true;
1138+
logger.LogBuffering.BufferAtLogLevel = LogLevel.Warning;
11421139
});
11431140
}
11441141

@@ -1161,18 +1158,16 @@ When configuring the buffer, you can set the following options to fine-tune how
11611158

11621159
=== "FlushOnErrorLog"
11631160

1164-
```csharp hl_lines="10"
1161+
```csharp hl_lines="10 11"
11651162
public class Function
11661163
{
11671164
public Function()
11681165
{
11691166
Logger.Configure(logger =>
11701167
{
11711168
logger.Service = "MyServiceName";
1172-
logger.LogBuffering = new LogBufferingOptions
1173-
{
1174-
FlushOnErrorLog = false
1175-
};
1169+
logger.LogBuffering.Enabled = true;
1170+
logger.LogBuffering.FlushOnErrorLog = false;
11761171
});
11771172
}
11781173

@@ -1214,18 +1209,16 @@ When using the `Logger` decorator, you can configure the logger to automatically
12141209

12151210
=== "FlushBufferOnUncaughtError"
12161211

1217-
```csharp hl_lines="15"
1212+
```csharp hl_lines="14"
12181213
public class Function
12191214
{
12201215
public Function()
12211216
{
12221217
Logger.Configure(logger =>
12231218
{
12241219
logger.Service = "MyServiceName";
1225-
logger.LogBuffering = new LogBufferingOptions
1226-
{
1227-
BufferAtLogLevel = LogLevel.Debug
1228-
};
1220+
logger.LogBuffering.Enabled = true;
1221+
logger.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
12291222
});
12301223
}
12311224

@@ -1328,7 +1321,7 @@ sequenceDiagram
13281321
No, we never buffer logs during cold starts. This is because we want to ensure that logs emitted during this phase are always available for debugging and monitoring purposes. The buffer is only used during the execution of the Lambda function.
13291322

13301323
3. **How can I prevent log buffering from consuming excessive memory?**
1331-
You can limit the size of the buffer by setting the `MaxBytes` option in the `LogBufferingOptions` constructor parameter. This will ensure that the buffer does not grow indefinitely and consume excessive memory.
1324+
You can limit the size of the buffer by setting the `MaxBytes` option in the `LogBuffering` property. This will ensure that the buffer does not grow indefinitely and consume excessive memory.
13321325

13331326
4. **What happens if the log buffer reaches its maximum size?**
13341327
Older logs are removed from the buffer to make room for new logs. This means that if the buffer is full, you may lose some logs if they are not flushed before the buffer reaches its maximum size. When this happens, we emit a warning when flushing the buffer to indicate that some logs have been dropped.

docs/getting-started/logger/aspnet.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -392,11 +392,9 @@ var logger = LoggerFactory.Create(builder =>
392392
builder.AddPowertoolsLogger(config =>
393393
{
394394
config.Service = "powertools-aspnet-demo";
395-
config.LogBuffering = new LogBufferingOptions
396-
{
397-
BufferAtLogLevel = LogLevel.Debug,
398-
FlushOnErrorLog = true
399-
};
395+
config.LogBuffering.Enabled = true;
396+
config.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
397+
config.LogBuffering.FlushOnErrorLog = true;
400398
});
401399
}).CreatePowertoolsLogger();
402400

libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspect.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ private void InitializeLogger(LoggingAttribute trigger)
7777

7878
// Set operational flags based on current configuration
7979
_isDebug = _currentConfig.MinimumLogLevel <= LogLevel.Debug;
80-
_bufferingEnabled = _currentConfig.LogBuffering != null;
80+
_bufferingEnabled = _currentConfig.LogBuffering?.Enabled == true;
8181
}
8282

8383
/// <summary>

libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,10 @@ public bool IsEnabled(LogLevel logLevel)
9393
private bool IsEnabledForConfig(LogLevel logLevel, PowertoolsLoggerConfiguration config)
9494
{
9595
//if Buffering is enabled and the log level is below the buffer threshold, skip logging only if bellow error
96-
if (logLevel <= config.LogBuffering?.BufferAtLogLevel
97-
&& config.LogBuffering?.BufferAtLogLevel != LogLevel.Error
98-
&& config.LogBuffering?.BufferAtLogLevel != LogLevel.Critical)
96+
if (config.LogBuffering?.Enabled == true
97+
&& logLevel <= config.LogBuffering.BufferAtLogLevel
98+
&& config.LogBuffering.BufferAtLogLevel != LogLevel.Error
99+
&& config.LogBuffering.BufferAtLogLevel != LogLevel.Critical)
99100
{
100101
return false;
101102
}

libraries/src/AWS.Lambda.Powertools.Logging/LogBufferingOptions.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,23 @@ namespace AWS.Lambda.Powertools.Logging;
2222
/// </summary>
2323
public class LogBufferingOptions
2424
{
25+
/// <summary>
26+
/// Gets or sets whether log buffering is enabled.
27+
/// <para></para>
28+
/// Default is false. Set to true to enable log buffering.
29+
/// </summary>
30+
/// <example>
31+
/// <code>
32+
/// // Enable buffering with default options
33+
/// options.LogBuffering.Enabled = true;
34+
///
35+
/// // Enable buffering with custom options
36+
/// options.LogBuffering.Enabled = true;
37+
/// options.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
38+
/// </code>
39+
/// </example>
40+
public bool Enabled { get; set; }
41+
2542
/// <summary>
2643
/// Gets or sets the maximum size of the buffer in bytes
2744
/// <para></para>

libraries/src/AWS.Lambda.Powertools.Logging/PowertoolsLoggerBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public PowertoolsLoggerBuilder WithFormatter(ILogFormatter formatter)
9999
/// <returns>The builder instance for method chaining.</returns>
100100
public PowertoolsLoggerBuilder WithLogBuffering(Action<LogBufferingOptions> configure)
101101
{
102-
_configuration.LogBuffering = new LogBufferingOptions();
102+
_configuration.LogBuffering.Enabled = true;
103103
configure?.Invoke(_configuration.LogBuffering);
104104
return this;
105105
}

libraries/src/AWS.Lambda.Powertools.Logging/PowertoolsLoggerConfiguration.cs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,9 @@ namespace AWS.Lambda.Powertools.Logging;
2727
/// <code>
2828
/// builder.Logging.AddPowertoolsLogger(options =>
2929
/// {
30-
/// options.LogBuffering = new LogBufferingOptions
31-
/// {
32-
/// Enabled = true,
33-
/// BufferAtLogLevel = LogLevel.Debug,
34-
/// FlushOnErrorLog = true
35-
/// };
30+
/// options.LogBuffering.Enabled = true;
31+
/// options.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
32+
/// options.LogBuffering.FlushOnErrorLog = true;
3633
/// });
3734
/// </code>
3835
///
@@ -229,32 +226,35 @@ public JsonSerializerOptions JsonOptions
229226
}
230227
}
231228

229+
private LogBufferingOptions _logBuffering = new LogBufferingOptions();
230+
232231
/// <summary>
233-
/// Enables or disables log buffering. Logs below the specified level will be buffered
234-
/// until the buffer is flushed or an error occurs.
235-
/// Buffer logs at the WARNING, INFO, and DEBUG levels and reduce CloudWatch costs by decreasing the number of emitted log messages
232+
/// Gets or sets the configuration options for log buffering.
233+
/// When enabled, logs below the specified level are buffered until explicitly flushed or an error occurs.
234+
/// This can reduce CloudWatch costs by decreasing the number of emitted log messages.
235+
/// <para>Log buffering is disabled by default. Set <see cref="LogBufferingOptions.Enabled"/> to true to enable it.</para>
236+
/// <para>Setting this property to null will reset it to a default <see cref="LogBufferingOptions"/> instance with buffering disabled.</para>
236237
/// </summary>
237238
/// <example>
238239
/// <code>
239-
/// // Enable buffering for debug logs
240-
/// options.LogBuffering = new LogBufferingOptions
241-
/// {
242-
/// Enabled = true,
243-
/// BufferAtLogLevel = LogLevel.Debug,
244-
/// FlushOnErrorLog = true
245-
/// };
240+
/// // Enable buffering with default options
241+
/// options.LogBuffering.Enabled = true;
242+
///
243+
/// // Enable buffering for debug logs with custom settings
244+
/// options.LogBuffering.Enabled = true;
245+
/// options.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
246+
/// options.LogBuffering.FlushOnErrorLog = true;
246247
///
247248
/// // Buffer all logs below Error level
248-
/// options.LogBuffering = new LogBufferingOptions
249-
/// {
250-
/// Enabled = true,
251-
/// BufferAtLogLevel = LogLevel.Warning,
252-
/// FlushOnErrorLog = true
253-
/// };
249+
/// options.LogBuffering.Enabled = true;
250+
/// options.LogBuffering.BufferAtLogLevel = LogLevel.Warning;
254251
/// </code>
255252
/// </example>
256-
public LogBufferingOptions LogBuffering { get; set; }
257-
253+
public LogBufferingOptions LogBuffering
254+
{
255+
get => _logBuffering;
256+
set => _logBuffering = value ?? new LogBufferingOptions();
257+
}
258258
/// <summary>
259259
/// Serializer instance for this configuration
260260
/// </summary>

libraries/src/AWS.Lambda.Powertools.Logging/PowertoolsLoggingBuilderExtensions.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,8 @@ public static ILoggingBuilder AddPowertoolsLogger(
157157
/// <code>
158158
/// builder.Logging.AddPowertoolsLogger(options =>
159159
/// {
160-
/// options.LogBuffering = new LogBufferingOptions
161-
/// {
162-
/// Enabled = true,
163-
/// BufferAtLogLevel = LogLevel.Debug
164-
/// };
160+
/// options.LogBuffering.Enabled = true;
161+
/// options.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
165162
/// });
166163
/// </code>
167164
/// </example>
@@ -188,7 +185,7 @@ public static ILoggingBuilder AddPowertoolsLogger(
188185
UpdateConfiguration(options);
189186

190187
// If buffering is enabled, register buffer providers
191-
if (options.LogBuffering != null)
188+
if (options.LogBuffering?.Enabled == true)
192189
{
193190
// Add a filter for the buffer provider
194191
builder.AddFilter<BufferingLoggerProvider>(

libraries/tests/AWS.Lambda.Powertools.ConcurrencyTests/Logging/BufferIsolationTests.cs

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,9 @@ public void BufferSeparation_ConcurrentInvocations_ShouldMaintainSeparateBuffers
5555
Logger.Configure(config =>
5656
{
5757
config.MinimumLogLevel = LogLevel.Debug;
58-
config.LogBuffering = new LogBufferingOptions
59-
{
60-
BufferAtLogLevel = LogLevel.Debug,
61-
FlushOnErrorLog = false
62-
};
58+
config.LogBuffering.Enabled = true;
59+
config.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
60+
config.LogBuffering.FlushOnErrorLog = false;
6361
});
6462

6563
for (int e = 0; e < entriesPerInvocation; e++)
@@ -128,11 +126,9 @@ public void BufferLifecycleIsolation_OverlappingInvocations_ShouldPreserveActive
128126
Logger.Configure(config =>
129127
{
130128
config.MinimumLogLevel = LogLevel.Debug;
131-
config.LogBuffering = new LogBufferingOptions
132-
{
133-
BufferAtLogLevel = LogLevel.Debug,
134-
FlushOnErrorLog = false
135-
};
129+
config.LogBuffering.Enabled = true;
130+
config.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
131+
config.LogBuffering.FlushOnErrorLog = false;
136132
});
137133

138134
for (int e = 0; e < entriesPerInvocation; e++)
@@ -161,11 +157,9 @@ public void BufferLifecycleIsolation_OverlappingInvocations_ShouldPreserveActive
161157
Logger.Configure(config =>
162158
{
163159
config.MinimumLogLevel = LogLevel.Debug;
164-
config.LogBuffering = new LogBufferingOptions
165-
{
166-
BufferAtLogLevel = LogLevel.Debug,
167-
FlushOnErrorLog = false
168-
};
160+
config.LogBuffering.Enabled = true;
161+
config.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
162+
config.LogBuffering.FlushOnErrorLog = false;
169163
});
170164

171165
for (int e = 0; e < entriesPerInvocation; e++)
@@ -224,12 +218,10 @@ public void BufferEvictionIsolation_SizeLimitEviction_ShouldOnlyAffectOwnBuffer(
224218
Logger.Configure(config =>
225219
{
226220
config.MinimumLogLevel = LogLevel.Debug;
227-
config.LogBuffering = new LogBufferingOptions
228-
{
229-
BufferAtLogLevel = LogLevel.Debug,
230-
FlushOnErrorLog = false,
231-
MaxBytes = smallBufferSize
232-
};
221+
config.LogBuffering.Enabled = true;
222+
config.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
223+
config.LogBuffering.FlushOnErrorLog = false;
224+
config.LogBuffering.MaxBytes = smallBufferSize;
233225
});
234226

235227
for (int e = 0; e < entriesPerInvocation * 3; e++)
@@ -256,12 +248,10 @@ public void BufferEvictionIsolation_SizeLimitEviction_ShouldOnlyAffectOwnBuffer(
256248
Logger.Configure(config =>
257249
{
258250
config.MinimumLogLevel = LogLevel.Debug;
259-
config.LogBuffering = new LogBufferingOptions
260-
{
261-
BufferAtLogLevel = LogLevel.Debug,
262-
FlushOnErrorLog = false,
263-
MaxBytes = largeBufferSize
264-
};
251+
config.LogBuffering.Enabled = true;
252+
config.LogBuffering.BufferAtLogLevel = LogLevel.Debug;
253+
config.LogBuffering.FlushOnErrorLog = false;
254+
config.LogBuffering.MaxBytes = largeBufferSize;
265255
});
266256

267257
for (int e = 0; e < entriesPerInvocation; e++)

0 commit comments

Comments
 (0)