Auto status change to "Under Review"
@@ -0,0 +1,17 | |||||
|
1 | namespace Implab.Diagnostics | |||
|
2 | { | |||
|
3 | public abstract class TraceChannel { | |||
|
4 | readonly object m_id; | |||
|
5 | ||||
|
6 | public object Id { | |||
|
7 | get { | |||
|
8 | return m_id; | |||
|
9 | } | |||
|
10 | } | |||
|
11 | ||||
|
12 | protected TraceChannel(object id) { | |||
|
13 | m_id = id ?? new object(); | |||
|
14 | } | |||
|
15 | ||||
|
16 | } | |||
|
17 | } No newline at end of file |
@@ -0,0 +1,83 | |||||
|
1 | using System; | |||
|
2 | using System.Collections.Generic; | |||
|
3 | using System.Diagnostics; | |||
|
4 | using Implab.Parallels; | |||
|
5 | ||||
|
6 | namespace Implab.Diagnostics { | |||
|
7 | public class TraceRegistry { | |||
|
8 | ||||
|
9 | class Subscription : IDisposable { | |||
|
10 | readonly WeakReference<TraceRegistry> m_registry; | |||
|
11 | readonly Action<object> m_unsubscribe; | |||
|
12 | ||||
|
13 | public Subscription(TraceRegistry registry) { | |||
|
14 | m_registry = new WeakReference<TraceRegistry>(registry); | |||
|
15 | } | |||
|
16 | ||||
|
17 | public void Dispose() { | |||
|
18 | TraceRegistry t; | |||
|
19 | if (m_registry.TryGetTarget(out t)) | |||
|
20 | t.RemoveSubscription(this); | |||
|
21 | } | |||
|
22 | } | |||
|
23 | ||||
|
24 | public static TraceRegistry Global { get; } = new TraceRegistry(); | |||
|
25 | ||||
|
26 | readonly object m_lock = new object(); | |||
|
27 | ||||
|
28 | readonly Dictionary<object, Action<TraceChannel>> m_subscriptions = new Dictionary<object, Action<TraceChannel>>(); | |||
|
29 | readonly SimpleAsyncQueue<TraceChannel> m_channels = new SimpleAsyncQueue<TraceChannel>(); | |||
|
30 | ||||
|
31 | internal void Register(TraceChannel channel) { | |||
|
32 | // notifications can run in parallel | |||
|
33 | Action<TraceChannel>[] handlers = null; | |||
|
34 | ||||
|
35 | lock(m_lock) { | |||
|
36 | m_channels.Enqueue(channel); | |||
|
37 | if (m_subscriptions.Count > 0) { | |||
|
38 | handlers = new Action<TraceChannel>[m_subscriptions.Count]; | |||
|
39 | m_subscriptions.Values.CopyTo(handlers, 0); | |||
|
40 | } | |||
|
41 | } | |||
|
42 | ||||
|
43 | if (handlers != null) | |||
|
44 | foreach(var h in handlers) | |||
|
45 | h(channel); | |||
|
46 | } | |||
|
47 | ||||
|
48 | /// <summary> | |||
|
49 | /// Subscribes the specified handler to notifications about new trace | |||
|
50 | /// channels | |||
|
51 | /// </summary> | |||
|
52 | /// <param name="handler"></param> | |||
|
53 | /// <returns></returns> | |||
|
54 | public IDisposable Subscribe(Action<TraceChannel> handler, bool existing) { | |||
|
55 | Safe.ArgumentNotNull(handler, nameof(handler)); | |||
|
56 | ||||
|
57 | var cookie = new Subscription(this); | |||
|
58 | ||||
|
59 | IEnumerable<TraceChannel> snap; | |||
|
60 | ||||
|
61 | // lock to ensure that no new channels will be added | |||
|
62 | // while the subscription is added | |||
|
63 | lock(m_lock) { | |||
|
64 | m_subscriptions.Add(cookie, handler); | |||
|
65 | snap = m_channels.Snapshot(); | |||
|
66 | } | |||
|
67 | ||||
|
68 | // announce previously declared channels if required | |||
|
69 | if (existing) { | |||
|
70 | foreach(var c in snap) | |||
|
71 | handler(c); | |||
|
72 | } | |||
|
73 | ||||
|
74 | // return the subscription | |||
|
75 | return cookie; | |||
|
76 | } | |||
|
77 | ||||
|
78 | void RemoveSubscription(object cookie) { | |||
|
79 | lock(m_lock) | |||
|
80 | m_subscriptions.Remove(cookie); | |||
|
81 | } | |||
|
82 | } | |||
|
83 | } No newline at end of file |
@@ -0,0 +1,27 | |||||
|
1 | using TraceSource = System.Diagnostics.TraceSource; | |||
|
2 | ||||
|
3 | namespace Implab.Diagnostics { | |||
|
4 | ||||
|
5 | /// <summary> | |||
|
6 | /// Trace channel which incapsulates <see cref="System.Diagnostics.TraceSource"/> instance. | |||
|
7 | /// </summary> | |||
|
8 | public class TraceSourceChannel : TraceChannel { | |||
|
9 | readonly TraceSource m_trace; | |||
|
10 | ||||
|
11 | public TraceSourceChannel() : base(new object()) { | |||
|
12 | } | |||
|
13 | ||||
|
14 | public TraceSourceChannel(object id) : base(id) { | |||
|
15 | } | |||
|
16 | ||||
|
17 | public TraceSourceChannel(object id, string name) : base(id) { | |||
|
18 | m_trace = new TraceSource(name); | |||
|
19 | } | |||
|
20 | ||||
|
21 | public TraceSource Source { | |||
|
22 | get { | |||
|
23 | return m_trace; | |||
|
24 | } | |||
|
25 | } | |||
|
26 | } | |||
|
27 | } No newline at end of file |
@@ -0,0 +1,33 | |||||
|
1 | using System; | |||
|
2 | using System.Threading; | |||
|
3 | using TraceSource = System.Diagnostics.TraceSource; | |||
|
4 | ||||
|
5 | namespace Implab.Diagnostics { | |||
|
6 | /// <summary> | |||
|
7 | /// This class is used to provide a single <see cref="TraceSourceChannel"/> | |||
|
8 | /// instance for the specified class in <typeparamref name="T"/> parameter. | |||
|
9 | /// </summary> | |||
|
10 | /// <typeparam name="T"> | |||
|
11 | /// The class for which <see cref="TraceSourceChannel"/> is required. | |||
|
12 | /// </typeparam> | |||
|
13 | /// <remarks> | |||
|
14 | /// The <see cref="TraceSourceChannel"/> instance will be created on demand | |||
|
15 | /// and automatically registered in <see cref="TraceRegistry.Global"/>. | |||
|
16 | /// </remarks> | |||
|
17 | public static class TraceSourceChannel<T> { | |||
|
18 | static Lazy<TraceSourceChannel> _traceSource = new Lazy<TraceSourceChannel>(CreateChannel, LazyThreadSafetyMode.ExecutionAndPublication); | |||
|
19 | ||||
|
20 | /// <summary> | |||
|
21 | /// The default <see cref="TraceSourceChannel"/> instance. | |||
|
22 | /// </summary> | |||
|
23 | public static TraceSourceChannel Default { get { return _traceSource.Value; } } | |||
|
24 | ||||
|
25 | static TraceSourceChannel CreateChannel() { | |||
|
26 | var channel = new TraceSourceChannel(typeof(T), typeof(T).Name); | |||
|
27 | ||||
|
28 | TraceRegistry.Global.Register(channel); | |||
|
29 | ||||
|
30 | return channel; | |||
|
31 | } | |||
|
32 | } | |||
|
33 | } No newline at end of file |
@@ -12,141 +12,24 using Unity.Injection; | |||||
12 | using Unity.Registration; |
|
12 | using Unity.Registration; | |
13 |
|
13 | |||
14 | namespace Implab.Playground { |
|
14 | namespace Implab.Playground { | |
15 |
|
15 | using static Trace<Bar>; | ||
16 | public class Foo { |
|
|||
17 |
|
||||
18 | public class Bar { |
|
|||
19 |
|
||||
20 | } |
|
|||
21 |
|
||||
22 | public string Name { get; set; } |
|
|||
23 |
|
||||
24 | public int IntValue { get; set; } |
|
|||
25 |
|
||||
26 | public string StringValue { get; set; } |
|
|||
27 |
|
||||
28 | public void AddRange(Foo[] items) { |
|
|||
29 | Console.WriteLine($"AddRange: Foo[]"); |
|
|||
30 | } |
|
|||
31 |
|
||||
32 | } |
|
|||
33 |
|
||||
34 | public class FooFactory : IFactory<Foo>, IFactory<Foo.Bar> { |
|
|||
35 |
|
||||
36 | public bool UseSsl { get; set; } |
|
|||
37 |
|
||||
38 | public string Connection { get; set; } |
|
|||
39 |
|
|
16 | ||
40 | public Foo Create() { |
|
17 | class Foo { | |
41 | return new Foo() { |
|
|||
42 | Name = "AutoFac" |
|
|||
43 | }; |
|
|||
44 | } |
|
|||
45 |
|
||||
46 | Foo.Bar IFactory<Foo.Bar>.Create() { |
|
|||
47 | return new Foo.Bar(); |
|
|||
48 | } |
|
|||
49 | } |
|
|||
50 |
|
||||
51 | public interface IContainer<T> { |
|
|||
52 | T Instance { get; set; } |
|
|||
53 | } |
|
|||
54 |
|
||||
55 | public class Container<T> : IContainer<T> { |
|
|||
56 | public class Bar { |
|
|||
57 |
|
||||
58 | } |
|
|||
59 |
|
||||
60 | public class Bar<T2> { |
|
|||
61 | public class Baz { |
|
|||
62 |
|
||||
63 | } |
|
|||
64 |
|
||||
65 | } |
|
|||
66 |
|
||||
67 | public Container() { |
|
|||
68 |
|
18 | |||
69 |
|
|
19 | } | |
70 |
|
20 | |||
71 | public Container(T instance) { |
|
21 | class Bar : Foo { | |
72 | Instance = instance; |
|
|||
73 | } |
|
|||
74 |
|
||||
75 | public T Instance { get; set; } |
|
|||
76 |
|
||||
77 | public void SetInstance(T value) { |
|
|||
78 | Instance = value; |
|
|||
79 | } |
|
|||
80 |
|
22 | |||
81 | public void AddRange(List<T> items) { |
|
|||
82 | Console.WriteLine($"AddRange: {typeof(List<T>)}"); |
|
|||
83 |
|
|
23 | } | |
84 |
|
||||
85 | public void AddRange(T[] items) { |
|
|||
86 | Console.WriteLine($"AddRange: T[] ofType {typeof(T[])}"); |
|
|||
87 | } |
|
|||
88 | } |
|
|||
89 |
|
||||
90 | public class Program { |
|
24 | public class Program { | |
91 |
|
25 | |||
92 | static void Main(string[] args) { |
|
26 | static void Main(string[] args) { | |
93 | var u1 = new Uri("/some/one"); |
|
|||
94 |
|
27 | |||
95 | dynamic obj = new ExpandoObject(); |
|
28 | using(TraceRegistry.Global.Subscribe(ch => { | |
96 |
|
29 | Console.WriteLine($"{ch.Id}: {ch.Source.Name}"); | ||
97 | obj.Name = "Dynamo"; |
|
30 | }, true)) { | |
98 |
|
31 | Trace<Foo>.Log("Hi!"); | ||
99 | obj.Hello = new Func<string>(() => { return "Hello"; }); |
|
32 | Log("Respect!"); | |
100 |
|
||||
101 | Console.WriteLine($"{obj.Hello()}"); |
|
|||
102 |
|
||||
103 | } |
|
|||
104 |
|
||||
105 | static void Main2(string[] args) { |
|
|||
106 | var listener = new SimpleTraceListener(Console.Out); |
|
|||
107 | var source = Trace<TypeResolver>.TraceSource; |
|
|||
108 | source.Switch.Level = SourceLevels.All; |
|
|||
109 | source.Listeners.Add(listener); |
|
|||
110 |
|
||||
111 | var stopwatch = new Stopwatch(); |
|
|||
112 | stopwatch.Start(); |
|
|||
113 |
|
||||
114 | var container = new UnityContainer(); |
|
|||
115 |
|
||||
116 | Console.WriteLine($"Created: {stopwatch.ElapsedMilliseconds}"); |
|
|||
117 | stopwatch.Restart(); |
|
|||
118 |
|
||||
119 | container.LoadXmlConfiguration("data/sample.xml"); |
|
|||
120 |
|
||||
121 | Console.WriteLine($"Loaded: {stopwatch.ElapsedMilliseconds}"); |
|
|||
122 |
|
||||
123 | stopwatch.Restart(); |
|
|||
124 | var instace1 = container.Resolve<IContainer<string>>(); |
|
|||
125 | Console.WriteLine($"Resolved1: {stopwatch.ElapsedMilliseconds}"); |
|
|||
126 |
|
||||
127 | stopwatch.Restart(); |
|
|||
128 | var instace2 = container.Resolve<IContainer<Foo>>(); |
|
|||
129 | Console.WriteLine($"Resolved2: {stopwatch.ElapsedMilliseconds}"); |
|
|||
130 |
|
||||
131 | DisplayContainerRegistrations(container); |
|
|||
132 | } |
|
|||
133 |
|
||||
134 | static void DisplayContainerRegistrations(IUnityContainer theContainer) { |
|
|||
135 | string regName, regType, mapTo, lifetime; |
|
|||
136 | Console.WriteLine("Container has {0} Registrations:", |
|
|||
137 | theContainer.Registrations.Count()); |
|
|||
138 | foreach (ContainerRegistration item in theContainer.Registrations) { |
|
|||
139 | regType = item.RegisteredType.FullName; |
|
|||
140 | mapTo = item.MappedToType.FullName; |
|
|||
141 | regName = item.Name ?? "[default]"; |
|
|||
142 | lifetime = item.LifetimeManager.LifetimeType.Name; |
|
|||
143 | if (mapTo != regType) { |
|
|||
144 | mapTo = " -> " + mapTo; |
|
|||
145 | } else { |
|
|||
146 | mapTo = string.Empty; |
|
|||
147 | } |
|
|||
148 | lifetime = lifetime.Substring(0, lifetime.Length - "LifetimeManager".Length); |
|
|||
149 | Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime); |
|
|||
150 | } |
|
33 | } | |
151 | } |
|
34 | } | |
152 |
|
35 |
@@ -5,7 +5,7 using Implab.Diagnostics; | |||||
5 | using Unity; |
|
5 | using Unity; | |
6 |
|
6 | |||
7 | namespace Implab.ServiceHost.Unity { |
|
7 | namespace Implab.ServiceHost.Unity { | |
8 |
using |
|
8 | using Log = Trace<ContainerBuilder>; | |
9 |
|
9 | |||
10 | public class ContainerBuilder { |
|
10 | public class ContainerBuilder { | |
11 |
|
11 | |||
@@ -33,7 +33,9 namespace Implab.ServiceHost.Unity { | |||||
33 | } |
|
33 | } | |
34 |
|
34 | |||
35 | public Type ResolveType(string typeReference) { |
|
35 | public Type ResolveType(string typeReference) { | |
36 |
|
|
36 | var resolved = string.IsNullOrEmpty(typeReference) ? null : m_resolver.Resolve(typeReference, true); | |
|
37 | Log.Debug("ResolveType('{0}'): {1}", typeReference, resolved?.FullName); | |||
|
38 | return resolved; | |||
37 | } |
|
39 | } | |
38 |
|
40 | |||
39 | public void Visit(ITypeRegistration registration) { |
|
41 | public void Visit(ITypeRegistration registration) { |
@@ -1,15 +1,25 | |||||
1 | using System; |
|
1 | using System; | |
2 | using System.Diagnostics; |
|
2 | using Stopwatch = System.Diagnostics.Stopwatch; | |
3 |
|
3 | |||
4 | namespace Implab.Diagnostics { |
|
4 | namespace Implab.Diagnostics { | |
5 | public class LogicalOperation { |
|
5 | public class LogicalOperation { | |
6 | public Stopwatch OperationStopwatch { get; private set; } |
|
6 | readonly Stopwatch m_stopwatch; | |
7 |
|
7 | |||
8 | public string Name { get; private set; } |
|
8 | public string Name { get; private set; } | |
9 |
|
9 | |||
10 | internal LogicalOperation(string name) { |
|
10 | internal LogicalOperation(string name) { | |
11 | Name = string.IsNullOrEmpty(name) ? "<unnamed>" : name; |
|
11 | Name = string.IsNullOrEmpty(name) ? "<unnamed>" : name; | |
12 |
|
|
12 | m_stopwatch = Stopwatch.StartNew(); | |
|
13 | } | |||
|
14 | ||||
|
15 | public TimeSpan Elapsed { | |||
|
16 | get { | |||
|
17 | return m_stopwatch.Elapsed; | |||
|
18 | } | |||
|
19 | } | |||
|
20 | ||||
|
21 | public void End() { | |||
|
22 | m_stopwatch.Stop(); | |||
13 | } |
|
23 | } | |
14 |
|
24 | |||
15 | public override string ToString() => Name; |
|
25 | public override string ToString() => Name; |
@@ -13,7 +13,7 namespace Implab.Diagnostics { | |||||
13 | } |
|
13 | } | |
14 |
|
14 | |||
15 | public void Dispose() { |
|
15 | public void Dispose() { | |
16 |
m_operation. |
|
16 | m_operation.End(); | |
17 | Trace.CorrelationManager.StopLogicalOperation(); |
|
17 | Trace.CorrelationManager.StopLogicalOperation(); | |
18 | m_source.TraceData(TraceEventType.Information, TraceEventCodes.StopLogicalOperation, m_operation); |
|
18 | m_source.TraceData(TraceEventType.Information, TraceEventCodes.StopLogicalOperation, m_operation); | |
19 | } |
|
19 | } |
@@ -41,7 +41,7 namespace Implab.Diagnostics { | |||||
41 |
|
41 | |||
42 | string FormatStopLogicalOperation(object data) { |
|
42 | string FormatStopLogicalOperation(object data) { | |
43 | if (data is LogicalOperation op) { |
|
43 | if (data is LogicalOperation op) { | |
44 |
return string.Format("-{0} ({1})", op, FormatTimespan(op. |
|
44 | return string.Format("-{0} ({1})", op, FormatTimespan(op.Elapsed)); | |
45 | } else { |
|
45 | } else { | |
46 | return data?.ToString(); |
|
46 | return data?.ToString(); | |
47 | } |
|
47 | } | |
@@ -90,7 +90,7 namespace Implab.Diagnostics { | |||||
90 | operation = eventCache.LogicalOperationStack.Peek() as LogicalOperation; |
|
90 | operation = eventCache.LogicalOperationStack.Peek() as LogicalOperation; | |
91 |
|
91 | |||
92 | if (operation != null) { |
|
92 | if (operation != null) { | |
93 |
base.TraceData(eventCache, source, eventType, id, FormatTimespan(operation. |
|
93 | base.TraceData(eventCache, source, eventType, id, FormatTimespan(operation.Elapsed) + ": " + message); | |
94 | } else { |
|
94 | } else { | |
95 | base.TraceData(eventCache, source, eventType, id, message); |
|
95 | base.TraceData(eventCache, source, eventType, id, message); | |
96 | } |
|
96 | } |
@@ -10,34 +10,49 using System.Threading; | |||||
10 | using System.Threading.Tasks; |
|
10 | using System.Threading.Tasks; | |
11 |
|
11 | |||
12 | namespace Implab.Diagnostics { |
|
12 | namespace Implab.Diagnostics { | |
|
13 | /// <summary> | |||
|
14 | /// Static class which creates an individual <see cref="TraceSource"/> for | |||
|
15 | /// the type specified in the parameter <typeparamref name="T"/>. | |||
|
16 | /// </summary> | |||
|
17 | /// <typeparam name="T">The type for which tracing is demanded.</typeparam> | |||
13 | public static class Trace<T> { |
|
18 | public static class Trace<T> { | |
14 |
|
19 | |||
15 |
static Lazy<TraceSource> _trace |
|
20 | readonly static Lazy<TraceSource> _trace = new Lazy<TraceSource>(() => TraceSourceChannel<T>.Default.Source); | |
16 |
|
||||
17 | static int _nextId; |
|
|||
18 |
|
21 | |||
19 | static TraceSource CreateChannel() { |
|
22 | public static TraceSource TraceSource { get { return _trace.Value; } } | |
20 | var id = Interlocked.Increment(ref _nextId); |
|
|||
21 | var trs = new TraceSource(typeof(T).Name); |
|
|||
22 |
|
||||
23 | TraceChannelRegistry.AllCannels.NotifyChannelCreated(new ChannelInfo(typeof(T), trs)); |
|
|||
24 |
|
||||
25 | return trs; |
|
|||
26 | } |
|
|||
27 |
|
||||
28 | public static TraceSource TraceSource { get { return _traceSource.Value; } } |
|
|||
29 |
|
23 | |||
30 | #if NETFX_TRACE_BUG |
|
24 | #if NETFX_TRACE_BUG | |
31 | readonly static AsyncLocal<object> m_currentOperation = new AsyncLocal<object>(); |
|
25 | readonly static AsyncLocal<object> m_currentOperation = new AsyncLocal<object>(); | |
32 | #endif |
|
26 | #endif | |
33 |
|
27 | |||
34 | /// <summary> |
|
28 | /// <summary> | |
35 | /// Starts the logical operation nested to the current operation nested to the current one. |
|
29 | /// If this property is set then <see cref="Debug(string, object[])"/> will produce output. | |
|
30 | /// </summary> | |||
|
31 | public static bool TraceVerbose { | |||
|
32 | get { | |||
|
33 | return TraceSource.Switch.ShouldTrace(TraceEventType.Verbose); | |||
|
34 | } | |||
|
35 | } | |||
|
36 | ||||
|
37 | /// <summary> | |||
|
38 | /// If this property is set then <see cref="Log(string, object[])"/> will produce output. | |||
36 | /// </summary> |
|
39 | /// </summary> | |
37 |
public static |
|
40 | public static bool TraceInformation { | |
38 | Trace.CorrelationManager.StartLogicalOperation(); |
|
41 | get { | |
|
42 | return TraceSource.Switch.ShouldTrace(TraceEventType.Information); | |||
|
43 | } | |||
|
44 | } | |||
39 |
|
45 | |||
|
46 | /// <summary> | |||
|
47 | /// If this property is set then <see cref="Warn(string, object[])"/> will produce output. | |||
|
48 | /// </summary> | |||
|
49 | public static bool TraceWarnings { | |||
|
50 | get { | |||
|
51 | return TraceSource.Switch.ShouldTrace(TraceEventType.Warning); | |||
40 | } |
|
52 | } | |
|
53 | } | |||
|
54 | ||||
|
55 | ||||
41 |
|
56 | |||
42 | /// <summary> |
|
57 | /// <summary> | |
43 | /// Starts the logical operation with the specified name, this name is usefull in logs. |
|
58 | /// Starts the logical operation with the specified name, this name is usefull in logs. | |
@@ -48,10 +63,27 namespace Implab.Diagnostics { | |||||
48 | m_currentOperation.Value = name; |
|
63 | m_currentOperation.Value = name; | |
49 | Trace.CorrelationManager.StartLogicalOperation(name); |
|
64 | Trace.CorrelationManager.StartLogicalOperation(name); | |
50 | } |
|
65 | } | |
|
66 | ||||
|
67 | /// <summary> | |||
|
68 | /// Starts the logical operation nested to the current operation nested to the current one. | |||
|
69 | /// </summary> | |||
|
70 | public static void StartLogicalOperation() { | |||
|
71 | m_currentOperation.Value = new object(); | |||
|
72 | Trace.CorrelationManager.StartLogicalOperation(); | |||
|
73 | ||||
|
74 | } | |||
51 | #else |
|
75 | #else | |
52 | public static void StartLogicalOperation(object name) { |
|
76 | public static void StartLogicalOperation(object name) { | |
53 | Trace.CorrelationManager.StartLogicalOperation(name); |
|
77 | Trace.CorrelationManager.StartLogicalOperation(name); | |
54 | } |
|
78 | } | |
|
79 | ||||
|
80 | /// <summary> | |||
|
81 | /// Starts the logical operation nested to the current operation nested to the current one. | |||
|
82 | /// </summary> | |||
|
83 | public static void StartLogicalOperation() { | |||
|
84 | Trace.CorrelationManager.StartLogicalOperation(); | |||
|
85 | ||||
|
86 | } | |||
55 | #endif |
|
87 | #endif | |
56 |
|
88 | |||
57 | /// <summary> |
|
89 | /// <summary> | |
@@ -68,7 +100,7 namespace Implab.Diagnostics { | |||||
68 | /// <param name="arguments">Arguments.</param> |
|
100 | /// <param name="arguments">Arguments.</param> | |
69 | [Conditional("DEBUG")] |
|
101 | [Conditional("DEBUG")] | |
70 | public static void Debug(string format, params object[] arguments) { |
|
102 | public static void Debug(string format, params object[] arguments) { | |
71 |
|
103 | TraceSource.TraceEvent(TraceEventType.Verbose, 0, format, arguments); | ||
72 | } |
|
104 | } | |
73 |
|
105 | |||
74 | /// <summary> |
|
106 | /// <summary> |
@@ -5,6 +5,7 namespace Implab.Diagnostics { | |||||
5 | /// Used to mark class which uses <see cref="Trace{T}"/> class to trace it's events |
|
5 | /// Used to mark class which uses <see cref="Trace{T}"/> class to trace it's events | |
6 | /// </summary> |
|
6 | /// </summary> | |
7 | [AttributeUsage(AttributeTargets.Class)] |
|
7 | [AttributeUsage(AttributeTargets.Class)] | |
|
8 | [Obsolete("Use TraceRegistry to monitor trace sources")] | |||
8 | public class TraceSourceAttribute : Attribute { |
|
9 | public class TraceSourceAttribute : Attribute { | |
9 | } |
|
10 | } | |
10 | } |
|
11 | } |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now