Trace.cs
199 lines
| 8.0 KiB
| text/x-csharp
|
CSharpLexer
cin
|
r289 | // 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 { | ||||
/// <summary> | ||||
/// Static class which creates an individual <see cref="TraceSource"/> for | ||||
/// the type specified in the parameter <typeparamref name="T"/> and uses | ||||
/// it to perform logging operations. | ||||
/// </summary> | ||||
/// <typeparam name="T">The type for which tracing is demanded.</typeparam> | ||||
public static class Trace<T> { | ||||
readonly static Lazy<TraceSource> _trace = new Lazy<TraceSource>(() => TraceSourceChannel<T>.Default.Source); | ||||
/// <summary> | ||||
/// The <see cref="TraceSource"/> associated with the current class. | ||||
/// TraceSource is created using <see cref="TraceSourceChannel{T}"/>. | ||||
/// </summary> | ||||
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<object> m_currentOperation = new AsyncLocal<object>(); | ||||
#endif | ||||
/// <summary> | ||||
/// If this property is set then <see cref="Debug(string, object[])"/> will produce output. | ||||
/// </summary> | ||||
public static bool TraceVerbose { | ||||
get { | ||||
return TraceSource.Switch.ShouldTrace(TraceEventType.Verbose); | ||||
} | ||||
} | ||||
/// <summary> | ||||
/// If this property is set then <see cref="Log(string, object[])"/> will produce output. | ||||
/// </summary> | ||||
public static bool TraceInformation { | ||||
get { | ||||
return TraceSource.Switch.ShouldTrace(TraceEventType.Information); | ||||
} | ||||
} | ||||
/// <summary> | ||||
/// If this property is set then <see cref="Warn(string, object[])"/> will produce output. | ||||
/// </summary> | ||||
public static bool TraceWarnings { | ||||
get { | ||||
return TraceSource.Switch.ShouldTrace(TraceEventType.Warning); | ||||
} | ||||
} | ||||
/// <summary> | ||||
/// Starts the logical operation with the specified name, this name is usefull in logs. | ||||
/// </summary> | ||||
/// <param name="name">Name.</param> | ||||
#if NETFX_TRACE_BUG | ||||
public static void StartLogicalOperation(object name) { | ||||
m_currentOperation.Value = name; | ||||
Trace.CorrelationManager.StartLogicalOperation(name); | ||||
} | ||||
/// <summary> | ||||
/// Starts the logical operation nested to the current operation nested to the current one. | ||||
/// </summary> | ||||
public static void StartLogicalOperation() { | ||||
m_currentOperation.Value = new object(); | ||||
Trace.CorrelationManager.StartLogicalOperation(); | ||||
} | ||||
#else | ||||
public static void StartLogicalOperation(object name) { | ||||
Trace.CorrelationManager.StartLogicalOperation(name); | ||||
} | ||||
/// <summary> | ||||
/// Starts the logical operation nested to the current operation nested to the current one. | ||||
/// </summary> | ||||
public static void StartLogicalOperation() { | ||||
Trace.CorrelationManager.StartLogicalOperation(); | ||||
} | ||||
#endif | ||||
/// <summary> | ||||
/// Ends the logical operation and restores the previous one. | ||||
/// </summary> | ||||
public static void StopLogicalOperation() { | ||||
Trace.CorrelationManager.StopLogicalOperation(); | ||||
} | ||||
/// <summary> | ||||
/// Writes a debug message. | ||||
/// </summary> | ||||
/// <param name="format">Format.</param> | ||||
/// <param name="arguments">Arguments.</param> | ||||
[Conditional("DEBUG")] | ||||
public static void Debug(string format, params object[] arguments) { | ||||
TraceSource.TraceEvent(TraceEventType.Verbose, 0, format, arguments); | ||||
} | ||||
/// <summary> | ||||
/// Writes an informational message. | ||||
/// </summary> | ||||
/// <param name="format">Format.</param> | ||||
/// <param name="arguments">Arguments.</param> | ||||
[Conditional("TRACE")] | ||||
public static void Log(string format, params object[] arguments) { | ||||
TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments); | ||||
} | ||||
/// <summary> | ||||
/// Writes a warning message. | ||||
/// </summary> | ||||
/// <param name="format">Format.</param> | ||||
/// <param name="arguments">Arguments.</param> | ||||
public static void Warn(string format, params object[] arguments) { | ||||
TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments); | ||||
} | ||||
/// <summary> | ||||
/// Writes a error message. | ||||
/// </summary> | ||||
/// <param name="format">Format.</param> | ||||
/// <param name="arguments">Arguments.</param> | ||||
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); | ||||
} | ||||
/// <summary> | ||||
/// This method save the current activity, and transfers to the specified activity, | ||||
/// emits <see cref="TraceEventType.Start"/> and returns a scope of the new | ||||
/// activity. | ||||
/// </summary> | ||||
/// <param name="activityName">The name of the new activity/</param> | ||||
/// <param name="activityId">The identifier of the activity to which | ||||
/// the control will be transferred</param> | ||||
/// <returns>A scope of the new activity, dispose it to transfer | ||||
/// the control back to the original activity.</returns> | ||||
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); | ||||
} | ||||
/// <summary> | ||||
/// Emits <see cref="TraceEventType.Start"/> and returns a scope of the | ||||
/// activity. | ||||
/// </summary> | ||||
/// <param name="activityName">The name of the activity to start</param> | ||||
/// <returns>A scope of the new activity, dispose it to emit | ||||
/// <see cref="TraceEventType.Stop"/> for the current activity.</returns> | ||||
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); | ||||
} | ||||
/// <summary> | ||||
/// Creates new <see cref="LogicalOperation(string)"/> and calls | ||||
/// to <see cref="CorrelationManager.StartLogicalOperation(object)"/> | ||||
/// passing the created operation as identity. Calls | ||||
/// <see cref="TraceSource.TraceData(TraceEventType, int, object)"/> | ||||
/// to notify listeners on operation start. | ||||
/// </summary> | ||||
/// <param name="name">The name of the logical operation.</param> | ||||
/// <returns>Logical operation scope, disposing it will stop | ||||
/// logical operation and notify trace listeners.</returns> | ||||
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); | ||||
} | ||||
} | ||||
} | ||||