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