##// END OF EJS Templates
Improved logging
cin -
r134:04d4c92d0f28 v2
parent child
Show More
@@ -0,0 +1,8
1 using System;
2
3 namespace Implab.Diagnostics {
4 public interface ILogWriter<in TEvent> {
5 void Write(LogEventArgs args, TEvent entry);
6 }
7 }
8
@@ -0,0 +1,87
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Implab.Diagnostics {
7 public abstract class ListenerBase : ServiceLocator, ILogWriter<object>, ILogWriter<TraceEvent> {
8
9 readonly Dictionary<object, Action> m_subscriptions = new Dictionary<object, Action>();
10
11 protected ListenerBase() {
12 Register(this);
13 }
14
15 public void Subscribe(Type eventType) {
16 if (eventType == null)
17 throw new ArgumentNullException("eventType");
18 GetType().GetMethod("Subscribe", new Type[0]).MakeGenericMethod(eventType).Invoke(this, null);
19 }
20
21 public void Subscribe<TEvent>() {
22 Subscribe<TEvent>(LogChannel<TEvent>.Default);
23 }
24
25 public void Subscribe<TEvent>(LogChannel<TEvent> channel) {
26 if (channel == null)
27 throw new ArgumentNullException("channel");
28
29 lock (m_subscriptions) {
30 AssertNotDisposed();
31 if (m_subscriptions.ContainsKey(channel))
32 return;
33
34 var writer = GetService<ILogWriter<TEvent>>();
35
36 EventHandler<LogEventArgs<TEvent>> handler = (sender, args) => writer.Write(args,args.Value);
37
38 channel.Events += handler;
39
40 Action unsubscribe = () => {
41 channel.Events -= handler;
42 };
43
44 m_subscriptions.Add(channel, unsubscribe);
45 }
46 }
47
48 public void Unsubscribe<TEvent>(LogChannel<TEvent> channel) {
49 if (channel == null)
50 throw new ArgumentNullException("channel");
51
52 lock (m_subscriptions) {
53 Action subscription;
54 if (m_subscriptions.TryGetValue(channel, out subscription)) {
55 subscription();
56 m_subscriptions.Remove(channel);
57 }
58 }
59 }
60
61 public void UnsubscribeAll() {
62 lock (m_subscriptions) {
63 foreach (var subscription in m_subscriptions.Values)
64 subscription();
65 m_subscriptions.Clear();
66 }
67 }
68
69 #region ILogWriter implementation
70 public abstract void Write(LogEventArgs args, object entry);
71 #endregion
72
73 #region ILogWriter implementation
74 public virtual void Write(LogEventArgs args, TraceEvent entry) {
75 Write(args, (object)entry);
76 }
77 #endregion
78
79
80 protected override void Dispose(bool disposing) {
81 base.Dispose(disposing);
82 if (disposing) {
83 UnsubscribeAll();
84 }
85 }
86 }
87 }
@@ -9,7 +9,7 using System.Windows.Forms;
9
9
10 namespace Implab.Diagnostics.Interactive
10 namespace Implab.Diagnostics.Interactive
11 {
11 {
12 public class InteractiveListener: TextListenerBase
12 public class InteractiveListener: ListenerBase
13 {
13 {
14 TraceForm m_form;
14 TraceForm m_form;
15
15
@@ -29,7 +29,7 namespace Implab.Diagnostics.Interactive
29 bool m_paused;
29 bool m_paused;
30 readonly ManualResetEvent m_pauseEvent = new ManualResetEvent(true);
30 readonly ManualResetEvent m_pauseEvent = new ManualResetEvent(true);
31
31
32 public InteractiveListener(bool global) : base(global) {
32 public InteractiveListener() {
33 m_guiFinished = AsyncPool.RunThread(GuiThread);
33 m_guiFinished = AsyncPool.RunThread(GuiThread);
34 /*m_workerFinished = */AsyncPool.RunThread(QueueThread);
34 /*m_workerFinished = */AsyncPool.RunThread(QueueThread);
35
35
@@ -107,12 +107,12 namespace Implab.Diagnostics.Interactive
107 base.Dispose(disposing);
107 base.Dispose(disposing);
108 }
108 }
109
109
110 protected override void WriteEntry(LogEventArgs args, EventText text, string channel) {
110 public override void Write(LogEventArgs args, object entry) {
111 var item = new TraceViewItem {
111 var item = new TraceViewItem {
112 Indent = text.indent,
112 Indent = args.Operation.Level,
113 Message = text.content,
113 Message = entry.ToString(),
114 Thread = args.ThreadId,
114 Thread = args.ThreadId,
115 Channel = channel,
115 Channel = args.ChannelName,
116 Timestamp = Environment.TickCount
116 Timestamp = Environment.TickCount
117 };
117 };
118
118
@@ -1,29 +1,17
1 using System;
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
2 using System.Text;
5
3
6 namespace Implab.Diagnostics {
4 namespace Implab.Diagnostics {
7 public class ConsoleTraceListener: TextListenerBase {
5 public class ConsoleTraceListener: ListenerBase {
8
6
9 static readonly object _consoleLock = new object();
7 static readonly object _consoleLock = new object();
10
8
11 public ConsoleTraceListener()
9 public override void Write(LogEventArgs args, object entry) {
12 : base(true) {
13
14 }
15
16 public ConsoleTraceListener(bool global)
17 : base(global) {
18
19 }
20
21 protected override void WriteEntry(LogEventArgs args, EventText text, string channel) {
22 var msg = new StringBuilder();
10 var msg = new StringBuilder();
23
11
24 for (int i = 0; i < text.indent; i++)
12 for (int i = 0; i < args.Operation.Level; i++)
25 msg.Append(" ");
13 msg.Append(" ");
26 msg.AppendFormat("[{0}]: {1}", args.ThreadId, text.content);
14 msg.AppendFormat("[{0}]: {1}", args.ThreadId, entry);
27
15
28 lock (_consoleLock) {
16 lock (_consoleLock) {
29 Console.ForegroundColor = (ConsoleColor)(args.ThreadId % 15 + 1);
17 Console.ForegroundColor = (ConsoleColor)(args.ThreadId % 15 + 1);
@@ -1,6 +1,4
1 using System;
1 namespace Implab.Diagnostics {
2
3 namespace Implab.Diagnostics {
4 public static class Extensions {
2 public static class Extensions {
5 public static IPromise<T> EndLogicalOperation<T>(this IPromise<T> promise) {
3 public static IPromise<T> EndLogicalOperation<T>(this IPromise<T> promise) {
6 Safe.ArgumentNotNull(promise, "promise");
4 Safe.ArgumentNotNull(promise, "promise");
@@ -69,6 +69,7 namespace Implab.Diagnostics {
69 this,
69 this,
70 new LogEventArgs<TEvent>(
70 new LogEventArgs<TEvent>(
71 data,
71 data,
72 Name,
72 traceContext.ThreadId,
73 traceContext.ThreadId,
73 traceContext.CurrentOperation,
74 traceContext.CurrentOperation,
74 traceContext.CurrentOperation.Duration
75 traceContext.CurrentOperation.Duration
@@ -2,6 +2,10
2
2
3 namespace Implab.Diagnostics {
3 namespace Implab.Diagnostics {
4 public class LogEventArgs : EventArgs {
4 public class LogEventArgs : EventArgs {
5 public string ChannelName {
6 get;
7 private set;
8 }
5 public int ThreadId {
9 public int ThreadId {
6 get;
10 get;
7 private set;
11 private set;
@@ -14,7 +18,8 namespace Implab.Diagnostics {
14 get;
18 get;
15 private set;
19 private set;
16 }
20 }
17 public LogEventArgs(int threadId, LogicalOperation operation, int timeOffset) {
21 public LogEventArgs(string channelName, int threadId, LogicalOperation operation, int timeOffset) {
22 ChannelName = channelName;
18 ThreadId = threadId;
23 ThreadId = threadId;
19 Operation = operation;
24 Operation = operation;
20 OperationTimeOffset = timeOffset;
25 OperationTimeOffset = timeOffset;
@@ -5,7 +5,7
5 private set;
5 private set;
6 }
6 }
7
7
8 public LogEventArgs(TEvent value, int threadId, LogicalOperation operation, int timeOffset) : base(threadId, operation, timeOffset) {
8 public LogEventArgs(TEvent value,string channelName, int threadId, LogicalOperation operation, int timeOffset) : base(channelName, threadId, operation, timeOffset) {
9 Value = value;
9 Value = value;
10 }
10 }
11 }
11 }
@@ -1,9 +1,10
1 namespace Implab.Diagnostics {
1 namespace Implab.Diagnostics {
2 struct OperationContext {
2 struct OperationContext {
3 readonly LogicalOperation m_initial;
4 public readonly static OperationContext EMPTY = new OperationContext(LogicalOperation.EMPTY, false);
3 public readonly static OperationContext EMPTY = new OperationContext(LogicalOperation.EMPTY, false);
4
5 LogicalOperation m_initial;
5 LogicalOperation m_current;
6 LogicalOperation m_current;
6 readonly bool m_ownership;
7 bool m_ownership;
7
8
8 public OperationContext(LogicalOperation operation, bool ownership) {
9 public OperationContext(LogicalOperation operation, bool ownership) {
9 Safe.ArgumentNotNull(operation, "operation");
10 Safe.ArgumentNotNull(operation, "operation");
@@ -39,14 +40,19
39 return detached;
40 return detached;
40 }
41 }
41
42
42 public void EndLogicalOperation() {
43 public LogicalOperation EndLogicalOperation() {
43 if (m_current != m_initial) {
44 var current = m_current;
45 if (m_current != LogicalOperation.EMPTY && (m_current != m_initial || m_ownership)) {
44 m_current = m_current.Parent;
46 m_current = m_current.Parent;
45 } else if (m_current != LogicalOperation.EMPTY && m_ownership) {
47 if (current == m_initial) {
46 m_current = LogicalOperation.EMPTY;
48 // we have complete the owned operation
49 m_initial = m_current;
50 m_ownership = false;
51 }
47 } else {
52 } else {
48 TraceLog.TraceWarning("EndLogicalOperation can't be applied in the current context");
53 TraceLog.TraceWarning("EndLogicalOperation can't be applied in the current context");
49 }
54 }
55 return current;
50 }
56 }
51
57
52 public void Leave() {
58 public void Leave() {
@@ -3,22 +3,22 using System.IO;
3 using System.Text;
3 using System.Text;
4
4
5 namespace Implab.Diagnostics {
5 namespace Implab.Diagnostics {
6 public class TextFileListener: TextListenerBase {
6 public class TextFileListener: ListenerBase {
7 readonly TextWriter m_textWriter;
7 readonly TextWriter m_textWriter;
8
8
9 public TextFileListener(string fileName, bool global)
9 public TextFileListener(string fileName) {
10 : base(global) {
11 m_textWriter = File.CreateText(fileName);
10 m_textWriter = File.CreateText(fileName);
12
11
13 m_textWriter.WriteLine("LOG {0}", DateTime.Now);
12 m_textWriter.WriteLine("LOG {0}", DateTime.Now);
14 Register(this);
15 }
13 }
16
14
17 protected override void WriteEntry(LogEventArgs args, EventText text, string channel) {
15 #region implemented abstract members of ListenerBase
16
17 public override void Write(LogEventArgs args, object entry) {
18 var msg = new StringBuilder();
18 var msg = new StringBuilder();
19 for (int i = 0; i < text.indent; i++)
19 for (int i = 0; i < args.Operation.Level; i++)
20 msg.Append(" ");
20 msg.Append(" ");
21 msg.AppendFormat("[{0}]:{1}: {2}", args.ThreadId, channel, text.content);
21 msg.AppendFormat("[{0}]:{1}: {2}", args.ThreadId, args.ChannelName, entry);
22
22
23 lock (m_textWriter) {
23 lock (m_textWriter) {
24 if (!IsDisposed) {
24 if (!IsDisposed) {
@@ -29,7 +29,8 namespace Implab.Diagnostics {
29 }
29 }
30 }
30 }
31
31
32
32 #endregion
33
33 protected override void Dispose(bool disposing) {
34 protected override void Dispose(bool disposing) {
34 base.Dispose(disposing);
35 base.Dispose(disposing);
35 if (disposing) {
36 if (disposing) {
@@ -42,14 +42,14 namespace Implab.Diagnostics {
42
42
43 public void EnterLogicalOperation(LogicalOperation operation, bool takeOwnership) {
43 public void EnterLogicalOperation(LogicalOperation operation, bool takeOwnership) {
44 //var prev = CurrentOperation;
44 //var prev = CurrentOperation;
45 //LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(takeOwnership ? TraceEventType.Attach : TraceEventType.Enter, String.Format("{0} -> {1}",prev.Name, operation.Name)));
45 m_stack.Push(m_current);
46 m_stack.Push(m_current);
46 m_current = new OperationContext(operation, takeOwnership);
47 m_current = new OperationContext(operation, takeOwnership);
47 //LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(takeOwnership ? TraceEventType.Attach : TraceEventType.Enter, String.Format("{0} -> {1}",prev.Name, operation.Name)));
48 }
48 }
49
49
50 public void StartLogicalOperation(string name) {
50 public void StartLogicalOperation(string name) {
51 LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.OperationStarted, name));
51 m_current.BeginLogicalOperation(name);
52 m_current.BeginLogicalOperation(name);
52 LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.OperationStarted, String.Format("+{0}",CurrentOperation.Name)));
53 }
53 }
54
54
55 public void StartLogicalOperation() {
55 public void StartLogicalOperation() {
@@ -57,8 +57,8 namespace Implab.Diagnostics {
57 }
57 }
58
58
59 public void EndLogicalOperation() {
59 public void EndLogicalOperation() {
60 LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.OperationCompleted, String.Format("-{0} : {1}ms",CurrentOperation.Name, CurrentOperation.Duration)));
60 var op = m_current.EndLogicalOperation();
61 m_current.EndLogicalOperation();
61 LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.OperationCompleted, String.Format("-{0} : {1}ms",op.Name, op.Duration)));
62 }
62 }
63
63
64 public LogicalOperation DetachLogicalOperation() {
64 public LogicalOperation DetachLogicalOperation() {
@@ -74,11 +74,9
74 <Compile Include="CustomEqualityComparer.cs" />
74 <Compile Include="CustomEqualityComparer.cs" />
75 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
75 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
76 <Compile Include="Diagnostics\EventText.cs" />
76 <Compile Include="Diagnostics\EventText.cs" />
77 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
78 <Compile Include="Diagnostics\LogChannel.cs" />
77 <Compile Include="Diagnostics\LogChannel.cs" />
79 <Compile Include="Diagnostics\LogicalOperation.cs" />
78 <Compile Include="Diagnostics\LogicalOperation.cs" />
80 <Compile Include="Diagnostics\TextFileListener.cs" />
79 <Compile Include="Diagnostics\TextFileListener.cs" />
81 <Compile Include="Diagnostics\TextListenerBase.cs" />
82 <Compile Include="Diagnostics\TraceLog.cs" />
80 <Compile Include="Diagnostics\TraceLog.cs" />
83 <Compile Include="Diagnostics\TraceEvent.cs" />
81 <Compile Include="Diagnostics\TraceEvent.cs" />
84 <Compile Include="Diagnostics\TraceEventType.cs" />
82 <Compile Include="Diagnostics\TraceEventType.cs" />
@@ -155,6 +153,8
155 <Compile Include="PromiseTransientException.cs" />
153 <Compile Include="PromiseTransientException.cs" />
156 <Compile Include="Parallels\Signal.cs" />
154 <Compile Include="Parallels\Signal.cs" />
157 <Compile Include="Parallels\SharedLock.cs" />
155 <Compile Include="Parallels\SharedLock.cs" />
156 <Compile Include="Diagnostics\ILogWriter.cs" />
157 <Compile Include="Diagnostics\ListenerBase.cs" />
158 </ItemGroup>
158 </ItemGroup>
159 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
159 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
160 <ItemGroup />
160 <ItemGroup />
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now