using Serilog.Core; using Serilog.Events; using System.Collections.Concurrent; using System.Globalization; namespace ErsatzTV.Core; public class InMemorySink : ILogEventSink { private readonly ConcurrentDictionary> _logs = new(); public void Emit(LogEvent logEvent) { if (logEvent.Properties.TryGetValue(InMemoryLogService.CorrelationIdKey, out var correlationIdValue) && correlationIdValue is ScalarValue { Value: Guid correlationId }) { ConcurrentQueue logQueue = _logs.GetOrAdd(correlationId, _ => new ConcurrentQueue()); string message = logEvent.RenderMessage(CultureInfo.CurrentCulture); logQueue.Enqueue($"[{logEvent.Timestamp:HH:mm:ss} {logEvent.Level}] {message}"); while (logQueue.Count > 100) { logQueue.TryDequeue(out _); } } } public IEnumerable GetLogs(Guid correlationId) { _logs.TryGetValue(correlationId, out ConcurrentQueue logs); return logs ?? Enumerable.Empty(); } public void ClearLogs(Guid correlationId) { _logs.TryRemove(correlationId, out _); } } public class InMemoryLogService { public InMemorySink Sink { get; } = new(); public static readonly string CorrelationIdKey = "CorrelationId"; }