using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; namespace Wayne.Lib.Log.SlowLog { internal class Slowlogger : DisposableBase, ISlowLogger { private static readonly IIdentifiableEntity LoggingEntity = new IdentifiableEntity(IdentifiableEntity.NoId, "SlowLog", "", null); private readonly Stopwatch stopwatch = Stopwatch.StartNew(); private readonly string context; private readonly TimeSpan threshold; readonly List checkpoints = new List(); class CheckpointInstant { public TimeSpan At { get; set; } public string Name { get; set; } } public Slowlogger(string context, TimeSpan threshold) { this.context = context; this.threshold = threshold; } protected override void DoDispose() { stopwatch.Stop(); if (stopwatch.Elapsed > threshold) { using (DebugLogger debugLogger = new DebugLogger(LoggingEntity)) { if (debugLogger.IsActive()) { StringBuilder sb = new StringBuilder(); sb.AppendFormat(":::::: SLOWLOG ::::: [{0}] Expected to take less than {1} but took {2}", context, threshold, stopwatch.Elapsed); if (checkpoints.Count > 0) { TimeSpan lastTimeSpan = checkpoints[0].At; foreach (var checkpointInstant in checkpoints) { sb.AppendLine(); sb.AppendFormat(" Checkpoint {0,45} @ {1}, delta {2}", checkpointInstant.Name, checkpointInstant.At, checkpointInstant.At - lastTimeSpan); lastTimeSpan = checkpointInstant.At; } } debugLogger.Add(sb); } } } } public void Checkpoint(string checkpointName) { checkpoints.Add(new CheckpointInstant() { Name = checkpointName, At = stopwatch.Elapsed }); } } }