Mercurial > pub > ImplabNet
annotate Implab/Diagnostics/TextListenerBase.cs @ 126:f7b2b8bfbb8c v2
minor changes
| author | cin |
|---|---|
| date | Mon, 26 Jan 2015 02:12:01 +0300 |
| parents | 4c0e5ef99986 |
| children |
| rev | line source |
|---|---|
| 40 | 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 TextListenerBase : ServiceLocator, IEventTextFormatter<object>, IEventTextFormatter<TraceEvent> { | |
| 8 | |
| 9 readonly Dictionary<object, Action> m_subscriptions = new Dictionary<object, Action>(); | |
|
43
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
10 readonly LogicalOperation m_boundOperation; |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
11 readonly int m_baseIndent; |
| 40 | 12 |
| 48 | 13 protected TextListenerBase(bool global) { |
| 40 | 14 Register(this); |
| 48 | 15 if (!global) { |
| 92 | 16 m_boundOperation = TraceContext.Instance.CurrentOperation; |
|
43
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
17 m_baseIndent = Math.Max(0, m_boundOperation.Level - 1); |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
18 } |
| 40 | 19 } |
| 20 | |
| 21 public void Subscribe(Type eventType) { | |
| 22 if (eventType == null) | |
| 23 throw new ArgumentNullException("eventType"); | |
| 24 GetType().GetMethod("Subscribe", new Type[0]).MakeGenericMethod(eventType).Invoke(this, null); | |
| 25 } | |
| 26 | |
| 27 public void Subscribe<TEvent>() { | |
| 28 Subscribe<TEvent>(LogChannel<TEvent>.Default); | |
| 29 } | |
| 30 | |
| 31 public void Subscribe<TEvent>(LogChannel<TEvent> channel) { | |
| 32 if (channel == null) | |
| 33 throw new ArgumentNullException("channel"); | |
| 34 | |
| 35 lock (m_subscriptions) { | |
| 36 AssertNotDisposed(); | |
| 37 | |
| 38 var formatter = GetService<IEventTextFormatter<TEvent>>(); | |
| 48 | 39 var channelName = channel.Name; |
| 40 | 40 |
| 92 | 41 EventHandler<LogEventArgs<TEvent>> handler = (sender, args) => { |
| 42 var text = formatter.Format(args, args.Value); | |
|
43
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
43 text.indent -= m_baseIndent; |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
44 |
| 92 | 45 if (IsRelated(args.Operation)) |
| 46 WriteEntry(args, text, channelName); | |
| 40 | 47 }; |
| 48 | |
| 49 if (m_subscriptions.ContainsKey(channel)) | |
| 50 return; | |
| 51 | |
| 52 channel.Events += handler; | |
| 53 | |
| 54 Action unsubscribe = () => { | |
| 55 channel.Events -= handler; | |
| 56 }; | |
| 57 | |
| 58 m_subscriptions.Add(channel, unsubscribe); | |
| 59 } | |
| 60 } | |
| 61 | |
|
43
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
62 public bool IsRelated(LogicalOperation op) { |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
63 if (m_boundOperation == null) |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
64 return true; |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
65 |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
66 while (op != m_boundOperation && op.Level > m_boundOperation.Level) |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
67 op = op.Parent; |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
68 return op == m_boundOperation; |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
69 } |
|
7c2369f580b8
improved tracing, TextListenerBase can be bound to logical operation scope.
cin
parents:
40
diff
changeset
|
70 |
| 40 | 71 public void Unsubscribe<TEvent>(LogChannel<TEvent> channel) { |
| 72 if (channel == null) | |
| 73 throw new ArgumentNullException("channel"); | |
| 74 | |
| 75 lock (m_subscriptions) { | |
| 76 Action subscription; | |
| 77 if (m_subscriptions.TryGetValue(channel, out subscription)) { | |
| 78 subscription(); | |
| 79 m_subscriptions.Remove(channel); | |
| 80 } | |
| 81 } | |
| 82 } | |
| 83 | |
| 84 public void UnsubscribeAll() { | |
| 85 lock (m_subscriptions) { | |
| 86 foreach (var subscription in m_subscriptions.Values) | |
| 87 subscription(); | |
| 88 m_subscriptions.Clear(); | |
| 89 } | |
| 90 } | |
| 91 | |
| 47 | 92 /// <summary> |
| 93 /// Вызывается для записи текста сообщения, в журнал. | |
| 94 /// </summary> | |
| 95 /// <remarks> | |
| 96 /// Данный метод может вызваться из разных потоков одновременно. Возможна ситуация, когда | |
| 97 /// данный метод вызывается уже после освобождения ообъекта методом <see cref="Dispose()"/>. | |
| 98 /// </remarks> | |
| 99 /// <param name="text">Текст сообщения.</param> | |
| 92 | 100 /// <param name = "channel"></param> |
| 101 protected abstract void WriteEntry(LogEventArgs args, EventText text, string channel); | |
| 40 | 102 |
| 92 | 103 public EventText Format(LogEventArgs args, object data) { |
| 40 | 104 return new EventText { |
| 92 | 105 indent = args.Operation.Level, |
| 40 | 106 content = data.ToString() |
| 107 }; | |
| 108 } | |
| 109 | |
| 92 | 110 public EventText Format(LogEventArgs args, TraceEvent data) { |
| 111 var level = args.Operation.Level; | |
| 40 | 112 if (data.EventType == TraceEventType.OperationCompleted || data.EventType == TraceEventType.OperationStarted) |
| 113 level--; | |
| 114 | |
| 115 return new EventText { | |
| 116 indent = level, | |
| 117 content = data.ToString() | |
| 118 }; | |
| 119 } | |
| 120 | |
| 121 protected override void Dispose(bool disposing) { | |
| 47 | 122 base.Dispose(disposing); |
| 40 | 123 if (disposing) { |
| 124 UnsubscribeAll(); | |
| 125 } | |
| 126 } | |
| 127 } | |
| 128 } |
