// 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 { /// /// Static class which creates an individual for /// the type specified in the parameter and uses /// it to perform logging operations. /// /// The type for which tracing is demanded. public static class Trace { readonly static Lazy _trace = new Lazy(() => TraceSourceChannel.Default.Source); /// /// The associated with the current class. /// TraceSource is created using . /// public static TraceSource TraceSource { get { return _trace.Value; } } #if NETFX_TRACE_BUG // AsyncLocal will store value inside the current execution context // and will force it to be copied... not a very effective solution. readonly static AsyncLocal m_currentOperation = new AsyncLocal(); #endif /// /// If this property is set then will produce output. /// public static bool TraceVerbose { get { return TraceSource.Switch.ShouldTrace(TraceEventType.Verbose); } } /// /// If this property is set then will produce output. /// public static bool TraceInformation { get { return TraceSource.Switch.ShouldTrace(TraceEventType.Information); } } /// /// If this property is set then will produce output. /// public static bool TraceWarnings { get { return TraceSource.Switch.ShouldTrace(TraceEventType.Warning); } } /// /// 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); } /// /// Starts the logical operation nested to the current operation nested to the current one. /// public static void StartLogicalOperation() { m_currentOperation.Value = new object(); Trace.CorrelationManager.StartLogicalOperation(); } #else public static void StartLogicalOperation(object name) { Trace.CorrelationManager.StartLogicalOperation(name); } /// /// Starts the logical operation nested to the current operation nested to the current one. /// public static void StartLogicalOperation() { Trace.CorrelationManager.StartLogicalOperation(); } #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) { TraceSource.TraceEvent(TraceEventType.Verbose, 0, format, 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); } } }