##// END OF EJS Templates
Added IObservable to TraceRegistry
Added IObservable to TraceRegistry

File last commit:

r287:78da52bb28f0 v3
r288:90cef6117ced v3
Show More
Trace.cs
199 lines | 8.0 KiB | text/x-csharp | CSharpLexer
// 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);
}
}
}