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