Duplicate Suppression
Duplicate suppression prevents identical log messages from flooding your logs by suppressing repeated messages within a specified time window. This reduces noise and improves log readability.
Configuration
Configure duplicate suppression in LogSettings
:
Log.Initialize(new LogSettings
{
DuplicateSuppressionWindow = TimeSpan.FromSeconds(5) // Default: null (disabled)
});
How It Works
When duplicate suppression is enabled, ByteHide Logger:
- Compares messages: Checks if the current message is identical to recent messages
- Applies time window: Only suppresses duplicates within the specified time window
- Suppresses duplicates: Skips logging identical messages during the window
- Resets on timeout: Allows the message again after the window expires
Log.Initialize(new LogSettings
{
DuplicateSuppressionWindow = TimeSpan.FromSeconds(5)
});
Log.Info("Database connection failed"); // Logged
Log.Info("Database connection failed"); // Suppressed (within 5 seconds)
Log.Info("Database connection failed"); // Suppressed (within 5 seconds)
// After 5 seconds...
Log.Info("Database connection failed"); // Logged again
Common Time Windows
// Short suppression for high-frequency events
DuplicateSuppressionWindow = TimeSpan.FromSeconds(1)
// Medium suppression for regular events
DuplicateSuppressionWindow = TimeSpan.FromSeconds(5)
// Long suppression for persistent issues
DuplicateSuppressionWindow = TimeSpan.FromMinutes(1)
// Environment-based configuration
var suppressionWindow = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") switch
{
"Development" => TimeSpan.FromSeconds(1),
"Production" => TimeSpan.FromSeconds(10),
_ => TimeSpan.FromSeconds(5)
};
Use Cases
Duplicate suppression is useful for preventing log flooding:
// Database connection issues - only log once every 10 seconds
public async Task<User> GetUserAsync(int userId)
{
try
{
return await _database.GetUserAsync(userId);
}
catch (SqlException ex)
{
Log.Error("Database connection failed", new { UserId = userId }, ex);
throw;
}
}
// API rate limiting - prevent flooding with rate limit messages
public async Task<ApiResponse> CallExternalApiAsync()
{
try
{
return await _httpClient.GetAsync("/api/data");
}
catch (HttpRequestException ex) when (ex.Message.Contains("429"))
{
Log.Warn("API rate limit exceeded - requests being throttled", ex);
throw;
}
}
Message Comparison
Duplicate suppression compares the exact message content and context:
Log.Info("User login failed"); // Logged
Log.Info("User login failed"); // Suppressed (exact match)
Log.Info("User Login Failed"); // Logged (different case)
// Context objects are also compared
Log.Error("Payment failed", new { UserId = 123, Amount = 100 }, ex); // Logged
Log.Error("Payment failed", new { UserId = 456, Amount = 100 }, ex); // Logged (different UserId)
Log.Error("Payment failed", new { UserId = 123, Amount = 100 }, ex); // Suppressed (exact match)
Disable Suppression
// Disable suppression for debugging
Log.Initialize(new LogSettings
{
DuplicateSuppressionWindow = null // Disabled
});
// Environment-based disabling
var isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";
DuplicateSuppressionWindow = isDevelopment ? null : TimeSpan.FromSeconds(10)
Best Practices
Best Practices
- Start with 5-10 second windows and adjust based on needs
- Use longer windows for high-volume applications
- Disable suppression when debugging specific issues
- Consider memory usage with very long windows
Next Steps
- Global Properties - Add consistent context to all logs
- Configuration - Configure suppression settings