Mercurial > pub > ImplabNet
view 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 source
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Implab.Diagnostics { /// <summary> /// Контекст трассировки, привязывается к потоку и содержит в себе информацию о стеке логических операций. /// </summary> /// <remarks> /// Контекст трассировки передается слушателям событий для определения места, где возникло событие. /// </remarks> public class TraceContext { LogicalOperation m_currentOperation; readonly LogicalOperation m_bound; readonly int m_threadId; [ThreadStatic] static TraceContext _current; /// <summary> /// Текущий контекст трассировки для потока, создается астоматически при первом обращении. /// </summary> public static TraceContext Current { get { if (_current == null) _current = new TraceContext(); return _current; } } TraceContext(TraceContext context) { if (context == null) throw new ArgumentNullException("context"); m_currentOperation = context.CurrentOperation; m_bound = context.CurrentOperation; m_threadId = Thread.CurrentThread.ManagedThreadId; } TraceContext() { m_currentOperation = new LogicalOperation(); 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) { 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; } } /// <summary> /// Операция ниже которой нельзя опускаться в стеке логических операций, т.е. она не может быть завершена в текущем контексте. /// </summary> public LogicalOperation BoundOperation { get { 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) { m_currentOperation = new LogicalOperation(name, m_currentOperation); LogEvent(TraceEventType.OperationStarted, name); } /// <summary> /// Заканчивает логическую операцию начатую в текущем контексте. Операции, начатые в других контекстах не могут быть закончены в текущем контексте. /// </summary> /// <remarks> /// При вызове данного метода создается событие журнала трассировки, либо о завершении операции, либо об ошибки, поскольку данная операция /// начата в другом контексте. /// </remarks> public void EndLogicalOperation() { 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; } } void LogEvent(TraceEventType type, string format, params object[] args) { LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args)); } } }