92
|
1 using System;
|
|
2 using System.Collections.Generic;
|
|
3 using System.Threading;
|
|
4
|
|
5 namespace Implab.Diagnostics {
|
|
6 /// <summary>
|
|
7 /// Trace context is bound to the specific thread, each thread has it's own ThreadContext.
|
|
8 /// </summary>
|
|
9 /// <remarks>
|
|
10 /// ThreadContext manages relations between logical operations and threads.
|
|
11 /// </remarks>
|
|
12 public class TraceContext {
|
|
13
|
|
14 [ThreadStatic]
|
|
15 static TraceContext _instance;
|
|
16
|
|
17 OperationContext m_current = OperationContext.EMPTY;
|
|
18 readonly Stack<OperationContext> m_stack = new Stack<OperationContext>();
|
|
19 readonly int m_threadId;
|
|
20
|
|
21 public static TraceContext Instance {
|
|
22 get {
|
|
23 if (_instance == null)
|
|
24 _instance = new TraceContext();
|
|
25 return _instance;
|
|
26 }
|
|
27 }
|
|
28
|
|
29 public TraceContext() {
|
|
30 m_threadId = Thread.CurrentThread.ManagedThreadId;
|
|
31 }
|
|
32
|
|
33 public int ThreadId {
|
|
34 get { return m_threadId; }
|
|
35 }
|
|
36
|
|
37 public LogicalOperation CurrentOperation {
|
|
38 get {
|
|
39 return m_current.CurrentOperation;
|
|
40 }
|
|
41 }
|
|
42
|
|
43 public void EnterLogicalOperation(LogicalOperation operation, bool takeOwnership) {
|
94
|
44 var prev = CurrentOperation;
|
92
|
45 m_stack.Push(m_current);
|
|
46 m_current = new OperationContext(operation, takeOwnership);
|
94
|
47 LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(takeOwnership ? TraceEventType.Attach : TraceEventType.Enter, String.Format("{0} -> {1}",prev.Name, operation.Name)));
|
92
|
48 }
|
|
49
|
|
50 public void StartLogicalOperation(string name) {
|
|
51 m_current.BeginLogicalOperation(name);
|
93
|
52 LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.OperationStarted, String.Format("+{0}",CurrentOperation.Name)));
|
92
|
53 }
|
|
54
|
|
55 public void StartLogicalOperation() {
|
93
|
56 StartLogicalOperation(String.Empty);
|
92
|
57 }
|
|
58
|
|
59 public void EndLogicalOperation() {
|
93
|
60 LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.OperationCompleted, String.Format("-{0} : {1}ms",CurrentOperation.Name, CurrentOperation.Duration)));
|
92
|
61 m_current.EndLogicalOperation();
|
|
62 }
|
|
63
|
|
64 public LogicalOperation DetachLogicalOperation() {
|
94
|
65 var prev = m_current.DetachLogicalOperation();
|
|
66 LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.Detach, String.Format("{0} -> {1}",prev.Name, CurrentOperation.Name)));
|
|
67 return prev;
|
92
|
68 }
|
|
69
|
|
70 public void Leave() {
|
93
|
71 if (m_stack.Count > 0) {
|
|
72 m_current.Leave();
|
94
|
73 var prev = CurrentOperation;
|
92
|
74 m_current = m_stack.Pop();
|
94
|
75 LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.Leave, String.Format("{0} -> {1}", prev.Name, CurrentOperation.Name)));
|
93
|
76 } else {
|
92
|
77 TraceLog.TraceWarning("Attemtp to leave the last operation context");
|
|
78 m_current = OperationContext.EMPTY;
|
|
79 }
|
|
80 }
|
|
81 }
|
|
82 }
|
|
83
|