TeamCity.MSBuild.Logger/PerformanceCounter.cs (81 lines of code) (raw):
namespace TeamCity.MSBuild.Logger
{
using System;
using System.Collections.Generic;
using System.Globalization;
using JetBrains.Annotations;
using Microsoft.Build.Framework;
// ReSharper disable once ClassNeverInstantiated.Global
internal class PerformanceCounter: IPerformanceCounter
{
[NotNull] private readonly IMessageWriter _messageWriter;
private readonly IDictionary<string, IPerformanceCounter> _internalPerformanceCounters = new Dictionary<string, IPerformanceCounter>(StringComparer.OrdinalIgnoreCase);
private Dictionary<BuildEventContext, long> _startedEvent;
[NotNull] private readonly ILogWriter _logWriter;
[NotNull] private readonly IPerformanceCounterFactory _performanceCounterFactory;
private int _calls;
public PerformanceCounter(
[NotNull] ILogWriter logWriter,
[NotNull] IPerformanceCounterFactory performanceCounterFactory,
[NotNull] IMessageWriter messageWriter)
{
_messageWriter = messageWriter ?? throw new ArgumentNullException(nameof(messageWriter));
_logWriter = logWriter ?? throw new ArgumentNullException(nameof(logWriter));
_performanceCounterFactory = performanceCounterFactory ?? throw new ArgumentNullException(nameof(performanceCounterFactory));
}
public string ScopeName { get; set; } = string.Empty;
public TimeSpan ElapsedTime { get; private set; } = new TimeSpan(0L);
public bool ReenteredScope => false;
public int MessageIdentLevel { private get; set; } = 2;
public void AddEventStarted(string projectTargetNames, BuildEventContext buildEventContext, DateTime eventTimeStamp, IEqualityComparer<BuildEventContext> comparer)
{
if (!string.IsNullOrEmpty(projectTargetNames))
{
var performanceCounter = _performanceCounterFactory.GetOrCreatePerformanceCounter(projectTargetNames, _internalPerformanceCounters);
performanceCounter.AddEventStarted(null, buildEventContext, eventTimeStamp, ComparerContextNodeIdTargetId.Shared);
performanceCounter.MessageIdentLevel = 7;
}
if (_startedEvent == null)
{
_startedEvent = comparer != null ? new Dictionary<BuildEventContext, long>(comparer) : new Dictionary<BuildEventContext, long>();
}
if (_startedEvent.ContainsKey(buildEventContext))
{
return;
}
_startedEvent.Add(buildEventContext, eventTimeStamp.Ticks);
_calls += 1;
}
public void AddEventFinished(string projectTargetNames, BuildEventContext buildEventContext, DateTime eventTimeStamp)
{
if (!string.IsNullOrEmpty(projectTargetNames))
{
_performanceCounterFactory.GetOrCreatePerformanceCounter(projectTargetNames, _internalPerformanceCounters).AddEventFinished(null, buildEventContext, eventTimeStamp);
}
if (_startedEvent == null)
{
throw new InvalidOperationException("Cannot have finished counter without started counter.");
}
if (!_startedEvent.TryGetValue(buildEventContext, out var ticks))
{
return;
}
ElapsedTime += TimeSpan.FromTicks(eventTimeStamp.Ticks - ticks);
_startedEvent.Remove(buildEventContext);
}
public void PrintCounterMessage()
{
var str = string.Format(CultureInfo.CurrentCulture, "{0,5}", Math.Round(ElapsedTime.TotalMilliseconds, 0));
_messageWriter.WriteLinePrettyFromResource(MessageIdentLevel, "PerformanceLine", str, string.Format(CultureInfo.CurrentCulture, "{0,-40}", ScopeName), string.Format(CultureInfo.CurrentCulture, "{0,3}", _calls));
if (_internalPerformanceCounters == null || _internalPerformanceCounters.Count <= 0)
{
return;
}
foreach (var performanceCounter in _internalPerformanceCounters.Values)
{
_logWriter.SetColor(Color.PerformanceCounterInfo);
performanceCounter.PrintCounterMessage();
_logWriter.ResetColor();
}
}
}
}