Mercurial > pub > ImplabNet
diff Implab/Diagnostics/TraceContext.cs @ 40:fe33f4e02ad5
improved tracing
added text listeners (file,console)
author | cin |
---|---|
date | Tue, 15 Apr 2014 17:52:09 +0400 |
parents | c2c043520724 |
children | 2fc0fbe7d58b |
line wrap: on
line diff
--- a/Implab/Diagnostics/TraceContext.cs Tue Apr 15 02:46:53 2014 +0400 +++ b/Implab/Diagnostics/TraceContext.cs Tue Apr 15 17:52:09 2014 +0400 @@ -6,17 +6,23 @@ using System.Threading.Tasks; namespace Implab.Diagnostics { + /// <summary> + /// Контекст трассировки, привязывается к потоку и содержит в себе информацию о стеке логических операций. + /// </summary> + /// <remarks> + /// Контекст трассировки передается слушателям событий для определения места, где возникло событие. + /// </remarks> public class TraceContext { LogicalOperation m_currentOperation; - readonly LogicalOperation m_traceBound; + readonly LogicalOperation m_bound; readonly int m_threadId; - readonly TraceContext m_parent; - - readonly static object _consoleLock = new object(); [ThreadStatic] static TraceContext _current; + /// <summary> + /// Текущий контекст трассировки для потока, создается астоматически при первом обращении. + /// </summary> public static TraceContext Current { get { if (_current == null) @@ -29,64 +35,124 @@ if (context == null) throw new ArgumentNullException("context"); - m_parent = context; m_currentOperation = context.CurrentOperation; - m_traceBound = context.CurrentOperation; + m_bound = context.CurrentOperation; m_threadId = Thread.CurrentThread.ManagedThreadId; - - LogEvent(TraceEventType.Transfer, "FORK {0}", context.ThreadId); } TraceContext() { m_currentOperation = new LogicalOperation(); - m_traceBound = m_currentOperation; + m_bound = m_currentOperation; m_threadId = Thread.CurrentThread.ManagedThreadId; } + /// <summary> + /// При необходимости копирует состояние контекста трассивровки в текущий поток. + /// </summary> + /// <param name="from">Исходный контекст трассировки, который передается.</param> + /// <remarks> + /// <para> + /// Копирование происходит за счет создания нового контекста трассировки и заполнением его + /// состояния из переданного контекста. При этом копируется стек операций, однако в новом + /// контексте ранее начатые логические операции не могут быть завершены. + /// </para> + /// <para> + /// Если передача состояния состоялась, то вызывается событие трассировки <see cref="TraceEventType.Transfer"/>. + /// </para> + /// </remarks> public static void Transfer(TraceContext from) { - _current = from == null ? new TraceContext() : new TraceContext(from); - } - - public TraceContext ParentContext { - get { - return m_parent; + if (_current == from) + return; + if (from != null) { + var context = new TraceContext(from); + context.LogEvent(TraceEventType.Transfer, "[{0}]-->[{1}]",from.ThreadId, context.ThreadId); + _current = context; + } else { + _current = new TraceContext(); } } + /// <summary> + /// Создает постоянную копию текущего контекста, данную копию можно хранить и использовать для передачи через <see cref="Transfer(TraceContext)"/> + /// </summary> + /// <returns>Копия текущего контекста трассировки или <c>null</c> если таковой не был создан.</returns> + public static TraceContext Snapshot() { + return _current == null ? null : new TraceContext(_current); + } + + /// <summary> + /// Выполняет переданное действие в указанном контексте трассировки, по окончании восстанавливает предыдущий контекст трассировки потока. + /// </summary> + /// <param name="action"></param> + public void Invoke(Action action) { + if (action == null) + throw new ArgumentNullException("action"); + var old = _current; + Transfer(this); + try { + action(); + } finally { + _current = old; + } + } + + /// <summary> + /// Текущая логическая операция. + /// </summary> public LogicalOperation CurrentOperation { get { return m_currentOperation; } } - public LogicalOperation TraceBound { + /// <summary> + /// Операция ниже которой нельзя опускаться в стеке логических операций, т.е. она не может быть завершена в текущем контексте. + /// </summary> + public LogicalOperation BoundOperation { get { - return m_traceBound; + return m_bound; } } + /// <summary> + /// Поток, в котором создан контекст трассировки. + /// </summary> public int ThreadId { get { return m_threadId; } } + /// <summary> + /// Начинает безымянную логическую операцию. + /// </summary> public void StartLogicalOperation() { StartLogicalOperation(null); } + /// <summary> + /// Начинает логическую операцию с указанным именем. Созданная операция будет добвалена в стек логических операций контекста, затем будет создано соответсвующее событие. + /// </summary> + /// <param name="name">Имя начинаемой операции.</param> public void StartLogicalOperation(string name) { - LogEvent(TraceEventType.OperationStarted, "{0}", name); m_currentOperation = new LogicalOperation(name, m_currentOperation); + LogEvent(TraceEventType.OperationStarted, name); } + /// <summary> + /// Заканчивает логическую операцию начатую в текущем контексте. Операции, начатые в других контекстах не могут быть закончены в текущем контексте. + /// </summary> + /// <remarks> + /// При вызове данного метода создается событие журнала трассировки, либо о завершении операции, либо об ошибки, поскольку данная операция + /// начата в другом контексте. + /// </remarks> public void EndLogicalOperation() { - if (m_traceBound == m_currentOperation) { + if (m_bound == m_currentOperation) { LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace"); } else { var op = m_currentOperation; + LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration); m_currentOperation = m_currentOperation.Parent; - LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration); } }