// enable System.Diagnostics trace methods #define TRACE using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Implab.Diagnostics { public static class Trace { static Lazy _traceSource = new Lazy(CreateChannel, LazyThreadSafetyMode.ExecutionAndPublication); static int _nextId; static TraceSource CreateChannel() { var id = Interlocked.Increment(ref _nextId); var trs = new TraceSource(typeof(T).Name); TraceChannelRegistry.AllCannels.NotifyChannelCreated(new ChannelInfo(typeof(T), trs)); return trs; } public static TraceSource TraceSource { get { return _traceSource.Value; } } #if NETFX_TRACE_BUG readonly static AsyncLocal m_currentOperation = new AsyncLocal(); #endif /// /// Starts the logical operation nested to the current operation nested to the current one. /// public static void StartLogicalOperation() { Trace.CorrelationManager.StartLogicalOperation(); } /// /// Starts the logical operation with the specified name, this name is usefull in logs. /// /// Name. #if NETFX_TRACE_BUG public static void StartLogicalOperation(object name) { m_currentOperation.Value = name; Trace.CorrelationManager.StartLogicalOperation(name); } #else public static void StartLogicalOperation(object name) { Trace.CorrelationManager.StartLogicalOperation(name); } #endif /// /// Ends the logical operation and restores the previous one. /// public static void StopLogicalOperation() { Trace.CorrelationManager.StopLogicalOperation(); } /// /// Writes a debug message. /// /// Format. /// Arguments. [Conditional("DEBUG")] public static void Debug(string format, params object[] arguments) { } /// /// Writes an informational message. /// /// Format. /// Arguments. [Conditional("TRACE")] public static void Log(string format, params object[] arguments) { TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments); } /// /// Writes a warning message. /// /// Format. /// Arguments. public static void Warn(string format, params object[] arguments) { TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments); } /// /// Writes a error message. /// /// Format. /// Arguments. public static void Error(string format, params object[] arguments) { TraceSource.TraceEvent(TraceEventType.Error, 0, format, arguments); } public static void Error(Exception err) { TraceSource.TraceData(TraceEventType.Error, 0, err); } /// /// This method save the current activity, and transfers to the specified activity, /// emits and returns a scope of the new /// activity. /// /// The name of the new activity/ /// The identifier of the activity to which /// the control will be transferred /// A scope of the new activity, dispose it to transfer /// the control back to the original activity. public static ActivityScope TransferActivity(string activityName, Guid activityId) { var prev = Trace.CorrelationManager.ActivityId; TraceSource.TraceTransfer(0, "Transfer", activityId); Trace.CorrelationManager.ActivityId = activityId; TraceSource.TraceEvent(TraceEventType.Start, 0, activityName); return new ActivityScope(TraceSource, prev, 0, activityName); } /// /// Emits and returns a scope of the /// activity. /// /// The name of the activity to start /// A scope of the new activity, dispose it to emit /// for the current activity. public static ActivityScope StartActivity(string activityName) { if (Trace.CorrelationManager.ActivityId == Guid.Empty) Trace.CorrelationManager.ActivityId = Guid.NewGuid(); var prev = Trace.CorrelationManager.ActivityId; TraceSource.TraceEvent(TraceEventType.Start, 0, activityName); return new ActivityScope(TraceSource, prev, 0, activityName); } /// /// Creates new and calls /// to /// passing the created operation as identity. Calls /// /// to notify listeners on operation start. /// /// The name of the logical operation. /// Logical operation scope, disposing it will stop /// logical operation and notify trace listeners. public static LogicalOperationScope LogicalOperation(string name) { var operation = new LogicalOperation(name); TraceSource.TraceData(TraceEventType.Information, TraceEventCodes.StartLogicalOperation, operation); StartLogicalOperation(operation); return new LogicalOperationScope(TraceSource, operation); } } }