##// END OF EJS Templates
removed absolete Diagnostics classes
cin -
r252:6f4630d0bcd9 v3
parent child
Show More
@@ -1,29 +1,37
1 1 using System;
2 2 using System.Diagnostics;
3 3 using System.Threading;
4 using Implab.Diagnostics;
4 5 using Xunit;
5 6
6 7 namespace Implab.Test
7 8 {
9 using static Trace<UnitTest1>;
8 10 public class UnitTest1
9 11 {
10 12 [Fact]
11 13 public void Test1()
12 14 {
13 15 var listener = new TextWriterTraceListener(Console.Out);
14 var source = new TraceSource("Custom",SourceLevels.ActivityTracing);
16 var source = TraceSource;
17 source.Switch.Level = SourceLevels.All;
15 18
16 19 source.Listeners.Add(listener);
20 Trace.Listeners.Add(listener);
17 21
18 Trace.Listeners.Add(listener);
19 22 Trace.WriteLine("Hello!");
20 Trace.CorrelationManager.StartLogicalOperation();
23 StartLogicalOperation();
24
21 25 Trace.WriteLine("Inner");
22 26 foreach(var x in Trace.CorrelationManager.LogicalOperationStack)
23 27 Trace.WriteLine($"-{x}");
24 source.TraceEvent(TraceEventType.Information, 1, "source event");
28 Log("source event");
29
30 listener.IndentLevel = 1;
31
25 32 source.TraceData(TraceEventType.Start, 1, DateTime.Now);
26 Trace.CorrelationManager.StopLogicalOperation();
33
34 StopLogicalOperation();
27 35 }
28 36 }
29 37 }
@@ -1,63 +1,55
1 1 using Implab.Diagnostics;
2 2 using System;
3 3 using System.Diagnostics.CodeAnalysis;
4 4 using System.Threading;
5 5
6 6 namespace Implab.Components {
7 7 /// <summary>
8 8 /// Base class the objects which support disposing.
9 9 /// </summary>
10 10 public class Disposable : IDisposable {
11 11
12 12 public event EventHandler Disposed;
13 13
14 14 public bool IsDisposed {
15 15 get; private set;
16 16 }
17 17
18 18 /// <summary>
19 19 /// Asserts the object is not disposed.
20 20 /// </summary>
21 21 /// <exception cref="ObjectDisposedException">The object is disposed</exception>
22 22 /// <remarks>
23 23 protected void AssertNotDisposed() {
24 24 if (IsDisposed)
25 25 throw new ObjectDisposedException(ToString());
26 26 }
27 27 /// <summary>
28 28 /// Вызывает событие <see cref="Disposed"/>
29 29 /// </summary>
30 30 /// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод
31 31 /// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого
32 32 /// объекта.</param>
33 33 /// <remarks>
34 34 /// Данный метод вызывается гарантированно один раз даже при одновременном вызове <see cref="Dispose()"/>
35 35 /// из нескольких потоков.
36 36 /// </remarks>
37 37 protected virtual void Dispose(bool disposing) {
38 38 if (disposing)
39 39 Disposed.DispatchEvent(this, EventArgs.Empty);
40 40 }
41 41
42 42 [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")]
43 43 public void Dispose() {
44 44 if(!IsDisposed) {
45 45 IsDisposed = true;
46 46 Dispose(true);
47 47 GC.SuppressFinalize(this);
48 48 }
49 49 }
50 50
51 /// <summary>
52 /// Записывает сообщение об утечке объекта.
53 /// </summary>
54 protected virtual void ReportObjectLeaks() {
55 TraceLog.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this);
56 }
57
58 51 ~Disposable() {
59 52 Dispose(false);
60 ReportObjectLeaks();
61 53 }
62 54 }
63 55 } No newline at end of file
@@ -1,273 +1,273
1 1 using System;
2 2 using System.Diagnostics;
3 3 using System.Threading;
4 4 using System.Threading.Tasks;
5 5
6 6 namespace Implab.Components {
7 7 /// <summary>
8 8 /// Base class for implementing components which support start and stop operations,
9 9 /// such components may represent running services.
10 10 /// </summary>
11 11 /// <remarks>
12 12 /// This class provides a basic lifecycle from the creation to the
13 13 /// termination of the component.
14 14 /// </remarks>
15 15 public class RunnableComponent : IRunnable, IInitializable, IDisposable {
16 16
17 17 /// <summary>
18 /// This class bound <see cref="CancellationTokenSource"/> lifetime to the task,
18 /// This class bounds <see cref="CancellationTokenSource"/> lifetime to the task,
19 19 /// when the task completes the associated token source will be disposed.
20 20 /// </summary>
21 21 class AsyncOperationDescriptor {
22 22
23 23 public static AsyncOperationDescriptor None { get; } = new AsyncOperationDescriptor();
24 24
25 25 readonly CancellationTokenSource m_cts;
26 26
27 27 bool m_done;
28 28
29 29 public CancellationToken Token {
30 30 get { return m_cts == null ? CancellationToken.None : m_cts.Token; }
31 31 }
32 32
33 33 public Task Task { get; private set; }
34 34
35 35 private AsyncOperationDescriptor(Task task, CancellationTokenSource cts) {
36 36 m_cts = cts;
37 37 Task = Chain(task);
38 38 }
39 39
40 40 private AsyncOperationDescriptor() {
41 41 Task = Task.CompletedTask;
42 42 }
43 43
44 44 public void Cancel() {
45 45 if (m_cts != null) {
46 46 lock (m_cts) {
47 47 if (!m_done)
48 48 m_cts.Cancel();
49 49 }
50 50 }
51 51 }
52 52
53 53 void Done() {
54 54 if (m_cts != null) {
55 55 lock (m_cts) {
56 56 m_done = true;
57 57 m_cts.Dispose();
58 58 }
59 59 } else {
60 60 m_done = true;
61 61 }
62 62 }
63 63
64 64 async Task Chain(Task other) {
65 65 try {
66 66 await other;
67 67 } finally {
68 68 Done();
69 69 }
70 70 }
71 71
72 72 public static AsyncOperationDescriptor Create(Func<CancellationToken, Task> factory, CancellationToken ct) {
73 73 var cts = ct.CanBeCanceled ?
74 74 CancellationTokenSource.CreateLinkedTokenSource(ct) :
75 75 new CancellationTokenSource();
76 76
77 77 return new AsyncOperationDescriptor(factory(cts.Token), cts);
78 78 }
79 79
80 80 }
81 81
82 82 // this lock is used to synchronize state flow of the component during
83 83 // completions or the operations.
84 84 readonly object m_lock = new object();
85 85
86 86 // current operation cookie, used to check wheather a call to
87 87 // MoveSuccess/MoveFailed method belongs to the current
88 88 // operation, if cookies didn't match ignore completion result.
89 89 object m_cookie;
90 90
91 91 AsyncOperationDescriptor m_current = AsyncOperationDescriptor.None;
92 92
93 93 ExecutionState m_state;
94 94
95 95
96 96 protected RunnableComponent(bool initialized) {
97 97 State = initialized ? ExecutionState.Ready : ExecutionState.Created;
98 98 }
99 99
100 100 public Task Completion {
101 101 get { return m_current.Task; }
102 102 }
103 103
104 104 public ExecutionState State {
105 105 get { return m_state; }
106 106 private set {
107 107 if (m_state != value) {
108 108 m_state = value;
109 109 StateChanged.DispatchEvent(this, new StateChangeEventArgs {
110 110 State = value,
111 111 LastError = LastError
112 112 });
113 113 }
114 114 }
115 115 }
116 116
117 117 public Exception LastError { get; private set; }
118 118
119 119 public event EventHandler<StateChangeEventArgs> StateChanged;
120 120
121 121 /// <summary>
122 122 /// Releases all resources used by the current component regardless of its
123 123 /// execution state.
124 124 /// </summary>
125 125 /// <remarks>
126 126 /// Calling to this method may result unexpedted results if the component
127 127 /// isn't in the stopped state. Call this method after the component is
128 128 /// stopped if needed or if the component is in the failed state.
129 129 /// </remarks>
130 130 public void Dispose() {
131 131 bool dispose = false;
132 132 if (dispose) {
133 133 Dispose(true);
134 134 GC.SuppressFinalize(this);
135 135 }
136 136 }
137 137
138 138 ~RunnableComponent() {
139 139 Dispose(false);
140 140 }
141 141
142 142 /// <summary>
143 143 /// Releases all resources used by the current component regardless of its
144 144 /// execution state.
145 145 /// </summary>
146 146 /// <param name="disposing">Indicates that the component is disposed
147 147 /// during a normal disposing or during GC.</param>
148 148 protected virtual void Dispose(bool disposing) {
149 149 }
150 150
151 151 public void Initialize() {
152 152 var cookie = new object();
153 153 if (MoveInitialize(cookie))
154 154 ScheduleTask(InitializeInternalAsync, CancellationToken.None, cookie);
155 155 }
156 156
157 157 /// <summary>
158 158 /// This method is used for initialization during a component creation.
159 159 /// </summary>
160 160 /// <param name="ct">A cancellation token for this operation</param>
161 161 /// <remarks>
162 162 /// This method should be used for short and mostly syncronous operations,
163 163 /// other operations which require time to run shoud be placed in
164 /// <see cref="StartInternal(CancellationToken)"/> method.
164 /// <see cref="StartInternalAsync(CancellationToken)"/> method.
165 165 /// </remarks>
166 166 protected virtual Task InitializeInternalAsync(CancellationToken ct) {
167 167 return Task.CompletedTask;
168 168 }
169 169
170 170 public void Start(CancellationToken ct) {
171 171 var cookie = new object();
172 172 if (MoveStart(cookie))
173 ScheduleTask(StartInternal, ct, cookie);
173 ScheduleTask(StartInternalAsync, ct, cookie);
174 174 }
175 175
176 protected virtual Task StartInternal(CancellationToken ct) {
176 protected virtual Task StartInternalAsync(CancellationToken ct) {
177 177 return Task.CompletedTask;
178 178 }
179 179
180 180 public void Stop(CancellationToken ct) {
181 181 var cookie = new object();
182 182 if (MoveStop(cookie))
183 183 ScheduleTask(StopAsync, ct, cookie);
184 184 }
185 185
186 186 async Task StopAsync(CancellationToken ct) {
187 187 m_current.Cancel();
188 188 await Completion;
189 189
190 190 ct.ThrowIfCancellationRequested();
191 191
192 192 await StopInternalAsync(ct);
193 193 }
194 194
195 195 protected virtual Task StopInternalAsync(CancellationToken ct) {
196 196 return Task.CompletedTask;
197 197 }
198 198
199 199
200 200 #region state management
201 201
202 202 bool MoveInitialize(object cookie) {
203 203 lock (m_lock) {
204 204 if (State != ExecutionState.Created)
205 205 return false;
206 206 State = ExecutionState.Initializing;
207 207 m_cookie = cookie;
208 208 return true;
209 209 }
210 210 }
211 211
212 212 bool MoveStart(object cookie) {
213 213 lock (m_lock) {
214 214 if (State != ExecutionState.Ready)
215 215 return false;
216 216 State = ExecutionState.Starting;
217 217 m_cookie = cookie;
218 218 return true;
219 219 }
220 220 }
221 221
222 222 bool MoveStop(object cookie) {
223 223 lock (m_lock) {
224 224 if (State != ExecutionState.Starting && State != ExecutionState.Running)
225 225 return false;
226 226 State = ExecutionState.Stopping;
227 227 m_cookie = cookie;
228 228 return true;
229 229 }
230 230 }
231 231
232 232 void MoveSuccess(object cookie) {
233 233 lock (m_lock) {
234 234 if (m_cookie != cookie)
235 235 return;
236 236 switch (State) {
237 237 case ExecutionState.Initializing:
238 238 State = ExecutionState.Ready;
239 239 break;
240 240 case ExecutionState.Starting:
241 241 State = ExecutionState.Running;
242 242 break;
243 243 case ExecutionState.Stopping:
244 244 State = ExecutionState.Stopped;
245 245 break;
246 246 }
247 247 }
248 248 }
249 249
250 250 void MoveFailed(Exception err, object cookie) {
251 251 lock (m_lock) {
252 252 if (m_cookie != cookie)
253 253 return;
254 254 LastError = err;
255 255 State = ExecutionState.Failed;
256 256 }
257 257 }
258 258
259 259
260 260
261 261 protected async void ScheduleTask(Func<CancellationToken, Task> next, CancellationToken ct, object cookie) {
262 262 try {
263 263 m_current = AsyncOperationDescriptor.Create(next, ct);
264 264 await m_current.Task;
265 265 MoveSuccess(cookie);
266 266 } catch (Exception e) {
267 267 MoveFailed(e, cookie);
268 268 }
269 269 }
270 270
271 271 #endregion
272 272 }
273 273 } No newline at end of file
@@ -1,75 +1,73
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Diagnostics;
4 4 using System.Linq;
5 5 using System.Text;
6 6 using System.Threading.Tasks;
7 7
8 8 namespace Implab.Diagnostics {
9 9 public static class Trace<T> {
10 10
11 readonly static LogChannel<TraceEvent> _channel = new LogChannel<TraceEvent>(typeof(T).Name);
11 readonly static TraceSource _traceSource = new TraceSource(typeof(T).Name);
12 12
13 public static LogChannel<TraceEvent> Channel {
14 get { return _channel; }
13 public static TraceSource TraceSource {
14 get { return _traceSource; }
15 15 }
16 16
17 17 /// <summary>
18 18 /// Starts the logical operation nested to the current operation nested to the current one.
19 19 /// </summary>
20 20 [Conditional("TRACE")]
21 21 public static void StartLogicalOperation() {
22 TraceContext.Instance.StartLogicalOperation();
22 Trace.CorrelationManager.StartLogicalOperation();
23 23
24 24 }
25 25
26 26 /// <summary>
27 27 /// Starts the logical operation with the specified name, this name is usefull in logs.
28 28 /// </summary>
29 29 /// <param name="name">Name.</param>
30 30 [Conditional("TRACE")]
31 31 public static void StartLogicalOperation(string name) {
32 Channel.LogEvent(new TraceEvent(TraceContext.Instance.CurrentOperation, TraceEventType.OperationStarted, name));
33 TraceContext.Instance.StartLogicalOperation(name);
32 Trace.CorrelationManager.StartLogicalOperation();
34 33 }
35 34
36 35 /// <summary>
37 36 /// Ends the logical operation and restores the previous one.
38 37 /// </summary>
39 38 [Conditional("TRACE")]
40 public static void EndLogicalOperation() {
41 var op = TraceContext.Instance.EndLogicalOperation();
42 Channel.LogEvent(new TraceEvent(op, TraceEventType.OperationCompleted, String.Format("-{0} : {1}ms", op.Name, op.Duration)));
39 public static void StopLogicalOperation() {
40 Trace.CorrelationManager.StopLogicalOperation();
43 41 }
44 42
45 43 /// <summary>
46 44 /// Writes an informational message.
47 45 /// </summary>
48 46 /// <param name="format">Format.</param>
49 47 /// <param name="arguments">Arguments.</param>
50 48 [Conditional("TRACE")]
51 49 public static void Log(string format, params object[] arguments) {
52 Channel.LogEvent(TraceEvent.Create(TraceContext.Instance.CurrentOperation, TraceEventType.Information, format, arguments));
50 TraceSource.TraceEvent(TraceEventType.Information, 1, format, arguments);
53 51 }
54 52
55 53 /// <summary>
56 54 /// Writes a warning message.
57 55 /// </summary>
58 56 /// <param name="format">Format.</param>
59 57 /// <param name="arguments">Arguments.</param>
60 58 [Conditional("TRACE")]
61 59 public static void Warn(string format, params object[] arguments) {
62 Channel.LogEvent(TraceEvent.Create(TraceContext.Instance.CurrentOperation, TraceEventType.Warning, format, arguments));
60 TraceSource.TraceEvent(TraceEventType.Warning, 1, format, arguments);
63 61 }
64 62
65 63 [Conditional("TRACE")]
66 64 public static void Error(string format, params object[] arguments) {
67 Channel.LogEvent(TraceEvent.Create(TraceContext.Instance.CurrentOperation, TraceEventType.Error, format, arguments));
65 TraceSource.TraceEvent(TraceEventType.Error, 1, format, arguments);
68 66 }
69 67
70 68 [Conditional("TRACE")]
71 69 public static void Error(Exception err) {
72 Error("{0}", err);
70 TraceSource.TraceData(TraceEventType.Error, 1, err);
73 71 }
74 72 }
75 73 }
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now