using Microsoft.ApplicationInsights; using System; using System.Collections.Generic; using System.Linq; using System.Threading; namespace PostSharp.Samples.Profiling { internal class MetricPublisher : IDisposable { readonly SampleCollector sampleCollector; private readonly TelemetryClient telemetryClient; private MetricData[] lastSamples = new MetricData[0]; Timer timer; bool inProgress; public MetricPublisher(SampleCollector collector, TelemetryClient telemetryClient) { this.telemetryClient = telemetryClient; this.sampleCollector = collector; } public void Start(TimeSpan period) { this.timer?.Dispose(); this.timer = new Timer(this.OnTime, null, (int) period.TotalMilliseconds, (int) period.TotalMilliseconds); } private void OnTime(object state) { if (this.inProgress) { return; } this.inProgress = true; try { this.PublishMetrics(); } finally { this.inProgress = false; } } public void PublishMetrics() => this.PublishMetrics(this.sampleCollector.MetricsMetadata, this.sampleCollector.GetMetrics()); private void PublishMetrics(IReadOnlyList<MetricMetadata> methods, MetricData[] metrics) { for (var i = 0; i < metrics.Length; i++) { MetricData lastSample; if (i < this.lastSamples.Length) { lastSample = this.lastSamples[i]; } else { lastSample = new MetricData { Timestamp = ProfilingServices.StartTimestamp }; } metrics[i].GetDifference(lastSample, out var differenceSample); this.PublishMetric(methods[i], differenceSample); } this.lastSamples = metrics; } private void PublishMetric(MetricMetadata method, in MetricData metric) { if (metric.ExecutionCount > 0) { var metrics = new Dictionary<string, double> { ["ExceptionCount"] = metric.ExceptionCount, ["ExecutionCount"] = metric.ExecutionCount, ["CpuTime"] = metric.CpuTimeSpan.TotalMilliseconds, ["ThreadTime"] = metric.ThreadTimeSpan.TotalMilliseconds, ["ExclusiveCpuTime"] = metric.ExclusiveCpuTimeSpan.TotalMilliseconds, ["ExclusiveThreadTime"] = metric.ExclusiveThreadTimeSpan.TotalMilliseconds, ["AsyncTime"] = metric.AsyncTimeSpan.TotalMilliseconds, ["SampleTime"] = metric.SampleTimeSpan.TotalMilliseconds }; Console.WriteLine(string.Format("TrackEvent: Name='{0,-70}', {1}", method.Name, string.Join(", ", metrics.Select(p => $"{p.Key}={p.Value,10}")))); this.telemetryClient.TrackEvent(method.Name, metrics: metrics); } } public void Dispose() { this.timer?.Dispose(); } } }