264 lines
8.3 KiB
C#
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();
|
|
}
|
|
}
|