/

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:

  1. Compares messages: Checks if the current message is identical to recent messages
  2. Applies time window: Only suppresses duplicates within the specified time window
  3. Suppresses duplicates: Skips logging identical messages during the window
  4. 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

Previous
Correlation IDs