##// END OF EJS Templates
Added test for TraceRegistry
cin -
r287:78da52bb28f0 v3
parent child
Show More
@@ -0,0 +1,41
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Implab.Components;
5 using Implab.Diagnostics;
6 using Xunit;
7
8 namespace Implab.Test {
9
10 public class DiagnosticsTest {
11 class Foo {}
12
13 [Fact]
14 public void TestRegistration() {
15 var channel = TraceSourceChannel<Foo>.Default;
16
17 Assert.Equal(typeof(Foo), channel.Id);
18 Assert.Equal(typeof(Foo).FullName, channel.Source.Name);
19
20 TraceSourceChannel found = null;
21 int visited = 0;
22
23 TraceRegistry.Global.Subscribe(x => {
24 visited++;
25 found = x as TraceSourceChannel;
26 }, false);
27
28 Assert.Equal(0, visited);
29
30 TraceRegistry.Global.Subscribe(x => {
31 visited++;
32 found = x as TraceSourceChannel;
33 }, true);
34
35 Assert.Equal(1,visited);
36 Assert.Equal(channel, found);
37
38 }
39
40 }
41 } No newline at end of file
@@ -1,25 +1,25
1 <Project Sdk="Microsoft.NET.Sdk">
1 <Project Sdk="Microsoft.NET.Sdk">
2 <PropertyGroup Condition="'$(OSTYPE)'=='linux'">
2 <PropertyGroup Condition="'$(OSTYPE)'=='linux'">
3 <TargetFramework>netcoreapp2.0</TargetFramework>
3 <TargetFrameworks>netcoreapp2.0;;net46</TargetFrameworks>
4 <FrameworkPathOverride Condition="'$(TargetFramework)'=='net46'">/usr/lib/mono/4.6-api/</FrameworkPathOverride>
4 <FrameworkPathOverride Condition="'$(TargetFramework)'=='net46'">/usr/lib/mono/4.6-api/</FrameworkPathOverride>
5 </PropertyGroup>
5 </PropertyGroup>
6
6
7 <PropertyGroup Condition="'$(OSTYPE)'=='windows'">
7 <PropertyGroup Condition="'$(OSTYPE)'=='windows'">
8 <TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
8 <TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
9 </PropertyGroup>
9 </PropertyGroup>
10
10
11 <PropertyGroup>
11 <PropertyGroup>
12 <OutputType>Exe</OutputType>
12 <OutputType>Exe</OutputType>
13 <IsPackable>false</IsPackable>
13 <IsPackable>false</IsPackable>
14 </PropertyGroup>
14 </PropertyGroup>
15
15
16 <ItemGroup>
16 <ItemGroup>
17 <ProjectReference Include="../Implab/Implab.csproj" />
17 <ProjectReference Include="../Implab/Implab.csproj" />
18 <ProjectReference Include="..\Implab.ServiceHost\Implab.ServiceHost.csproj" />
18 <ProjectReference Include="..\Implab.ServiceHost\Implab.ServiceHost.csproj" />
19 </ItemGroup>
19 </ItemGroup>
20
20
21 <ItemGroup>
21 <ItemGroup>
22 <PackageReference Include="Unity" Version="5.8.5" />
22 <PackageReference Include="Unity" Version="5.8.5" />
23 </ItemGroup>
23 </ItemGroup>
24
24
25 </Project>
25 </Project>
@@ -1,38 +1,45
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.Dynamic;
4 using System.Dynamic;
5 using System.Linq;
5 using System.Linq;
6 using Implab.Components;
6 using Implab.Components;
7 using Implab.Diagnostics;
7 using Implab.Diagnostics;
8 using Implab.ServiceHost.Unity;
8 using Implab.ServiceHost.Unity;
9 using Implab.Xml;
9 using Implab.Xml;
10 using Unity;
10 using Unity;
11 using Unity.Injection;
11 using Unity.Injection;
12 using Unity.Registration;
12 using Unity.Registration;
13
13
14 namespace Implab.Playground {
14 namespace Implab.Playground {
15 using static Trace<Bar>;
15 using static Trace<Bar>;
16
16
17 class Foo {
17 class Foo {
18
18
19 }
19 }
20
20
21 class Bar : Foo {
21 class Bar : Foo {
22
22
23 }
23 }
24 public class Program {
24 public class Program {
25
25
26 static void Main(string[] args) {
26 static void Main(string[] args) {
27 Trace<Foo>.Log("First!");
28 Log("+1!");
27
29
28 using(TraceRegistry.Global.Subscribe(ch => {
30 using(TraceRegistry.Global.Subscribe(x => {
31 var ch = x as TraceSourceChannel;
32 if (ch == null)
33 return;
34
29 Console.WriteLine($"{ch.Id}: {ch.Source.Name}");
35 Console.WriteLine($"{ch.Id}: {ch.Source.Name}");
36
30 }, true)) {
37 }, true)) {
31 Trace<Foo>.Log("Hi!");
38 Trace<Foo>.Log("Hi!");
32 Log("Respect!");
39 Log("Respect!");
33 }
40 }
34 }
41 }
35
42
36
43
37 }
44 }
38 }
45 }
@@ -1,192 +1,199
1 // enable System.Diagnostics trace methods
1 // enable System.Diagnostics trace methods
2 #define TRACE
2 #define TRACE
3
3
4 using System;
4 using System;
5 using System.Collections.Generic;
5 using System.Collections.Generic;
6 using System.Diagnostics;
6 using System.Diagnostics;
7 using System.Linq;
7 using System.Linq;
8 using System.Text;
8 using System.Text;
9 using System.Threading;
9 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>
13 /// <summary>
14 /// Static class which creates an individual <see cref="TraceSource"/> for
14 /// Static class which creates an individual <see cref="TraceSource"/> for
15 /// the type specified in the parameter <typeparamref name="T"/>.
15 /// the type specified in the parameter <typeparamref name="T"/> and uses
16 /// it to perform logging operations.
16 /// </summary>
17 /// </summary>
17 /// <typeparam name="T">The type for which tracing is demanded.</typeparam>
18 /// <typeparam name="T">The type for which tracing is demanded.</typeparam>
18 public static class Trace<T> {
19 public static class Trace<T> {
19
20
20 readonly static Lazy<TraceSource> _trace = new Lazy<TraceSource>(() => TraceSourceChannel<T>.Default.Source);
21 readonly static Lazy<TraceSource> _trace = new Lazy<TraceSource>(() => TraceSourceChannel<T>.Default.Source);
21
22
23 /// <summary>
24 /// The <see cref="TraceSource"/> associated with the current class.
25 /// TraceSource is created using <see cref="TraceSourceChannel{T}"/>.
26 /// </summary>
22 public static TraceSource TraceSource { get { return _trace.Value; } }
27 public static TraceSource TraceSource { get { return _trace.Value; } }
23
28
24 #if NETFX_TRACE_BUG
29 #if NETFX_TRACE_BUG
30 // AsyncLocal will store value inside the current execution context
31 // and will force it to be copied... not a very effective solution.
25 readonly static AsyncLocal<object> m_currentOperation = new AsyncLocal<object>();
32 readonly static AsyncLocal<object> m_currentOperation = new AsyncLocal<object>();
26 #endif
33 #endif
27
34
28 /// <summary>
35 /// <summary>
29 /// If this property is set then <see cref="Debug(string, object[])"/> will produce output.
36 /// If this property is set then <see cref="Debug(string, object[])"/> will produce output.
30 /// </summary>
37 /// </summary>
31 public static bool TraceVerbose {
38 public static bool TraceVerbose {
32 get {
39 get {
33 return TraceSource.Switch.ShouldTrace(TraceEventType.Verbose);
40 return TraceSource.Switch.ShouldTrace(TraceEventType.Verbose);
34 }
41 }
35 }
42 }
36
43
37 /// <summary>
44 /// <summary>
38 /// If this property is set then <see cref="Log(string, object[])"/> will produce output.
45 /// If this property is set then <see cref="Log(string, object[])"/> will produce output.
39 /// </summary>
46 /// </summary>
40 public static bool TraceInformation {
47 public static bool TraceInformation {
41 get {
48 get {
42 return TraceSource.Switch.ShouldTrace(TraceEventType.Information);
49 return TraceSource.Switch.ShouldTrace(TraceEventType.Information);
43 }
50 }
44 }
51 }
45
52
46 /// <summary>
53 /// <summary>
47 /// If this property is set then <see cref="Warn(string, object[])"/> will produce output.
54 /// If this property is set then <see cref="Warn(string, object[])"/> will produce output.
48 /// </summary>
55 /// </summary>
49 public static bool TraceWarnings {
56 public static bool TraceWarnings {
50 get {
57 get {
51 return TraceSource.Switch.ShouldTrace(TraceEventType.Warning);
58 return TraceSource.Switch.ShouldTrace(TraceEventType.Warning);
52 }
59 }
53 }
60 }
54
61
55
62
56
63
57 /// <summary>
64 /// <summary>
58 /// Starts the logical operation with the specified name, this name is usefull in logs.
65 /// Starts the logical operation with the specified name, this name is usefull in logs.
59 /// </summary>
66 /// </summary>
60 /// <param name="name">Name.</param>
67 /// <param name="name">Name.</param>
61 #if NETFX_TRACE_BUG
68 #if NETFX_TRACE_BUG
62 public static void StartLogicalOperation(object name) {
69 public static void StartLogicalOperation(object name) {
63 m_currentOperation.Value = name;
70 m_currentOperation.Value = name;
64 Trace.CorrelationManager.StartLogicalOperation(name);
71 Trace.CorrelationManager.StartLogicalOperation(name);
65 }
72 }
66
73
67 /// <summary>
74 /// <summary>
68 /// Starts the logical operation nested to the current operation nested to the current one.
75 /// Starts the logical operation nested to the current operation nested to the current one.
69 /// </summary>
76 /// </summary>
70 public static void StartLogicalOperation() {
77 public static void StartLogicalOperation() {
71 m_currentOperation.Value = new object();
78 m_currentOperation.Value = new object();
72 Trace.CorrelationManager.StartLogicalOperation();
79 Trace.CorrelationManager.StartLogicalOperation();
73
80
74 }
81 }
75 #else
82 #else
76 public static void StartLogicalOperation(object name) {
83 public static void StartLogicalOperation(object name) {
77 Trace.CorrelationManager.StartLogicalOperation(name);
84 Trace.CorrelationManager.StartLogicalOperation(name);
78 }
85 }
79
86
80 /// <summary>
87 /// <summary>
81 /// Starts the logical operation nested to the current operation nested to the current one.
88 /// Starts the logical operation nested to the current operation nested to the current one.
82 /// </summary>
89 /// </summary>
83 public static void StartLogicalOperation() {
90 public static void StartLogicalOperation() {
84 Trace.CorrelationManager.StartLogicalOperation();
91 Trace.CorrelationManager.StartLogicalOperation();
85
92
86 }
93 }
87 #endif
94 #endif
88
95
89 /// <summary>
96 /// <summary>
90 /// Ends the logical operation and restores the previous one.
97 /// Ends the logical operation and restores the previous one.
91 /// </summary>
98 /// </summary>
92 public static void StopLogicalOperation() {
99 public static void StopLogicalOperation() {
93 Trace.CorrelationManager.StopLogicalOperation();
100 Trace.CorrelationManager.StopLogicalOperation();
94 }
101 }
95
102
96 /// <summary>
103 /// <summary>
97 /// Writes a debug message.
104 /// Writes a debug message.
98 /// </summary>
105 /// </summary>
99 /// <param name="format">Format.</param>
106 /// <param name="format">Format.</param>
100 /// <param name="arguments">Arguments.</param>
107 /// <param name="arguments">Arguments.</param>
101 [Conditional("DEBUG")]
108 [Conditional("DEBUG")]
102 public static void Debug(string format, params object[] arguments) {
109 public static void Debug(string format, params object[] arguments) {
103 TraceSource.TraceEvent(TraceEventType.Verbose, 0, format, arguments);
110 TraceSource.TraceEvent(TraceEventType.Verbose, 0, format, arguments);
104 }
111 }
105
112
106 /// <summary>
113 /// <summary>
107 /// Writes an informational message.
114 /// Writes an informational message.
108 /// </summary>
115 /// </summary>
109 /// <param name="format">Format.</param>
116 /// <param name="format">Format.</param>
110 /// <param name="arguments">Arguments.</param>
117 /// <param name="arguments">Arguments.</param>
111 [Conditional("TRACE")]
118 [Conditional("TRACE")]
112 public static void Log(string format, params object[] arguments) {
119 public static void Log(string format, params object[] arguments) {
113 TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments);
120 TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments);
114 }
121 }
115
122
116 /// <summary>
123 /// <summary>
117 /// Writes a warning message.
124 /// Writes a warning message.
118 /// </summary>
125 /// </summary>
119 /// <param name="format">Format.</param>
126 /// <param name="format">Format.</param>
120 /// <param name="arguments">Arguments.</param>
127 /// <param name="arguments">Arguments.</param>
121 public static void Warn(string format, params object[] arguments) {
128 public static void Warn(string format, params object[] arguments) {
122 TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments);
129 TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments);
123 }
130 }
124
131
125 /// <summary>
132 /// <summary>
126 /// Writes a error message.
133 /// Writes a error message.
127 /// </summary>
134 /// </summary>
128 /// <param name="format">Format.</param>
135 /// <param name="format">Format.</param>
129 /// <param name="arguments">Arguments.</param>
136 /// <param name="arguments">Arguments.</param>
130 public static void Error(string format, params object[] arguments) {
137 public static void Error(string format, params object[] arguments) {
131 TraceSource.TraceEvent(TraceEventType.Error, 0, format, arguments);
138 TraceSource.TraceEvent(TraceEventType.Error, 0, format, arguments);
132 }
139 }
133
140
134 public static void Error(Exception err) {
141 public static void Error(Exception err) {
135 TraceSource.TraceData(TraceEventType.Error, 0, err);
142 TraceSource.TraceData(TraceEventType.Error, 0, err);
136 }
143 }
137
144
138 /// <summary>
145 /// <summary>
139 /// This method save the current activity, and transfers to the specified activity,
146 /// This method save the current activity, and transfers to the specified activity,
140 /// emits <see cref="TraceEventType.Start"/> and returns a scope of the new
147 /// emits <see cref="TraceEventType.Start"/> and returns a scope of the new
141 /// activity.
148 /// activity.
142 /// </summary>
149 /// </summary>
143 /// <param name="activityName">The name of the new activity/</param>
150 /// <param name="activityName">The name of the new activity/</param>
144 /// <param name="activityId">The identifier of the activity to which
151 /// <param name="activityId">The identifier of the activity to which
145 /// the control will be transferred</param>
152 /// the control will be transferred</param>
146 /// <returns>A scope of the new activity, dispose it to transfer
153 /// <returns>A scope of the new activity, dispose it to transfer
147 /// the control back to the original activity.</returns>
154 /// the control back to the original activity.</returns>
148 public static ActivityScope TransferActivity(string activityName, Guid activityId) {
155 public static ActivityScope TransferActivity(string activityName, Guid activityId) {
149 var prev = Trace.CorrelationManager.ActivityId;
156 var prev = Trace.CorrelationManager.ActivityId;
150
157
151 TraceSource.TraceTransfer(0, "Transfer", activityId);
158 TraceSource.TraceTransfer(0, "Transfer", activityId);
152 Trace.CorrelationManager.ActivityId = activityId;
159 Trace.CorrelationManager.ActivityId = activityId;
153 TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
160 TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
154
161
155 return new ActivityScope(TraceSource, prev, 0, activityName);
162 return new ActivityScope(TraceSource, prev, 0, activityName);
156 }
163 }
157
164
158 /// <summary>
165 /// <summary>
159 /// Emits <see cref="TraceEventType.Start"/> and returns a scope of the
166 /// Emits <see cref="TraceEventType.Start"/> and returns a scope of the
160 /// activity.
167 /// activity.
161 /// </summary>
168 /// </summary>
162 /// <param name="activityName">The name of the activity to start</param>
169 /// <param name="activityName">The name of the activity to start</param>
163 /// <returns>A scope of the new activity, dispose it to emit
170 /// <returns>A scope of the new activity, dispose it to emit
164 /// <see cref="TraceEventType.Stop"/> for the current activity.</returns>
171 /// <see cref="TraceEventType.Stop"/> for the current activity.</returns>
165 public static ActivityScope StartActivity(string activityName) {
172 public static ActivityScope StartActivity(string activityName) {
166 if (Trace.CorrelationManager.ActivityId == Guid.Empty)
173 if (Trace.CorrelationManager.ActivityId == Guid.Empty)
167 Trace.CorrelationManager.ActivityId = Guid.NewGuid();
174 Trace.CorrelationManager.ActivityId = Guid.NewGuid();
168
175
169 var prev = Trace.CorrelationManager.ActivityId;
176 var prev = Trace.CorrelationManager.ActivityId;
170
177
171 TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
178 TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
172 return new ActivityScope(TraceSource, prev, 0, activityName);
179 return new ActivityScope(TraceSource, prev, 0, activityName);
173 }
180 }
174
181
175 /// <summary>
182 /// <summary>
176 /// Creates new <see cref="LogicalOperation(string)"/> and calls
183 /// Creates new <see cref="LogicalOperation(string)"/> and calls
177 /// to <see cref="CorrelationManager.StartLogicalOperation(object)"/>
184 /// to <see cref="CorrelationManager.StartLogicalOperation(object)"/>
178 /// passing the created operation as identity. Calls
185 /// passing the created operation as identity. Calls
179 /// <see cref="TraceSource.TraceData(TraceEventType, int, object)"/>
186 /// <see cref="TraceSource.TraceData(TraceEventType, int, object)"/>
180 /// to notify listeners on operation start.
187 /// to notify listeners on operation start.
181 /// </summary>
188 /// </summary>
182 /// <param name="name">The name of the logical operation.</param>
189 /// <param name="name">The name of the logical operation.</param>
183 /// <returns>Logical operation scope, disposing it will stop
190 /// <returns>Logical operation scope, disposing it will stop
184 /// logical operation and notify trace listeners.</returns>
191 /// logical operation and notify trace listeners.</returns>
185 public static LogicalOperationScope LogicalOperation(string name) {
192 public static LogicalOperationScope LogicalOperation(string name) {
186 var operation = new LogicalOperation(name);
193 var operation = new LogicalOperation(name);
187 TraceSource.TraceData(TraceEventType.Information, TraceEventCodes.StartLogicalOperation, operation);
194 TraceSource.TraceData(TraceEventType.Information, TraceEventCodes.StartLogicalOperation, operation);
188 StartLogicalOperation(operation);
195 StartLogicalOperation(operation);
189 return new LogicalOperationScope(TraceSource, operation);
196 return new LogicalOperationScope(TraceSource, operation);
190 }
197 }
191 }
198 }
192 }
199 }
@@ -1,33 +1,33
1 using System;
1 using System;
2 using System.Threading;
2 using System.Threading;
3 using TraceSource = System.Diagnostics.TraceSource;
3 using TraceSource = System.Diagnostics.TraceSource;
4
4
5 namespace Implab.Diagnostics {
5 namespace Implab.Diagnostics {
6 /// <summary>
6 /// <summary>
7 /// This class is used to provide a single <see cref="TraceSourceChannel"/>
7 /// This class is used to provide a single <see cref="TraceSourceChannel"/>
8 /// instance for the specified class in <typeparamref name="T"/> parameter.
8 /// instance for the specified class in <typeparamref name="T"/> parameter.
9 /// </summary>
9 /// </summary>
10 /// <typeparam name="T">
10 /// <typeparam name="T">
11 /// The class for which <see cref="TraceSourceChannel"/> is required.
11 /// The class for which <see cref="TraceSourceChannel"/> is required.
12 /// </typeparam>
12 /// </typeparam>
13 /// <remarks>
13 /// <remarks>
14 /// The <see cref="TraceSourceChannel"/> instance will be created on demand
14 /// The <see cref="TraceSourceChannel"/> instance will be created on demand
15 /// and automatically registered in <see cref="TraceRegistry.Global"/>.
15 /// and automatically registered in <see cref="TraceRegistry.Global"/>.
16 /// </remarks>
16 /// </remarks>
17 public static class TraceSourceChannel<T> {
17 public static class TraceSourceChannel<T> {
18 static Lazy<TraceSourceChannel> _traceSource = new Lazy<TraceSourceChannel>(CreateChannel, LazyThreadSafetyMode.ExecutionAndPublication);
18 static Lazy<TraceSourceChannel> _traceSource = new Lazy<TraceSourceChannel>(CreateChannel, LazyThreadSafetyMode.ExecutionAndPublication);
19
19
20 /// <summary>
20 /// <summary>
21 /// The default <see cref="TraceSourceChannel"/> instance.
21 /// The default <see cref="TraceSourceChannel"/> instance.
22 /// </summary>
22 /// </summary>
23 public static TraceSourceChannel Default { get { return _traceSource.Value; } }
23 public static TraceSourceChannel Default { get { return _traceSource.Value; } }
24
24
25 static TraceSourceChannel CreateChannel() {
25 static TraceSourceChannel CreateChannel() {
26 var channel = new TraceSourceChannel(typeof(T), typeof(T).Name);
26 var channel = new TraceSourceChannel(typeof(T), typeof(T).FullName);
27
27
28 TraceRegistry.Global.Register(channel);
28 TraceRegistry.Global.Register(channel);
29
29
30 return channel;
30 return channel;
31 }
31 }
32 }
32 }
33 } No newline at end of file
33 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now