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