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