Files
EonaCat.LogStack/EonaCat.LogStack/AdvancedMetricsCollector.cs
T
EonaCatandJeroen Saey dae624fd45 Added more stats
Added more dependency injection
Made README.md better
2026-06-11 08:17:29 +02:00

264 lines
8.3 KiB
C#

using EonaCat.LogStack.Analytics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace EonaCat.LogStack;
// This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
/// <summary>
/// Advanced metrics collector that provides comprehensive analytics across loggers
/// </summary>
public sealed class AdvancedMetricsCollector
{
private readonly List<EonaCatLogStack> _loggers = new();
private readonly object _lock = new();
/// <summary>
/// Registers a logger for metrics collection
/// </summary>
public void RegisterLogger(EonaCatLogStack logger)
{
if (logger != null)
{
lock (_lock)
{
if (!_loggers.Contains(logger))
{
_loggers.Add(logger);
}
}
}
}
/// <summary>
/// Unregisters a logger
/// </summary>
public void UnregisterLogger(EonaCatLogStack logger)
{
if (logger != null)
{
lock (_lock)
{
_loggers.Remove(logger);
}
}
}
/// <summary>
/// Gets aggregated metrics across all registered loggers
/// </summary>
public AggregatedMetrics GetAggregatedMetrics()
{
lock (_lock)
{
var aggregated = new AggregatedMetrics
{
Timestamp = DateTime.UtcNow,
LoggerMetrics = new List<LoggerMetrics>()
};
foreach (var logger in _loggers)
{
try
{
var metrics = logger.GetMetrics();
aggregated.LoggerMetrics.Add(metrics);
}
catch { }
}
// Aggregate totals
aggregated.TotalLoggedAcrossAll = aggregated.LoggerMetrics.Sum(m => m.TotalLogged);
aggregated.TotalDroppedAcrossAll = aggregated.LoggerMetrics.Sum(m => m.TotalDropped);
aggregated.TotalExceptionsAcrossAll = aggregated.LoggerMetrics.Sum(m => m.TotalExceptions);
aggregated.TotalBytesAcrossAll = aggregated.LoggerMetrics.Sum(m => m.TotalBytes);
aggregated.ActiveLoggers = _loggers.Count;
return aggregated;
}
}
/// <summary>
/// Gets a performance comparison across loggers
/// </summary>
public PerformanceComparison GetPerformanceComparison()
{
var aggregated = GetAggregatedMetrics();
return new PerformanceComparison
{
Timestamp = aggregated.Timestamp,
TotalLoggers = aggregated.ActiveLoggers,
HighestThroughputLogger = aggregated.LoggerMetrics.OrderByDescending(m => m.WritesPerSecond).FirstOrDefault(),
LowestSuccessRateLogger = aggregated.LoggerMetrics.OrderBy(m => m.SuccessRate).FirstOrDefault(),
AverageBytesPerEvent = aggregated.LoggerMetrics.Count > 0
? aggregated.LoggerMetrics.Average(m => m.AverageBytesPerEvent)
: 0,
AverageWritesPerSecond = aggregated.LoggerMetrics.Count > 0
? aggregated.LoggerMetrics.Average(m => m.WritesPerSecond)
: 0
};
}
/// <summary>
/// Gets a health report
/// </summary>
public HealthReport GetHealthReport()
{
var aggregated = GetAggregatedMetrics();
var report = new HealthReport
{
Timestamp = aggregated.Timestamp,
OverallStatus = "Healthy",
Warnings = new List<string>(),
Errors = new List<string>()
};
foreach (var logger in aggregated.LoggerMetrics)
{
if (logger.SuccessRate < 95)
{
report.Warnings.Add($"{logger.GetType().Name}: Low success rate ({logger.SuccessRate:F1}%)");
}
if (logger.TotalExceptions > logger.TotalLogged * 0.05) // More than 5% exceptions
{
report.Warnings.Add($"Logger: High exception rate ({logger.TotalExceptions} exceptions)");
}
}
if (report.Warnings.Count > 0)
{
report.OverallStatus = "Warning";
}
if (report.Errors.Count > 0)
{
report.OverallStatus = "Error";
}
return report;
}
/// <summary>
/// Resets all metrics
/// </summary>
public void Reset()
{
lock (_lock)
{
_loggers.Clear();
}
}
}
/// <summary>
/// Aggregated metrics across multiple loggers
/// </summary>
public sealed class AggregatedMetrics
{
public DateTime Timestamp { get; set; }
public List<LoggerMetrics> LoggerMetrics { get; set; } = new();
public long TotalLoggedAcrossAll { get; set; }
public long TotalDroppedAcrossAll { get; set; }
public long TotalExceptionsAcrossAll { get; set; }
public long TotalBytesAcrossAll { get; set; }
public int ActiveLoggers { get; set; }
public double OverallSuccessRate
{
get
{
var total = TotalLoggedAcrossAll + TotalDroppedAcrossAll;
return total > 0 ? (TotalLoggedAcrossAll * 100.0) / total : 100;
}
}
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine("===== AGGREGATED METRICS =====");
sb.AppendLine($"Timestamp: {Timestamp:O}");
sb.AppendLine($"Active Loggers: {ActiveLoggers}");
sb.AppendLine($"Total Logged: {TotalLoggedAcrossAll:N0}");
sb.AppendLine($"Total Dropped: {TotalDroppedAcrossAll:N0}");
sb.AppendLine($"Overall Success Rate: {OverallSuccessRate:F2}%");
sb.AppendLine($"Total Exceptions: {TotalExceptionsAcrossAll:N0}");
sb.AppendLine($"Total Bytes: {TotalBytesAcrossAll:N0}");
sb.AppendLine("==============================");
return sb.ToString();
}
}
/// <summary>
/// Performance comparison across loggers
/// </summary>
public sealed class PerformanceComparison
{
public DateTime Timestamp { get; set; }
public int TotalLoggers { get; set; }
public LoggerMetrics HighestThroughputLogger { get; set; }
public LoggerMetrics LowestSuccessRateLogger { get; set; }
public double AverageBytesPerEvent { get; set; }
public double AverageWritesPerSecond { get; set; }
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine("===== PERFORMANCE COMPARISON =====");
sb.AppendLine($"Timestamp: {Timestamp:O}");
sb.AppendLine($"Total Loggers: {TotalLoggers}");
sb.AppendLine($"Highest Throughput: {HighestThroughputLogger?.WritesPerSecond:F2} events/sec");
sb.AppendLine($"Lowest Success Rate: {LowestSuccessRateLogger?.SuccessRate:F2}%");
sb.AppendLine($"Average Bytes/Event: {AverageBytesPerEvent:F2}");
sb.AppendLine($"Average Writes/Second: {AverageWritesPerSecond:F2}");
sb.AppendLine("==================================");
return sb.ToString();
}
}
/// <summary>
/// Health report for logging system
/// </summary>
public sealed class HealthReport
{
public DateTime Timestamp { get; set; }
public string OverallStatus { get; set; } = "Unknown";
public List<string> Warnings { get; set; } = new();
public List<string> Errors { get; set; } = new();
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine("===== HEALTH REPORT =====");
sb.AppendLine($"Timestamp: {Timestamp:O}");
sb.AppendLine($"Status: {OverallStatus}");
if (Warnings.Count > 0)
{
sb.AppendLine("\nWarnings:");
foreach (var warning in Warnings)
{
sb.AppendLine($" - {warning}");
}
}
if (Errors.Count > 0)
{
sb.AppendLine("\nErrors:");
foreach (var error in Errors)
{
sb.AppendLine($" - {error}");
}
}
sb.AppendLine("========================");
return sb.ToString();
}
}