Auto status change to "Under Review"
@@ -0,0 +1,29 | |||||
|
1 | using System; | |||
|
2 | using System.Diagnostics; | |||
|
3 | ||||
|
4 | namespace Implab.Diagnostics { | |||
|
5 | public class ActivityScope : IDisposable { | |||
|
6 | readonly TraceSource m_source; | |||
|
7 | ||||
|
8 | readonly Guid m_prevId; | |||
|
9 | ||||
|
10 | readonly string m_activity; | |||
|
11 | ||||
|
12 | readonly int m_code; | |||
|
13 | ||||
|
14 | internal ActivityScope(TraceSource source, Guid prevId, int code, string activity) { | |||
|
15 | m_source = source; | |||
|
16 | m_prevId = prevId; | |||
|
17 | m_code = code; | |||
|
18 | m_activity = activity; | |||
|
19 | } | |||
|
20 | ||||
|
21 | ||||
|
22 | public void Dispose() { | |||
|
23 | if (Trace.CorrelationManager.ActivityId != m_prevId) | |||
|
24 | m_source.TraceTransfer(m_code, "Transfer", m_prevId); | |||
|
25 | m_source.TraceEvent(TraceEventType.Stop, 0, m_activity); | |||
|
26 | Trace.CorrelationManager.ActivityId = m_prevId; | |||
|
27 | } | |||
|
28 | } | |||
|
29 | } No newline at end of file |
@@ -0,0 +1,17 | |||||
|
1 | using System; | |||
|
2 | using System.Diagnostics; | |||
|
3 | ||||
|
4 | namespace Implab.Diagnostics { | |||
|
5 | public class LogicalOperation { | |||
|
6 | public Stopwatch OperationStopwatch { get; private set; } | |||
|
7 | ||||
|
8 | public string Name { get; private set; } | |||
|
9 | ||||
|
10 | internal LogicalOperation(string name) { | |||
|
11 | Name = string.IsNullOrEmpty(name) ? "<unnamed>" : name; | |||
|
12 | OperationStopwatch = Stopwatch.StartNew(); | |||
|
13 | } | |||
|
14 | ||||
|
15 | public override string ToString() => Name; | |||
|
16 | } | |||
|
17 | } No newline at end of file |
@@ -0,0 +1,21 | |||||
|
1 | using System; | |||
|
2 | using System.Diagnostics; | |||
|
3 | ||||
|
4 | namespace Implab.Diagnostics { | |||
|
5 | public class LogicalOperationScope : IDisposable { | |||
|
6 | readonly TraceSource m_source; | |||
|
7 | ||||
|
8 | readonly LogicalOperation m_operation; | |||
|
9 | ||||
|
10 | internal LogicalOperationScope(TraceSource source, LogicalOperation operation) { | |||
|
11 | m_source = source; | |||
|
12 | m_operation = operation; | |||
|
13 | } | |||
|
14 | ||||
|
15 | public void Dispose() { | |||
|
16 | m_operation.OperationStopwatch.Stop(); | |||
|
17 | Trace.CorrelationManager.StopLogicalOperation(); | |||
|
18 | m_source.TraceData(TraceEventType.Information, TraceEventCodes.StopLogicalOperation, m_operation); | |||
|
19 | } | |||
|
20 | } | |||
|
21 | } No newline at end of file |
@@ -0,0 +1,114 | |||||
|
1 | using System; | |||
|
2 | using System.Diagnostics; | |||
|
3 | using System.IO; | |||
|
4 | ||||
|
5 | namespace Implab.Diagnostics { | |||
|
6 | public class SimpleTraceListener : TextWriterTraceListener { | |||
|
7 | public SimpleTraceListener() { | |||
|
8 | } | |||
|
9 | ||||
|
10 | public SimpleTraceListener(Stream stream) : base(stream) { | |||
|
11 | } | |||
|
12 | ||||
|
13 | public SimpleTraceListener(TextWriter writer) : base(writer) { | |||
|
14 | } | |||
|
15 | ||||
|
16 | public SimpleTraceListener(string fileName) : base(fileName) { | |||
|
17 | } | |||
|
18 | ||||
|
19 | public SimpleTraceListener(Stream stream, string name) : base(stream, name) { | |||
|
20 | } | |||
|
21 | ||||
|
22 | public SimpleTraceListener(TextWriter writer, string name) : base(writer, name) { | |||
|
23 | } | |||
|
24 | ||||
|
25 | public SimpleTraceListener(string fileName, string name) : base(fileName, name) { | |||
|
26 | } | |||
|
27 | ||||
|
28 | public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data) { | |||
|
29 | switch (id) { | |||
|
30 | case TraceEventCodes.StartLogicalOperation: | |||
|
31 | TraceEvent(eventCache, source, eventType, id, "+{0}", data); | |||
|
32 | break; | |||
|
33 | case TraceEventCodes.StopLogicalOperation: | |||
|
34 | TraceEvent(eventCache, source, eventType, id, FormatStopLogicalOperation(data)); | |||
|
35 | break; | |||
|
36 | default: | |||
|
37 | TraceEvent(eventCache, source, eventType, id, data?.ToString()); | |||
|
38 | break; | |||
|
39 | } | |||
|
40 | } | |||
|
41 | ||||
|
42 | string FormatStopLogicalOperation(object data) { | |||
|
43 | if (data is LogicalOperation op) { | |||
|
44 | return string.Format("-{0} ({1})", op, FormatTimespan(op.OperationStopwatch.Elapsed)); | |||
|
45 | } else { | |||
|
46 | return data?.ToString(); | |||
|
47 | } | |||
|
48 | } | |||
|
49 | ||||
|
50 | string FormatTimespan(TimeSpan value) { | |||
|
51 | if (value.TotalSeconds < 10) { | |||
|
52 | return value.Milliseconds.ToString() + "ms"; | |||
|
53 | } else if (value.TotalSeconds < 30) { | |||
|
54 | return string.Format("{0:0.###}s", value.TotalSeconds); | |||
|
55 | } else { | |||
|
56 | return value.ToString(); | |||
|
57 | } | |||
|
58 | } | |||
|
59 | ||||
|
60 | public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data) { | |||
|
61 | var prev = IndentLevel; | |||
|
62 | IndentLevel += eventCache.LogicalOperationStack.Count; | |||
|
63 | try { | |||
|
64 | base.TraceData(eventCache, source, eventType, id, data); | |||
|
65 | } finally { | |||
|
66 | IndentLevel = prev; | |||
|
67 | } | |||
|
68 | } | |||
|
69 | ||||
|
70 | public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id) { | |||
|
71 | var prev = IndentLevel; | |||
|
72 | IndentLevel += eventCache.LogicalOperationStack.Count; | |||
|
73 | try { | |||
|
74 | base.TraceEvent(eventCache, source, eventType, id); | |||
|
75 | } finally { | |||
|
76 | IndentLevel = prev; | |||
|
77 | } | |||
|
78 | } | |||
|
79 | ||||
|
80 | public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args) { | |||
|
81 | TraceEvent(eventCache, source, eventType, id, String.Format(format, args)); | |||
|
82 | } | |||
|
83 | ||||
|
84 | public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message) { | |||
|
85 | var prev = IndentLevel; | |||
|
86 | IndentLevel += eventCache.LogicalOperationStack.Count; | |||
|
87 | try { | |||
|
88 | LogicalOperation operation = null; | |||
|
89 | if (eventCache.LogicalOperationStack.Count > 0) | |||
|
90 | operation = eventCache.LogicalOperationStack.Peek() as LogicalOperation; | |||
|
91 | ||||
|
92 | if (operation != null) { | |||
|
93 | base.TraceData(eventCache, source, eventType, id, FormatTimespan(operation.OperationStopwatch.Elapsed) + ": " + message); | |||
|
94 | } else { | |||
|
95 | base.TraceData(eventCache, source, eventType, id, message); | |||
|
96 | } | |||
|
97 | } finally { | |||
|
98 | IndentLevel = prev; | |||
|
99 | } | |||
|
100 | } | |||
|
101 | ||||
|
102 | public override void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId) { | |||
|
103 | var prev = IndentLevel; | |||
|
104 | IndentLevel += eventCache.LogicalOperationStack.Count; | |||
|
105 | try { | |||
|
106 | base.TraceTransfer(eventCache, source, id, message, relatedActivityId); | |||
|
107 | } finally { | |||
|
108 | IndentLevel = prev; | |||
|
109 | } | |||
|
110 | } | |||
|
111 | ||||
|
112 | ||||
|
113 | } | |||
|
114 | } No newline at end of file |
@@ -0,0 +1,10 | |||||
|
1 | namespace Implab.Diagnostics { | |||
|
2 | public class TraceEventCodes { | |||
|
3 | public const int EventCodesBase = 1024; | |||
|
4 | ||||
|
5 | public const int StartLogicalOperation = EventCodesBase + 1; | |||
|
6 | ||||
|
7 | public const int StopLogicalOperation = EventCodesBase + 2; | |||
|
8 | ||||
|
9 | } | |||
|
10 | } No newline at end of file |
@@ -1,37 +1,29 | |||||
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 Implab.Diagnostics; | |
5 | using Xunit; |
|
5 | using Xunit; | |
6 |
|
6 | |||
7 | namespace Implab.Test |
|
7 | namespace Implab.Test { | |
8 | { |
|
8 | using System.Threading.Tasks; | |
9 | using static Trace<UnitTest1>; |
|
9 | using static Trace<UnitTest1>; | |
10 | public class UnitTest1 |
|
10 | public class UnitTest1 { | |
11 | { |
|
|||
12 | [Fact] |
|
11 | [Fact] | |
13 |
public |
|
12 | public async Task Test1() { | |
14 | { |
|
13 | var listener = new SimpleTraceListener(Console.Out); | |
15 | var listener = new TextWriterTraceListener(Console.Out); |
|
14 | ||
16 | var source = TraceSource; |
|
15 | var source = TraceSource; | |
17 | source.Switch.Level = SourceLevels.All; |
|
16 | source.Switch.Level = SourceLevels.All; | |
18 |
|
17 | |||
19 | source.Listeners.Add(listener); |
|
18 | source.Listeners.Add(listener); | |
20 | Trace.Listeners.Add(listener); |
|
|||
21 |
|
19 | |||
22 | Trace.WriteLine("Hello!"); |
|
20 | using (var op = LogicalOperation(nameof(Test1))) | |
23 |
|
|
21 | using (LogicalOperation("InnerOperation")){ | |
24 |
|
22 | await Task.Yield(); | ||
25 |
|
|
23 | Log("Inner"); | |
26 | foreach(var x in Trace.CorrelationManager.LogicalOperationStack) |
|
24 | await Task.Yield(); | |
27 | Trace.WriteLine($"-{x}"); |
|
25 | Log("source event"); | |
28 | Log("source event"); |
|
26 | } | |
29 |
|
||||
30 | listener.IndentLevel = 1; |
|
|||
31 |
|
||||
32 | source.TraceData(TraceEventType.Start, 1, DateTime.Now); |
|
|||
33 |
|
||||
34 | StopLogicalOperation(); |
|
|||
35 | } |
|
27 | } | |
36 | } |
|
28 | } | |
37 | } |
|
29 | } |
@@ -1,130 +1,130 | |||||
1 | using System; |
|
1 | using System; | |
2 | using Implab.Parallels; |
|
2 | using Implab.Parallels; | |
3 | using System.Threading; |
|
3 | using System.Threading; | |
4 | using System.Reflection; |
|
4 | using System.Reflection; | |
5 | using System.Diagnostics; |
|
5 | using System.Diagnostics; | |
6 |
|
6 | |||
7 | namespace Implab { |
|
7 | namespace Implab { | |
8 | /// <summary> |
|
8 | /// <summary> | |
9 | /// Abstract class for creation of custom one-shot thread safe events. |
|
9 | /// Abstract class for creation of custom one-shot thread safe events. | |
10 | /// </summary> |
|
10 | /// </summary> | |
11 | /// <remarks> |
|
11 | /// <remarks> | |
12 | /// <para> |
|
12 | /// <para> | |
13 | /// An event is something that should happen in the future and the |
|
13 | /// An event is something that should happen in the future and the | |
14 | /// triggering of the event causes execution of some pending actions |
|
14 | /// triggering of the event causes execution of some pending actions | |
15 | /// which are formely event handlers. One-shot events occur only once |
|
15 | /// which are formely event handlers. One-shot events occur only once | |
16 | /// and any handler added after the event is triggered should run |
|
16 | /// and any handler added after the event is triggered should run | |
17 | /// without a delay. |
|
17 | /// without a delay. | |
18 | /// </para> |
|
18 | /// </para> | |
19 | /// <para> |
|
19 | /// <para> | |
20 | /// The lifecycle of the one-shot event is tipically consists of following |
|
20 | /// The lifecycle of the one-shot event is tipically consists of following | |
21 | /// phases. |
|
21 | /// phases. | |
22 | /// <list> |
|
22 | /// <list> | |
23 | /// <description>Pending state. This is the initial state of the event. Any |
|
23 | /// <description>Pending state. This is the initial state of the event. Any | |
24 | /// handler added to the event will be queued for the future execution. |
|
24 | /// handler added to the event will be queued for the future execution. | |
25 | /// </description> |
|
25 | /// </description> | |
26 | /// <description>Transitional state. This is intermediate state between pending |
|
26 | /// <description>Transitional state. This is intermediate state between pending | |
27 | /// and fulfilled states, during this state internal initialization and storing |
|
27 | /// and fulfilled states, during this state internal initialization and storing | |
28 | /// of the result occurs. |
|
28 | /// of the result occurs. | |
29 | /// </description> |
|
29 | /// </description> | |
30 | /// <description>Fulfilled state. The event contains the result, all queued |
|
30 | /// <description>Fulfilled state. The event contains the result, all queued | |
31 | /// handlers are signalled to run and newly added handlers are executed |
|
31 | /// handlers are signalled to run and newly added handlers are executed | |
32 | /// immediatelly. |
|
32 | /// immediatelly. | |
33 | /// </description> |
|
33 | /// </description> | |
34 | /// </list> |
|
34 | /// </list> | |
35 | /// </para> |
|
35 | /// </para> | |
36 | /// </remarks> |
|
36 | /// </remarks> | |
37 | public abstract class AbstractEvent<THandler> where THandler : class { |
|
37 | public abstract class AbstractEvent<THandler> where THandler : class { | |
38 | const int PendingState = 0; |
|
38 | const int PendingState = 0; | |
39 |
|
39 | |||
40 | const int TransitionalState = 1; |
|
40 | const int TransitionalState = 1; | |
41 |
|
41 | |||
42 | const int ResolvedState = 2; |
|
42 | const int ResolvedState = 2; | |
43 |
|
43 | |||
44 | volatile int m_state; |
|
44 | volatile int m_state; | |
45 |
|
45 | |||
46 | THandler m_handler; |
|
46 | THandler m_handler; | |
47 | SimpleAsyncQueue<THandler> m_extraHandlers; |
|
47 | SimpleAsyncQueue<THandler> m_extraHandlers; | |
48 |
|
48 | |||
49 | public bool IsResolved { |
|
49 | public bool IsResolved { | |
50 | get { |
|
50 | get { | |
51 | return m_state > TransitionalState; |
|
51 | return m_state > TransitionalState; | |
52 | } |
|
52 | } | |
53 | } |
|
53 | } | |
54 |
|
54 | |||
55 | #region state managment |
|
55 | #region state managment | |
56 | protected bool BeginTransit() { |
|
56 | protected bool BeginTransit() { | |
57 | return PendingState == Interlocked.CompareExchange(ref m_state, TransitionalState, PendingState); |
|
57 | return PendingState == Interlocked.CompareExchange(ref m_state, TransitionalState, PendingState); | |
58 | } |
|
58 | } | |
59 |
|
59 | |||
60 | protected void CompleteTransit() { |
|
60 | protected void CompleteTransit() { | |
61 | #if DEBUG |
|
61 | #if DEBUG | |
62 | if (TransitionalState != Interlocked.CompareExchange(ref m_state, ResolvedState, TransitionalState)) |
|
62 | if (TransitionalState != Interlocked.CompareExchange(ref m_state, ResolvedState, TransitionalState)) | |
63 | throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state"); |
|
63 | throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state"); | |
64 | #else |
|
64 | #else | |
65 | m_state = state; |
|
65 | m_state = ResolvedState; | |
66 | #endif |
|
66 | #endif | |
67 | Signal(); |
|
67 | Signal(); | |
68 | } |
|
68 | } | |
69 |
|
69 | |||
70 | protected void WaitTransition() { |
|
70 | protected void WaitTransition() { | |
71 | if (m_state == TransitionalState) { |
|
71 | if (m_state == TransitionalState) { | |
72 | SpinWait spin = new SpinWait(); |
|
72 | SpinWait spin = new SpinWait(); | |
73 | do { |
|
73 | do { | |
74 | spin.SpinOnce(); |
|
74 | spin.SpinOnce(); | |
75 | } while (m_state == TransitionalState); |
|
75 | } while (m_state == TransitionalState); | |
76 | } |
|
76 | } | |
77 | } |
|
77 | } | |
78 |
|
78 | |||
79 |
|
79 | |||
80 | protected abstract void SignalHandler(THandler handler); |
|
80 | protected abstract void SignalHandler(THandler handler); | |
81 |
|
81 | |||
82 | void Signal() { |
|
82 | void Signal() { | |
83 | THandler handler; |
|
83 | THandler handler; | |
84 | while (TryDequeueHandler(out handler)) |
|
84 | while (TryDequeueHandler(out handler)) | |
85 | SignalHandler(handler); |
|
85 | SignalHandler(handler); | |
86 | } |
|
86 | } | |
87 |
|
87 | |||
88 | #endregion |
|
88 | #endregion | |
89 |
|
89 | |||
90 | #region handlers managment |
|
90 | #region handlers managment | |
91 |
|
91 | |||
92 | protected void AddHandler(THandler handler) { |
|
92 | protected void AddHandler(THandler handler) { | |
93 |
|
93 | |||
94 | if (IsResolved) { |
|
94 | if (IsResolved) { | |
95 | // the promise is in the resolved state, just invoke the handler |
|
95 | // the promise is in the resolved state, just invoke the handler | |
96 | SignalHandler(handler); |
|
96 | SignalHandler(handler); | |
97 | } else { |
|
97 | } else { | |
98 | EnqueueHandler(handler); |
|
98 | EnqueueHandler(handler); | |
99 |
|
99 | |||
100 | if (IsResolved && TryDequeueHandler(out handler)) |
|
100 | if (IsResolved && TryDequeueHandler(out handler)) | |
101 | // if the promise have been resolved while we was adding the handler to the queue |
|
101 | // if the promise have been resolved while we was adding the handler to the queue | |
102 | // we can't guarantee that someone is still processing it |
|
102 | // we can't guarantee that someone is still processing it | |
103 | // therefore we need to fetch a handler from the queue and execute it |
|
103 | // therefore we need to fetch a handler from the queue and execute it | |
104 | // note that fetched handler may be not the one that we have added |
|
104 | // note that fetched handler may be not the one that we have added | |
105 | // even we can fetch no handlers at all :) |
|
105 | // even we can fetch no handlers at all :) | |
106 | SignalHandler(handler); |
|
106 | SignalHandler(handler); | |
107 | } |
|
107 | } | |
108 |
|
108 | |||
109 | } |
|
109 | } | |
110 |
|
110 | |||
111 | void EnqueueHandler(THandler handler) { |
|
111 | void EnqueueHandler(THandler handler) { | |
112 | if (Interlocked.CompareExchange(ref m_handler, handler, null) != null) { |
|
112 | if (Interlocked.CompareExchange(ref m_handler, handler, null) != null) { | |
113 | if (m_extraHandlers == null) |
|
113 | if (m_extraHandlers == null) | |
114 | // compare-exchange will protect from loosing already created queue |
|
114 | // compare-exchange will protect from loosing already created queue | |
115 | Interlocked.CompareExchange(ref m_extraHandlers, new SimpleAsyncQueue<THandler>(), null); |
|
115 | Interlocked.CompareExchange(ref m_extraHandlers, new SimpleAsyncQueue<THandler>(), null); | |
116 | m_extraHandlers.Enqueue(handler); |
|
116 | m_extraHandlers.Enqueue(handler); | |
117 | } |
|
117 | } | |
118 | } |
|
118 | } | |
119 |
|
119 | |||
120 | bool TryDequeueHandler(out THandler handler) { |
|
120 | bool TryDequeueHandler(out THandler handler) { | |
121 | handler = Interlocked.Exchange(ref m_handler, null); |
|
121 | handler = Interlocked.Exchange(ref m_handler, null); | |
122 | if (handler != null) |
|
122 | if (handler != null) | |
123 | return true; |
|
123 | return true; | |
124 | return m_extraHandlers != null && m_extraHandlers.TryDequeue(out handler); |
|
124 | return m_extraHandlers != null && m_extraHandlers.TryDequeue(out handler); | |
125 | } |
|
125 | } | |
126 |
|
126 | |||
127 | #endregion |
|
127 | #endregion | |
128 | } |
|
128 | } | |
129 | } |
|
129 | } | |
130 |
|
130 |
@@ -1,73 +1,127 | |||||
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 TraceSource _traceSource = new TraceSource(typeof(T).Name); |
|
11 | readonly static TraceSource _traceSource = new TraceSource(typeof(T).Name); | |
12 |
|
12 | |||
13 | public static TraceSource TraceSource { |
|
13 | public static TraceSource TraceSource { | |
14 | get { return _traceSource; } |
|
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 | Trace.CorrelationManager.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 | Trace.CorrelationManager.StartLogicalOperation(); |
|
32 | Trace.CorrelationManager.StartLogicalOperation(name); | |
33 | } |
|
33 | } | |
34 |
|
34 | |||
35 | /// <summary> |
|
35 | /// <summary> | |
36 | /// Ends the logical operation and restores the previous one. |
|
36 | /// Ends the logical operation and restores the previous one. | |
37 | /// </summary> |
|
37 | /// </summary> | |
38 | [Conditional("TRACE")] |
|
38 | [Conditional("TRACE")] | |
39 | public static void StopLogicalOperation() { |
|
39 | public static void StopLogicalOperation() { | |
40 | Trace.CorrelationManager.StopLogicalOperation(); |
|
40 | Trace.CorrelationManager.StopLogicalOperation(); | |
41 | } |
|
41 | } | |
42 |
|
42 | |||
43 | /// <summary> |
|
43 | /// <summary> | |
44 | /// Writes an informational message. |
|
44 | /// Writes an informational message. | |
45 | /// </summary> |
|
45 | /// </summary> | |
46 | /// <param name="format">Format.</param> |
|
46 | /// <param name="format">Format.</param> | |
47 | /// <param name="arguments">Arguments.</param> |
|
47 | /// <param name="arguments">Arguments.</param> | |
48 | [Conditional("TRACE")] |
|
48 | [Conditional("TRACE")] | |
49 | public static void Log(string format, params object[] arguments) { |
|
49 | public static void Log(string format, params object[] arguments) { | |
50 |
TraceSource.TraceEvent(TraceEventType.Information, |
|
50 | TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments); | |
51 | } |
|
51 | } | |
52 |
|
52 | |||
53 | /// <summary> |
|
53 | /// <summary> | |
54 | /// Writes a warning message. |
|
54 | /// Writes a warning message. | |
55 | /// </summary> |
|
55 | /// </summary> | |
56 | /// <param name="format">Format.</param> |
|
56 | /// <param name="format">Format.</param> | |
57 | /// <param name="arguments">Arguments.</param> |
|
57 | /// <param name="arguments">Arguments.</param> | |
58 | [Conditional("TRACE")] |
|
58 | [Conditional("TRACE")] | |
59 | public static void Warn(string format, params object[] arguments) { |
|
59 | public static void Warn(string format, params object[] arguments) { | |
60 |
TraceSource.TraceEvent(TraceEventType.Warning, |
|
60 | TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments); | |
61 | } |
|
61 | } | |
62 |
|
62 | |||
63 | [Conditional("TRACE")] |
|
63 | [Conditional("TRACE")] | |
64 | public static void Error(string format, params object[] arguments) { |
|
64 | public static void Error(string format, params object[] arguments) { | |
65 |
TraceSource.TraceEvent(TraceEventType.Error, |
|
65 | TraceSource.TraceEvent(TraceEventType.Error, 0, format, arguments); | |
66 | } |
|
66 | } | |
67 |
|
67 | |||
68 | [Conditional("TRACE")] |
|
68 | [Conditional("TRACE")] | |
69 | public static void Error(Exception err) { |
|
69 | public static void Error(Exception err) { | |
70 |
TraceSource.TraceData(TraceEventType.Error, |
|
70 | TraceSource.TraceData(TraceEventType.Error, 0, err); | |
|
71 | } | |||
|
72 | ||||
|
73 | /// <summary> | |||
|
74 | /// This method save the current activity, and transfers to the specified activity, | |||
|
75 | /// emits <see cref="TraceEventType.Start"/> and returns a scope of the new | |||
|
76 | /// activity. | |||
|
77 | /// </summary> | |||
|
78 | /// <param name="activityName">The name of the new activity/</param> | |||
|
79 | /// <param name="activityId">The identifier of the activity to which | |||
|
80 | /// the control will be transferred</param> | |||
|
81 | /// <returns>A scope of the new activity, dispose it to transfer | |||
|
82 | /// the control back to the original activity.</returns> | |||
|
83 | public static ActivityScope TransferActivity(string activityName, Guid activityId) { | |||
|
84 | var prev = Trace.CorrelationManager.ActivityId; | |||
|
85 | ||||
|
86 | TraceSource.TraceTransfer(0, "Transfer", activityId); | |||
|
87 | Trace.CorrelationManager.ActivityId = activityId; | |||
|
88 | TraceSource.TraceEvent(TraceEventType.Start, 0, activityName); | |||
|
89 | ||||
|
90 | return new ActivityScope(TraceSource, prev, 0, activityName); | |||
|
91 | } | |||
|
92 | ||||
|
93 | /// <summary> | |||
|
94 | /// Emits <see cref="TraceEventType.Start"/> and returns a scope of the | |||
|
95 | /// activity. | |||
|
96 | /// </summary> | |||
|
97 | /// <param name="activityName">The name of the activity to start</param> | |||
|
98 | /// <returns>A scope of the new activity, dispose it to emit | |||
|
99 | /// <see cref="TraceEventType.Stop"/> for the current activity.</returns> | |||
|
100 | public static ActivityScope StartActivity(string activityName) { | |||
|
101 | if (Trace.CorrelationManager.ActivityId == Guid.Empty) | |||
|
102 | Trace.CorrelationManager.ActivityId = Guid.NewGuid(); | |||
|
103 | ||||
|
104 | var prev = Trace.CorrelationManager.ActivityId; | |||
|
105 | ||||
|
106 | TraceSource.TraceEvent(TraceEventType.Start, 0, activityName); | |||
|
107 | return new ActivityScope(TraceSource, prev, 0, activityName); | |||
|
108 | } | |||
|
109 | ||||
|
110 | /// <summary> | |||
|
111 | /// Creates new <see cref="LogicalOperation(string)"/> and calls | |||
|
112 | /// to <see cref="CorrelationManager.StartLogicalOperation(object)"/> | |||
|
113 | /// passing the created operation as identity. Calls | |||
|
114 | /// <see cref="TraceSource.TraceData(TraceEventType, int, object)"/> | |||
|
115 | /// to notify listeners on operation start. | |||
|
116 | /// </summary> | |||
|
117 | /// <param name="name">The name of the logical operation.</param> | |||
|
118 | /// <returns>Logical operation scope, disposing it will stop | |||
|
119 | /// logical operation and notify trace listeners.</returns> | |||
|
120 | public static LogicalOperationScope LogicalOperation(string name) { | |||
|
121 | var operation = new LogicalOperation(name); | |||
|
122 | TraceSource.TraceData(TraceEventType.Information, TraceEventCodes.StartLogicalOperation, operation); | |||
|
123 | Trace.CorrelationManager.StartLogicalOperation(operation); | |||
|
124 | return new LogicalOperationScope(TraceSource, operation); | |||
71 | } |
|
125 | } | |
72 | } |
|
126 | } | |
73 | } |
|
127 | } |
@@ -1,8 +1,18 | |||||
1 | <Project Sdk="Microsoft.NET.Sdk"> |
|
1 | <Project Sdk="Microsoft.NET.Sdk"> | |
2 |
|
2 | |||
3 | <PropertyGroup> |
|
3 | <PropertyGroup> | |
|
4 | <Authors>Sergey Smirnov</Authors> | |||
|
5 | <Title>Implab library</Title> | |||
|
6 | <Description>Provides some helper clesses like XML serialization helpers, JSON XML reader, | |||
|
7 | JSON pull-parser, ECMA-style promises, lightweight synchonization routines Signal | |||
|
8 | and SharedLock, Trace helpers on top of System.Diagnostics, ObjectPool etc. | |||
|
9 | </Description> | |||
|
10 | <Copyright>2012-2018 Sergey Smirnov</Copyright> | |||
|
11 | <LicenseUrl>https://opensource.org/licenses/BSD-2-Clause</LicenseUrl> | |||
|
12 | <ProjectUrl>https://implab.org</ProjectUrl> | |||
|
13 | <RepositoryUrl>https://hg.implab.org/pub/ImplabNet/</RepositoryUrl> | |||
4 | <TargetFrameworks>netstandard2.0;net45</TargetFrameworks> |
|
14 | <TargetFrameworks>netstandard2.0;net45</TargetFrameworks> | |
5 | <FrameworkPathOverride Condition="'$(TargetFramework)'=='net45' and '$(OSTYPE)'=='linux'">/usr/lib/mono/4.5/</FrameworkPathOverride> |
|
15 | <FrameworkPathOverride Condition="'$(TargetFramework)'=='net45' and '$(OSTYPE)'=='linux'">/usr/lib/mono/4.5/</FrameworkPathOverride> | |
6 | </PropertyGroup> |
|
16 | </PropertyGroup> | |
7 |
|
17 | |||
8 | </Project> |
|
18 | </Project> |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now