mscorlib(4.0.0.0) API with additions
TraceSource.cs
1 #define TRACE
5 
6 namespace System.Diagnostics
7 {
9  public class TraceSource
10  {
11  private static List<WeakReference> tracesources = new List<WeakReference>();
12 
13  private static int s_LastCollectionCount;
14 
15  private volatile SourceSwitch internalSwitch;
16 
17  private volatile TraceListenerCollection listeners;
18 
19  private StringDictionary attributes;
20 
21  private SourceLevels switchLevel;
22 
23  private volatile string sourceName;
24 
25  internal volatile bool _initCalled;
26 
30  {
31  get
32  {
33  Initialize();
34  if (attributes == null)
35  {
36  attributes = new StringDictionary();
37  }
38  return attributes;
39  }
40  }
41 
44  public string Name => sourceName;
45 
49  {
50  [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
51  get
52  {
53  Initialize();
54  return listeners;
55  }
56  }
57 
62  public SourceSwitch Switch
63  {
64  get
65  {
66  Initialize();
67  return internalSwitch;
68  }
69  [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
70  set
71  {
72  if (value == null)
73  {
74  throw new ArgumentNullException("Switch");
75  }
76  Initialize();
77  internalSwitch = value;
78  }
79  }
80 
87  public TraceSource(string name)
88  : this(name, SourceLevels.Off)
89  {
90  }
91 
99  public TraceSource(string name, SourceLevels defaultLevel)
100  {
101  if (name == null)
102  {
103  throw new ArgumentNullException("name");
104  }
105  if (name.Length == 0)
106  {
107  throw new ArgumentException("name");
108  }
109  sourceName = name;
110  switchLevel = defaultLevel;
111  lock (tracesources)
112  {
113  _pruneCachedTraceSources();
114  tracesources.Add(new WeakReference(this));
115  }
116  }
117 
118  private static void _pruneCachedTraceSources()
119  {
120  lock (tracesources)
121  {
122  if (s_LastCollectionCount != GC.CollectionCount(2))
123  {
124  List<WeakReference> list = new List<WeakReference>(tracesources.Count);
125  for (int i = 0; i < tracesources.Count; i++)
126  {
127  TraceSource traceSource = (TraceSource)tracesources[i].Target;
128  if (traceSource != null)
129  {
130  list.Add(tracesources[i]);
131  }
132  }
133  if (list.Count < tracesources.Count)
134  {
135  tracesources.Clear();
136  tracesources.AddRange(list);
137  tracesources.TrimExcess();
138  }
139  s_LastCollectionCount = GC.CollectionCount(2);
140  }
141  }
142  }
143 
144  private void Initialize()
145  {
146  if (!_initCalled)
147  {
148  lock (this)
149  {
150  if (!_initCalled)
151  {
152  SourceElementsCollection sources = DiagnosticsConfiguration.Sources;
153  if (sources != null)
154  {
155  SourceElement sourceElement = sources[sourceName];
156  if (sourceElement != null)
157  {
158  if (!string.IsNullOrEmpty(sourceElement.SwitchName))
159  {
160  CreateSwitch(sourceElement.SwitchType, sourceElement.SwitchName);
161  }
162  else
163  {
164  CreateSwitch(sourceElement.SwitchType, sourceName);
165  if (!string.IsNullOrEmpty(sourceElement.SwitchValue))
166  {
167  internalSwitch.Level = (SourceLevels)Enum.Parse(typeof(SourceLevels), sourceElement.SwitchValue);
168  }
169  }
170  listeners = sourceElement.Listeners.GetRuntimeObject();
171  attributes = new StringDictionary();
172  TraceUtils.VerifyAttributes(sourceElement.Attributes, GetSupportedAttributes(), this);
173  attributes.ReplaceHashtable(sourceElement.Attributes);
174  }
175  else
176  {
177  NoConfigInit();
178  }
179  }
180  else
181  {
182  NoConfigInit();
183  }
184  _initCalled = true;
185  }
186  }
187  }
188  }
189 
190  private void NoConfigInit()
191  {
192  internalSwitch = new SourceSwitch(sourceName, switchLevel.ToString());
193  listeners = new TraceListenerCollection();
194  listeners.Add(new DefaultTraceListener());
195  attributes = null;
196  }
197 
199  [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
200  public void Close()
201  {
202  if (listeners != null)
203  {
204  lock (TraceInternal.critSec)
205  {
206  foreach (TraceListener listener in listeners)
207  {
208  listener.Close();
209  }
210  }
211  }
212  }
213 
216  public void Flush()
217  {
218  if (listeners != null)
219  {
220  if (TraceInternal.UseGlobalLock)
221  {
222  lock (TraceInternal.critSec)
223  {
224  foreach (TraceListener listener in listeners)
225  {
226  listener.Flush();
227  }
228  }
229  }
230  else
231  {
232  foreach (TraceListener listener2 in listeners)
233  {
234  if (!listener2.IsThreadSafe)
235  {
236  lock (listener2)
237  {
238  listener2.Flush();
239  }
240  }
241  else
242  {
243  listener2.Flush();
244  }
245  }
246  }
247  }
248  }
249 
252  protected internal virtual string[] GetSupportedAttributes()
253  {
254  return null;
255  }
256 
257  internal static void RefreshAll()
258  {
259  lock (tracesources)
260  {
261  _pruneCachedTraceSources();
262  for (int i = 0; i < tracesources.Count; i++)
263  {
264  ((TraceSource)tracesources[i].Target)?.Refresh();
265  }
266  }
267  }
268 
269  internal void Refresh()
270  {
271  if (!_initCalled)
272  {
273  Initialize();
274  return;
275  }
276  SourceElementsCollection sources = DiagnosticsConfiguration.Sources;
277  if (sources == null)
278  {
279  return;
280  }
281  SourceElement sourceElement = sources[Name];
282  if (sourceElement != null)
283  {
284  if ((string.IsNullOrEmpty(sourceElement.SwitchType) && internalSwitch.GetType() != typeof(SourceSwitch)) || sourceElement.SwitchType != internalSwitch.GetType().AssemblyQualifiedName)
285  {
286  if (!string.IsNullOrEmpty(sourceElement.SwitchName))
287  {
288  CreateSwitch(sourceElement.SwitchType, sourceElement.SwitchName);
289  }
290  else
291  {
292  CreateSwitch(sourceElement.SwitchType, Name);
293  if (!string.IsNullOrEmpty(sourceElement.SwitchValue))
294  {
295  internalSwitch.Level = (SourceLevels)Enum.Parse(typeof(SourceLevels), sourceElement.SwitchValue);
296  }
297  }
298  }
299  else if (!string.IsNullOrEmpty(sourceElement.SwitchName))
300  {
301  if (sourceElement.SwitchName != internalSwitch.DisplayName)
302  {
303  CreateSwitch(sourceElement.SwitchType, sourceElement.SwitchName);
304  }
305  else
306  {
307  internalSwitch.Refresh();
308  }
309  }
310  else if (!string.IsNullOrEmpty(sourceElement.SwitchValue))
311  {
312  internalSwitch.Level = (SourceLevels)Enum.Parse(typeof(SourceLevels), sourceElement.SwitchValue);
313  }
314  else
315  {
316  internalSwitch.Level = SourceLevels.Off;
317  }
318  TraceListenerCollection traceListenerCollection = new TraceListenerCollection();
319  foreach (ListenerElement listener in sourceElement.Listeners)
320  {
321  TraceListener traceListener = listeners[listener.Name];
322  if (traceListener != null)
323  {
324  traceListenerCollection.Add(listener.RefreshRuntimeObject(traceListener));
325  }
326  else
327  {
328  traceListenerCollection.Add(listener.GetRuntimeObject());
329  }
330  }
331  TraceUtils.VerifyAttributes(sourceElement.Attributes, GetSupportedAttributes(), this);
332  attributes = new StringDictionary();
333  attributes.ReplaceHashtable(sourceElement.Attributes);
334  listeners = traceListenerCollection;
335  }
336  else
337  {
338  internalSwitch.Level = switchLevel;
339  listeners.Clear();
340  attributes = null;
341  }
342  }
343 
348  [Conditional("TRACE")]
349  public void TraceEvent(TraceEventType eventType, int id)
350  {
351  Initialize();
352  TraceEventCache eventCache = new TraceEventCache();
353  if (!internalSwitch.ShouldTrace(eventType) || listeners == null)
354  {
355  return;
356  }
357  if (TraceInternal.UseGlobalLock)
358  {
359  lock (TraceInternal.critSec)
360  {
361  for (int i = 0; i < listeners.Count; i++)
362  {
363  TraceListener traceListener = listeners[i];
364  traceListener.TraceEvent(eventCache, Name, eventType, id);
365  if (Trace.AutoFlush)
366  {
367  traceListener.Flush();
368  }
369  }
370  }
371  return;
372  }
373  for (int j = 0; j < listeners.Count; j++)
374  {
375  TraceListener traceListener2 = listeners[j];
376  if (!traceListener2.IsThreadSafe)
377  {
378  lock (traceListener2)
379  {
380  traceListener2.TraceEvent(eventCache, Name, eventType, id);
381  if (Trace.AutoFlush)
382  {
383  traceListener2.Flush();
384  }
385  }
386  continue;
387  }
388  traceListener2.TraceEvent(eventCache, Name, eventType, id);
389  if (Trace.AutoFlush)
390  {
391  traceListener2.Flush();
392  }
393  }
394  }
395 
401  [Conditional("TRACE")]
402  public void TraceEvent(TraceEventType eventType, int id, string message)
403  {
404  Initialize();
405  TraceEventCache eventCache = new TraceEventCache();
406  if (!internalSwitch.ShouldTrace(eventType) || listeners == null)
407  {
408  return;
409  }
410  if (TraceInternal.UseGlobalLock)
411  {
412  lock (TraceInternal.critSec)
413  {
414  for (int i = 0; i < listeners.Count; i++)
415  {
416  TraceListener traceListener = listeners[i];
417  traceListener.TraceEvent(eventCache, Name, eventType, id, message);
418  if (Trace.AutoFlush)
419  {
420  traceListener.Flush();
421  }
422  }
423  }
424  return;
425  }
426  for (int j = 0; j < listeners.Count; j++)
427  {
428  TraceListener traceListener2 = listeners[j];
429  if (!traceListener2.IsThreadSafe)
430  {
431  lock (traceListener2)
432  {
433  traceListener2.TraceEvent(eventCache, Name, eventType, id, message);
434  if (Trace.AutoFlush)
435  {
436  traceListener2.Flush();
437  }
438  }
439  continue;
440  }
441  traceListener2.TraceEvent(eventCache, Name, eventType, id, message);
442  if (Trace.AutoFlush)
443  {
444  traceListener2.Flush();
445  }
446  }
447  }
448 
459  [Conditional("TRACE")]
460  public void TraceEvent(TraceEventType eventType, int id, string format, params object[] args)
461  {
462  Initialize();
463  TraceEventCache eventCache = new TraceEventCache();
464  if (!internalSwitch.ShouldTrace(eventType) || listeners == null)
465  {
466  return;
467  }
468  if (TraceInternal.UseGlobalLock)
469  {
470  lock (TraceInternal.critSec)
471  {
472  for (int i = 0; i < listeners.Count; i++)
473  {
474  TraceListener traceListener = listeners[i];
475  traceListener.TraceEvent(eventCache, Name, eventType, id, format, args);
476  if (Trace.AutoFlush)
477  {
478  traceListener.Flush();
479  }
480  }
481  }
482  return;
483  }
484  for (int j = 0; j < listeners.Count; j++)
485  {
486  TraceListener traceListener2 = listeners[j];
487  if (!traceListener2.IsThreadSafe)
488  {
489  lock (traceListener2)
490  {
491  traceListener2.TraceEvent(eventCache, Name, eventType, id, format, args);
492  if (Trace.AutoFlush)
493  {
494  traceListener2.Flush();
495  }
496  }
497  continue;
498  }
499  traceListener2.TraceEvent(eventCache, Name, eventType, id, format, args);
500  if (Trace.AutoFlush)
501  {
502  traceListener2.Flush();
503  }
504  }
505  }
506 
512  [Conditional("TRACE")]
513  public void TraceData(TraceEventType eventType, int id, object data)
514  {
515  Initialize();
516  TraceEventCache eventCache = new TraceEventCache();
517  if (!internalSwitch.ShouldTrace(eventType) || listeners == null)
518  {
519  return;
520  }
521  if (TraceInternal.UseGlobalLock)
522  {
523  lock (TraceInternal.critSec)
524  {
525  for (int i = 0; i < listeners.Count; i++)
526  {
527  TraceListener traceListener = listeners[i];
528  traceListener.TraceData(eventCache, Name, eventType, id, data);
529  if (Trace.AutoFlush)
530  {
531  traceListener.Flush();
532  }
533  }
534  }
535  return;
536  }
537  for (int j = 0; j < listeners.Count; j++)
538  {
539  TraceListener traceListener2 = listeners[j];
540  if (!traceListener2.IsThreadSafe)
541  {
542  lock (traceListener2)
543  {
544  traceListener2.TraceData(eventCache, Name, eventType, id, data);
545  if (Trace.AutoFlush)
546  {
547  traceListener2.Flush();
548  }
549  }
550  continue;
551  }
552  traceListener2.TraceData(eventCache, Name, eventType, id, data);
553  if (Trace.AutoFlush)
554  {
555  traceListener2.Flush();
556  }
557  }
558  }
559 
565  [Conditional("TRACE")]
566  public void TraceData(TraceEventType eventType, int id, params object[] data)
567  {
568  Initialize();
569  TraceEventCache eventCache = new TraceEventCache();
570  if (!internalSwitch.ShouldTrace(eventType) || listeners == null)
571  {
572  return;
573  }
574  if (TraceInternal.UseGlobalLock)
575  {
576  lock (TraceInternal.critSec)
577  {
578  for (int i = 0; i < listeners.Count; i++)
579  {
580  TraceListener traceListener = listeners[i];
581  traceListener.TraceData(eventCache, Name, eventType, id, data);
582  if (Trace.AutoFlush)
583  {
584  traceListener.Flush();
585  }
586  }
587  }
588  return;
589  }
590  for (int j = 0; j < listeners.Count; j++)
591  {
592  TraceListener traceListener2 = listeners[j];
593  if (!traceListener2.IsThreadSafe)
594  {
595  lock (traceListener2)
596  {
597  traceListener2.TraceData(eventCache, Name, eventType, id, data);
598  if (Trace.AutoFlush)
599  {
600  traceListener2.Flush();
601  }
602  }
603  continue;
604  }
605  traceListener2.TraceData(eventCache, Name, eventType, id, data);
606  if (Trace.AutoFlush)
607  {
608  traceListener2.Flush();
609  }
610  }
611  }
612 
616  [Conditional("TRACE")]
617  public void TraceInformation(string message)
618  {
619  TraceEvent(TraceEventType.Information, 0, message, null);
620  }
621 
630  [Conditional("TRACE")]
631  public void TraceInformation(string format, params object[] args)
632  {
633  TraceEvent(TraceEventType.Information, 0, format, args);
634  }
635 
640  [Conditional("TRACE")]
641  public void TraceTransfer(int id, string message, Guid relatedActivityId)
642  {
643  Initialize();
644  TraceEventCache eventCache = new TraceEventCache();
645  if (!internalSwitch.ShouldTrace(TraceEventType.Transfer) || listeners == null)
646  {
647  return;
648  }
649  if (TraceInternal.UseGlobalLock)
650  {
651  lock (TraceInternal.critSec)
652  {
653  for (int i = 0; i < listeners.Count; i++)
654  {
655  TraceListener traceListener = listeners[i];
656  traceListener.TraceTransfer(eventCache, Name, id, message, relatedActivityId);
657  if (Trace.AutoFlush)
658  {
659  traceListener.Flush();
660  }
661  }
662  }
663  return;
664  }
665  for (int j = 0; j < listeners.Count; j++)
666  {
667  TraceListener traceListener2 = listeners[j];
668  if (!traceListener2.IsThreadSafe)
669  {
670  lock (traceListener2)
671  {
672  traceListener2.TraceTransfer(eventCache, Name, id, message, relatedActivityId);
673  if (Trace.AutoFlush)
674  {
675  traceListener2.Flush();
676  }
677  }
678  continue;
679  }
680  traceListener2.TraceTransfer(eventCache, Name, id, message, relatedActivityId);
681  if (Trace.AutoFlush)
682  {
683  traceListener2.Flush();
684  }
685  }
686  }
687 
688  private void CreateSwitch(string typename, string name)
689  {
690  if (!string.IsNullOrEmpty(typename))
691  {
692  internalSwitch = (SourceSwitch)TraceUtils.GetRuntimeObject(typename, typeof(SourceSwitch), name);
693  }
694  else
695  {
696  internalSwitch = new SourceSwitch(name, switchLevel.ToString());
697  }
698  }
699  }
700 }
Provides a thread-safe list of T:System.Diagnostics.TraceListener objects.
virtual void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id)
Writes trace and event information to the listener specific output.
void TraceEvent(TraceEventType eventType, int id, string format, params object[] args)
Writes a trace event to the trace listeners in the P:System.Diagnostics.TraceSource....
Definition: TraceSource.cs:460
The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method th...
Describes a set of security permissions applied to code. This class cannot be inherited.
Provides trace event data specific to a thread and a process.
int Count
Gets the number of elements contained in the T:System.Collections.Generic.List`1.
Definition: List.cs:296
void TraceEvent(TraceEventType eventType, int id)
Writes a trace event message to the trace listeners in the P:System.Diagnostics.TraceSource....
Definition: TraceSource.cs:349
Provides the abstract base class for the listeners who monitor trace and debug output.
void TraceTransfer(int id, string message, Guid relatedActivityId)
Writes a trace transfer message to the trace listeners in the P:System.Diagnostics....
Definition: TraceSource.cs:641
void TraceInformation(string message)
Writes an informational message to the trace listeners in the P:System.Diagnostics....
Definition: TraceSource.cs:617
virtual void Close()
When overridden in a derived class, closes the output stream so it no longer receives tracing or debu...
void TraceData(TraceEventType eventType, int id, params object[] data)
Writes trace data to the trace listeners in the P:System.Diagnostics.TraceSource.Listeners collection...
Definition: TraceSource.cs:566
Provides a set of methods and properties that help you trace the execution of your code....
Definition: Trace.cs:6
Implements a hash table with the key and the value strongly typed to be strings rather than objects.
Definition: __Canon.cs:3
StringDictionary Attributes
Gets the custom switch attributes defined in the application configuration file.
Definition: TraceSource.cs:30
void TraceData(TraceEventType eventType, int id, object data)
Writes trace data to the trace listeners in the P:System.Diagnostics.TraceSource.Listeners collection...
Definition: TraceSource.cs:513
void Flush()
Flushes all the trace listeners in the trace listener collection.
Definition: TraceSource.cs:216
bool ShouldTrace(TraceEventType eventType)
Determines if trace listeners should be called, based on the trace event type.
Definition: SourceSwitch.cs:42
Represents a weak reference, which references an object while still allowing that object to be reclai...
void Add(T item)
Adds an object to the end of the T:System.Collections.Generic.List`1.
Definition: List.cs:510
SecurityAction
Specifies the security actions that can be performed using declarative security.
Represents a globally unique identifier (GUID).To browse the .NET Framework source code for this type...
Definition: Guid.cs:14
Provides a set of methods and properties that enable applications to trace the execution of code and ...
Definition: TraceSource.cs:9
virtual void Flush()
When overridden in a derived class, flushes the output buffer.
void Close()
Closes all the trace listeners in the trace listener collection.
Definition: TraceSource.cs:200
string Name
Gets the name of the trace source.
Definition: TraceSource.cs:44
virtual internal string [] GetSupportedAttributes()
Gets the custom attributes supported by the trace source.
Definition: TraceSource.cs:252
virtual void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
Writes trace information, a message, a related activity identity and event information to the listene...
void AddRange(IEnumerable< T > collection)
Adds the elements of the specified collection to the end of the T:System.Collections....
Definition: List.cs:545
TraceEventType
Identifies the type of event that has caused the trace.
Controls the system garbage collector, a service that automatically reclaims unused memory.
Definition: GC.cs:11
The exception that is thrown when one of the arguments provided to a method is not valid.
static bool AutoFlush
Gets or sets whether M:System.Diagnostics.Trace.Flush should be called on the P:System....
Definition: Trace.cs:26
TraceListenerCollection Listeners
Gets the collection of trace listeners for the trace source.
Definition: TraceSource.cs:49
void Clear()
Removes all elements from the T:System.Collections.Generic.List`1.
Definition: List.cs:614
Attribute can be applied to an enumeration.
Represents a strongly typed list of objects that can be accessed by index. Provides methods to search...
Definition: List.cs:14
TraceSource(string name, SourceLevels defaultLevel)
Initializes a new instance of the T:System.Diagnostics.TraceSource class, using the specified name fo...
Definition: TraceSource.cs:99
void TraceEvent(TraceEventType eventType, int id, string message)
Writes a trace event message to the trace listeners in the P:System.Diagnostics.TraceSource....
Definition: TraceSource.cs:402
TraceSource(string name)
Initializes a new instance of the T:System.Diagnostics.TraceSource class, using the specified name fo...
Definition: TraceSource.cs:87
SourceLevels Level
Gets or sets the level of the switch.
Definition: SourceSwitch.cs:11
static int CollectionCount(int generation)
Returns the number of times garbage collection has occurred for the specified generation of objects.
Definition: GC.cs:242
void TrimExcess()
Sets the capacity to the actual number of elements in the T:System.Collections.Generic....
Definition: List.cs:1540
SourceLevels
Specifies the levels of trace messages filtered by the source switch and event type filter.
Definition: SourceLevels.cs:7
Provides a multilevel switch to control tracing and debug output without recompiling your code.
Definition: SourceSwitch.cs:6
A conditional operation, such as a > b ? a : b in C# or If(a > b, a, b) in Visual Basic.
SecurityPermissionFlag
Specifies access flags for the security permission object.
Does not allow any events through.
Provides an abstract base class to create new debugging and tracing switches.
Definition: Switch.cs:10
string DisplayName
Gets a name used to identify the switch.
Definition: Switch.cs:52
void TraceInformation(string format, params object[] args)
Writes an informational message to the trace listeners in the P:System.Diagnostics....
Definition: TraceSource.cs:631
virtual bool IsThreadSafe
Gets a value indicating whether the trace listener is thread safe.
virtual void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
Writes trace information, a data object and event information to the listener specific output.