<PackageReference Include="Relativity.Server.Import.SDK" Version="2.9.2" />

Timekeeper2

public sealed class Timekeeper2
Represents a class object that tracks operational metrics. This class cannot be inherited.
using Relativity.DataExchange.Io; using System; using System.Collections.Concurrent; using System.Text; namespace Relativity.DataExchange { public sealed class Timekeeper2 { private const int DefaultThread = 0; private readonly ConcurrentDictionary<string, ConcurrentDictionary<int, TimekeeperEntry2>> dictionary; private readonly IFileSystem fileSystem; private readonly IAppSettings settings; private bool? logAllEvents; public int Count => dictionary.Count; public Timekeeper2() : this(FileSystem.Instance.DeepCopy(), AppSettings.Instance) { } public Timekeeper2(IFileSystem fileSystem, IAppSettings settings) { if (fileSystem == null) throw new ArgumentNullException("fileSystem"); if (settings == null) throw new ArgumentNullException("settings"); this.fileSystem = fileSystem; this.settings = settings; dictionary = new ConcurrentDictionary<string, ConcurrentDictionary<int, TimekeeperEntry2>>(); } public TimekeeperEntry2 GetEntry(string key) { return GetEntry(key, 0); } public TimekeeperEntry2 GetEntry(string key, int thread) { if (!dictionary.ContainsKey(key)) return null; ConcurrentDictionary<int, TimekeeperEntry2> concurrentDictionary = dictionary[key]; if (!concurrentDictionary.ContainsKey(thread)) return null; return concurrentDictionary[thread]; } public void MarkEnd(string key) { MarkEnd(key, 0); } public void MarkEnd(string key, int thread) { if (LogAllEvents()) { ConcurrentDictionary<int, TimekeeperEntry2> concurrentDictionary = dictionary[key]; TimekeeperEntry2 timekeeperEntry = (concurrentDictionary != null) ? concurrentDictionary[thread] : null; if (timekeeperEntry != null) { timekeeperEntry.Count++; TimekeeperEntry2 timekeeperEntry2 = timekeeperEntry; long length = timekeeperEntry2.Length; DateTime now = DateTime.Now; timekeeperEntry2.Length = length + (now.Ticks - timekeeperEntry.StartTime) / 10000; TimekeeperEntry2 timekeeperEntry3 = timekeeperEntry; now = DateTime.Now; timekeeperEntry3.StartTime = now.Ticks; } } } public void MarkStart(string key) { MarkStart(key, 0); } public void MarkStart(string key, int thread) { if (LogAllEvents()) { if (dictionary.ContainsKey(key)) { ConcurrentDictionary<int, TimekeeperEntry2> concurrentDictionary = dictionary[key]; if (concurrentDictionary.ContainsKey(thread)) concurrentDictionary[thread].StartTime = DateTime.Now.Ticks; else concurrentDictionary[thread] = new TimekeeperEntry2(); } else dictionary[key] = new ConcurrentDictionary<int, TimekeeperEntry2> { [thread] = new TimekeeperEntry2() }; } } public void GenerateCsvReportItemsAsRows() { GenerateCsvReportItemsAsRows(string.Empty, string.Empty); } public void GenerateCsvReportItemsAsRows(string filenameSuffix, string directory) { if (LogAllEvents()) { string fileName = GetFileName(filenameSuffix); string path = directory + fileName; if (!string.IsNullOrEmpty(directory)) path = fileSystem.Path.Combine(directory, fileName); using (IStreamWriter streamWriter = fileSystem.CreateStreamWriter(path, false, Encoding.Default)) { streamWriter.WriteLine("\"Function Name\",\"Number of calls\",\"Total Length (ms)\""); string[] array = new string[checked(dictionary.Keys.Count - 1 + 1)]; dictionary.Keys.CopyTo(array, 0); Array.Sort(array); string[] array2 = array; foreach (string text in array2) { ConcurrentDictionary<int, TimekeeperEntry2> concurrentDictionary = dictionary[text]; int num = 0; long num2 = 0; foreach (TimekeeperEntry2 value in concurrentDictionary.Values) { num += value.Count; num2 += value.Length; } streamWriter.WriteLine($"""{text}""{num}""{num2}"""); } } } } private string GetFileName(string filenameSuffix) { if (!LogAllEvents()) return null; StringBuilder stringBuilder = new StringBuilder(); DateTime now = DateTime.Now; stringBuilder.Append(now.Year); now = DateTime.Now; int num = now.Month; stringBuilder.Append(num.ToString().PadLeft(2, '0')); now = DateTime.Now; num = now.Day; stringBuilder.Append(num.ToString().PadLeft(2, '0')); now = DateTime.Now; num = now.Hour; stringBuilder.Append(num.ToString().PadLeft(2, '0')); now = DateTime.Now; num = now.Minute; stringBuilder.Append(num.ToString().PadLeft(2, '0')); now = DateTime.Now; num = now.Second; stringBuilder.Append(num.ToString().PadLeft(2, '0')); stringBuilder.Append(filenameSuffix); stringBuilder.Append(".csv"); return stringBuilder.ToString(); } private bool LogAllEvents() { if (!logAllEvents.HasValue) logAllEvents = settings.LogAllEvents; bool? nullable = logAllEvents; bool flag = true; return (nullable.GetValueOrDefault() == flag) & nullable.HasValue; } } }