Mercurial > pub > ImplabNet
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 39:6498078ae368 | 40:fe33f4e02ad5 |
|---|---|
| 4 using System.Text; | 4 using System.Text; |
| 5 using System.Threading; | 5 using System.Threading; |
| 6 using System.Threading.Tasks; | 6 using System.Threading.Tasks; |
| 7 | 7 |
| 8 namespace Implab.Diagnostics { | 8 namespace Implab.Diagnostics { |
| 9 /// <summary> | |
| 10 /// Контекст трассировки, привязывается к потоку и содержит в себе информацию о стеке логических операций. | |
| 11 /// </summary> | |
| 12 /// <remarks> | |
| 13 /// Контекст трассировки передается слушателям событий для определения места, где возникло событие. | |
| 14 /// </remarks> | |
| 9 public class TraceContext { | 15 public class TraceContext { |
| 10 LogicalOperation m_currentOperation; | 16 LogicalOperation m_currentOperation; |
| 11 readonly LogicalOperation m_traceBound; | 17 readonly LogicalOperation m_bound; |
| 12 readonly int m_threadId; | 18 readonly int m_threadId; |
| 13 readonly TraceContext m_parent; | |
| 14 | |
| 15 readonly static object _consoleLock = new object(); | |
| 16 | 19 |
| 17 [ThreadStatic] | 20 [ThreadStatic] |
| 18 static TraceContext _current; | 21 static TraceContext _current; |
| 19 | 22 |
| 23 /// <summary> | |
| 24 /// Текущий контекст трассировки для потока, создается астоматически при первом обращении. | |
| 25 /// </summary> | |
| 20 public static TraceContext Current { | 26 public static TraceContext Current { |
| 21 get { | 27 get { |
| 22 if (_current == null) | 28 if (_current == null) |
| 23 _current = new TraceContext(); | 29 _current = new TraceContext(); |
| 24 return _current; | 30 return _current; |
| 27 | 33 |
| 28 TraceContext(TraceContext context) { | 34 TraceContext(TraceContext context) { |
| 29 if (context == null) | 35 if (context == null) |
| 30 throw new ArgumentNullException("context"); | 36 throw new ArgumentNullException("context"); |
| 31 | 37 |
| 32 m_parent = context; | |
| 33 m_currentOperation = context.CurrentOperation; | 38 m_currentOperation = context.CurrentOperation; |
| 34 m_traceBound = context.CurrentOperation; | 39 m_bound = context.CurrentOperation; |
| 35 m_threadId = Thread.CurrentThread.ManagedThreadId; | 40 m_threadId = Thread.CurrentThread.ManagedThreadId; |
| 36 | |
| 37 LogEvent(TraceEventType.Transfer, "FORK {0}", context.ThreadId); | |
| 38 } | 41 } |
| 39 | 42 |
| 40 TraceContext() { | 43 TraceContext() { |
| 41 m_currentOperation = new LogicalOperation(); | 44 m_currentOperation = new LogicalOperation(); |
| 42 m_traceBound = m_currentOperation; | 45 m_bound = m_currentOperation; |
| 43 m_threadId = Thread.CurrentThread.ManagedThreadId; | 46 m_threadId = Thread.CurrentThread.ManagedThreadId; |
| 44 } | 47 } |
| 45 | 48 |
| 49 /// <summary> | |
| 50 /// При необходимости копирует состояние контекста трассивровки в текущий поток. | |
| 51 /// </summary> | |
| 52 /// <param name="from">Исходный контекст трассировки, который передается.</param> | |
| 53 /// <remarks> | |
| 54 /// <para> | |
| 55 /// Копирование происходит за счет создания нового контекста трассировки и заполнением его | |
| 56 /// состояния из переданного контекста. При этом копируется стек операций, однако в новом | |
| 57 /// контексте ранее начатые логические операции не могут быть завершены. | |
| 58 /// </para> | |
| 59 /// <para> | |
| 60 /// Если передача состояния состоялась, то вызывается событие трассировки <see cref="TraceEventType.Transfer"/>. | |
| 61 /// </para> | |
| 62 /// </remarks> | |
| 46 public static void Transfer(TraceContext from) { | 63 public static void Transfer(TraceContext from) { |
| 47 _current = from == null ? new TraceContext() : new TraceContext(from); | 64 if (_current == from) |
| 48 } | 65 return; |
| 49 | 66 if (from != null) { |
| 50 public TraceContext ParentContext { | 67 var context = new TraceContext(from); |
| 51 get { | 68 context.LogEvent(TraceEventType.Transfer, "[{0}]-->[{1}]",from.ThreadId, context.ThreadId); |
| 52 return m_parent; | 69 _current = context; |
| 70 } else { | |
| 71 _current = new TraceContext(); | |
| 53 } | 72 } |
| 54 } | 73 } |
| 55 | 74 |
| 75 /// <summary> | |
| 76 /// Создает постоянную копию текущего контекста, данную копию можно хранить и использовать для передачи через <see cref="Transfer(TraceContext)"/> | |
| 77 /// </summary> | |
| 78 /// <returns>Копия текущего контекста трассировки или <c>null</c> если таковой не был создан.</returns> | |
| 79 public static TraceContext Snapshot() { | |
| 80 return _current == null ? null : new TraceContext(_current); | |
| 81 } | |
| 82 | |
| 83 /// <summary> | |
| 84 /// Выполняет переданное действие в указанном контексте трассировки, по окончании восстанавливает предыдущий контекст трассировки потока. | |
| 85 /// </summary> | |
| 86 /// <param name="action"></param> | |
| 87 public void Invoke(Action action) { | |
| 88 if (action == null) | |
| 89 throw new ArgumentNullException("action"); | |
| 90 var old = _current; | |
| 91 Transfer(this); | |
| 92 try { | |
| 93 action(); | |
| 94 } finally { | |
| 95 _current = old; | |
| 96 } | |
| 97 } | |
| 98 | |
| 99 /// <summary> | |
| 100 /// Текущая логическая операция. | |
| 101 /// </summary> | |
| 56 public LogicalOperation CurrentOperation { | 102 public LogicalOperation CurrentOperation { |
| 57 get { | 103 get { |
| 58 return m_currentOperation; | 104 return m_currentOperation; |
| 59 } | 105 } |
| 60 } | 106 } |
| 61 | 107 |
| 62 public LogicalOperation TraceBound { | 108 /// <summary> |
| 109 /// Операция ниже которой нельзя опускаться в стеке логических операций, т.е. она не может быть завершена в текущем контексте. | |
| 110 /// </summary> | |
| 111 public LogicalOperation BoundOperation { | |
| 63 get { | 112 get { |
| 64 return m_traceBound; | 113 return m_bound; |
| 65 } | 114 } |
| 66 } | 115 } |
| 67 | 116 |
| 117 /// <summary> | |
| 118 /// Поток, в котором создан контекст трассировки. | |
| 119 /// </summary> | |
| 68 public int ThreadId { | 120 public int ThreadId { |
| 69 get { | 121 get { |
| 70 return m_threadId; | 122 return m_threadId; |
| 71 } | 123 } |
| 72 } | 124 } |
| 73 | 125 |
| 126 /// <summary> | |
| 127 /// Начинает безымянную логическую операцию. | |
| 128 /// </summary> | |
| 74 public void StartLogicalOperation() { | 129 public void StartLogicalOperation() { |
| 75 StartLogicalOperation(null); | 130 StartLogicalOperation(null); |
| 76 } | 131 } |
| 77 | 132 |
| 133 /// <summary> | |
| 134 /// Начинает логическую операцию с указанным именем. Созданная операция будет добвалена в стек логических операций контекста, затем будет создано соответсвующее событие. | |
| 135 /// </summary> | |
| 136 /// <param name="name">Имя начинаемой операции.</param> | |
| 78 public void StartLogicalOperation(string name) { | 137 public void StartLogicalOperation(string name) { |
| 79 LogEvent(TraceEventType.OperationStarted, "{0}", name); | |
| 80 m_currentOperation = new LogicalOperation(name, m_currentOperation); | 138 m_currentOperation = new LogicalOperation(name, m_currentOperation); |
| 139 LogEvent(TraceEventType.OperationStarted, name); | |
| 81 } | 140 } |
| 82 | 141 |
| 142 /// <summary> | |
| 143 /// Заканчивает логическую операцию начатую в текущем контексте. Операции, начатые в других контекстах не могут быть закончены в текущем контексте. | |
| 144 /// </summary> | |
| 145 /// <remarks> | |
| 146 /// При вызове данного метода создается событие журнала трассировки, либо о завершении операции, либо об ошибки, поскольку данная операция | |
| 147 /// начата в другом контексте. | |
| 148 /// </remarks> | |
| 83 public void EndLogicalOperation() { | 149 public void EndLogicalOperation() { |
| 84 if (m_traceBound == m_currentOperation) { | 150 if (m_bound == m_currentOperation) { |
| 85 LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace"); | 151 LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace"); |
| 86 } else { | 152 } else { |
| 87 var op = m_currentOperation; | 153 var op = m_currentOperation; |
| 154 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration); | |
| 88 m_currentOperation = m_currentOperation.Parent; | 155 m_currentOperation = m_currentOperation.Parent; |
| 89 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration); | |
| 90 } | 156 } |
| 91 } | 157 } |
| 92 | 158 |
| 93 void LogEvent(TraceEventType type, string format, params object[] args) { | 159 void LogEvent(TraceEventType type, string format, params object[] args) { |
| 94 LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args)); | 160 LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args)); |
