// -----------------------------------------------------------------------------
// 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);
}
}
}