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