// ----------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. // ----------------------------------------------------------------------------- namespace Microsoft.DiagnosticsHub { using System; using System.Diagnostics; using System.Diagnostics.Tracing; using System.Threading; /// /// Types of user mark events /// #pragma warning disable CA1008 // We can never have a value of 0 for MarkEvent because it is an invalid event ID public enum MarkEvent { MapIdToName = 1, Emit = 2, Range = 3, MapRangeToName = 4 } #pragma warning restore CA1008 /// /// Class used for firing UserMarks via EventSource /// [EventSource(Guid = "F9189F8A-0753-4A70-AD66-D622D88DB986", Name = "UserMarks")] internal class UserMarkSource : EventSource { private static readonly Lazy lazy = new Lazy(() => new UserMarkSource()); public static UserMarkSource Log => lazy.Value; /// /// Constructor to create a usermark /// /// Optional name of the usermark private UserMarkSource() : base() { } /// /// Fires an event to add the user mark with an optional message /// /// Id of the user mark /// Optional message [Event((int)MarkEvent.Emit, Version = 2)] [Conditional("DIAGHUB_ENABLE_TRACE_SYSTEM")] public void FireEmitEvent(int id, string message = "") { this.WriteEvent((int)MarkEvent.Emit, id, message); } /// /// Fires an event to correlate te user mark with a name /// /// Id of the user mark /// Name of the user mark [Event((int)MarkEvent.MapIdToName, Version = 2)] [Conditional("DIAGHUB_ENABLE_TRACE_SYSTEM")] public void FireIdToNameEvent(int id, string name) { this.WriteEvent((int)MarkEvent.MapIdToName, id, name); } /// /// Fires an event to correlate an id with its range /// /// Range guid /// User mark range start id /// User mark range end id [Event((int)MarkEvent.Range, Version = 2)] [Conditional("DIAGHUB_ENABLE_TRACE_SYSTEM")] public void FireRangeEvent(string rangeGuid, int startId, int endId) { this.WriteEvent((int)MarkEvent.Range, rangeGuid, startId, endId); } /// /// Fires an event to correlate the range with a name /// /// Unique guid identifying the range /// Name of the range [Event((int)MarkEvent.MapRangeToName, Version = 2)] [Conditional("DIAGHUB_ENABLE_TRACE_SYSTEM")] public void FireRangeIdToName(string rangeGuid, string name) { this.WriteEvent((int)MarkEvent.MapRangeToName, rangeGuid, name); } } public sealed class UserMarks { private const int DefaultId = int.MaxValue; private static int newId = int.MinValue; private readonly int id; internal static int GetNewId() { var newId = Interlocked.Increment(ref UserMarks.newId); if (newId == DefaultId) { throw new InvalidOperationException("Unable to create new UserMark identifier due to reaching max limit."); } return newId; } /// /// Get the id of the usermark /// public int Id => this.id; /// /// Create a usermark /// /// Optional name of the usermark /// >A new usermark public UserMarks(string name = "") { this.id = GetNewId(); if (!string.IsNullOrEmpty(name)) { UserMarkSource.Log.FireIdToNameEvent(this.id, name); } } /// /// Emits a usermark with the default id and the specified message /// /// Message to add [Conditional("DIAGHUB_ENABLE_TRACE_SYSTEM")] public static void EmitMessage(string message) { UserMarkSource.Log.FireEmitEvent(DefaultId, message); } /// /// Emits the usermark /// [Conditional("DIAGHUB_ENABLE_TRACE_SYSTEM")] public void Emit() { UserMarkSource.Log.FireEmitEvent(this.id); } /// /// Emits the usermark with a message /// /// Message to emit [Conditional("DIAGHUB_ENABLE_TRACE_SYSTEM")] public void Emit(string message) { UserMarkSource.Log.FireEmitEvent(this.id, message); } } }