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