using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Implab.Diagnostics { public class TraceContext { LogicalOperation m_currentOperation; readonly LogicalOperation m_traceBound; readonly int m_threadId; readonly TraceContext m_parent; readonly static object _consoleLock = new object(); [ThreadStatic] static TraceContext _current; public static TraceContext Current { get { if (_current == null) _current = new TraceContext(); return _current; } } TraceContext(TraceContext context) { if (context == null) throw new ArgumentNullException("context"); m_parent = context; m_currentOperation = context.CurrentOperation; m_traceBound = context.CurrentOperation; m_threadId = Thread.CurrentThread.ManagedThreadId; LogEvent(TraceEventType.Transfer, "FORK {0}", context.ThreadId); } TraceContext() { m_currentOperation = new LogicalOperation(); m_traceBound = m_currentOperation; m_threadId = Thread.CurrentThread.ManagedThreadId; } public static void Transfer(TraceContext from) { _current = from == null ? new TraceContext() : new TraceContext(from); } public TraceContext ParentContext { get { return m_parent; } } public LogicalOperation CurrentOperation { get { return m_currentOperation; } } public LogicalOperation TraceBound { get { return m_traceBound; } } public int ThreadId { get { return m_threadId; } } public void StartLogicalOperation() { StartLogicalOperation(null); } public void StartLogicalOperation(string name) { LogEvent(TraceEventType.OperationStarted, "{0}", name); m_currentOperation = new LogicalOperation(name, m_currentOperation); } public void EndLogicalOperation() { if (m_traceBound == m_currentOperation) { LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace"); } else { var op = m_currentOperation; m_currentOperation = m_currentOperation.Parent; LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration); } } void LogEvent(TraceEventType type, string format, params object[] args) { LogChannel.Default.LogEvent(this, TraceEvent.Create(type, format, args)); } } }