The Labs \ Source Viewer \ SSCLI \ System.Diagnostics \ XmlWriterTraceListener

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlWriterTraceListener.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System;
  16. using System.Text;
  17. using System.Xml;
  18. using System.Xml.XPath;
  19. using System.IO;
  20. using System.Globalization;
  21. using System.Collections;
  22. using System.Security.Permissions;
  23. using System.Runtime.Versioning;
  24. namespace System.Diagnostics
  25. {
  26.     [HostProtection(Synchronization = true)]
  27.     public class XmlWriterTraceListener : TextWriterTraceListener
  28.     {
  29.         private const string fixedHeader = "<E2ETraceEvent xmlns=\"http://schemas.microsoft.com/2004/06/E2ETraceEvent\">" + "<System xmlns=\"http://schemas.microsoft.com/2004/06/windows/eventlog/system\">";
  30.         private readonly string machineName = Environment.MachineName;
  31.         private StringBuilder strBldr = null;
  32.         private XmlTextWriter xmlBlobWriter = null;
  33.        
  34.         public XmlWriterTraceListener(Stream stream) : base(stream)
  35.         {
  36.         }
  37.         public XmlWriterTraceListener(Stream stream, string name) : base(stream, name)
  38.         {
  39.         }
  40.         public XmlWriterTraceListener(TextWriter writer) : base(writer)
  41.         {
  42.         }
  43.         public XmlWriterTraceListener(TextWriter writer, string name) : base(writer, name)
  44.         {
  45.         }
  46.        
  47.         [ResourceExposure(ResourceScope.Machine)]
  48.         [ResourceConsumption(ResourceScope.Machine)]
  49.         public XmlWriterTraceListener(string filename) : base(filename)
  50.         {
  51.         }
  52.        
  53.         [ResourceExposure(ResourceScope.Machine)]
  54.         [ResourceConsumption(ResourceScope.Machine)]
  55.         public XmlWriterTraceListener(string filename, string name) : base(filename, name)
  56.         {
  57.         }
  58.        
  59.         public override void Write(string message)
  60.         {
  61.             this.WriteLine(message);
  62.         }
  63.        
  64.         public override void WriteLine(string message)
  65.         {
  66.             this.TraceEvent(null, SR.GetString(SR.TraceAsTraceSource), TraceEventType.Information, 0, message);
  67.         }
  68.        
  69.         public override void Fail(string message, string detailMessage)
  70.         {
  71.             StringBuilder failMessage = new StringBuilder(message);
  72.             if (detailMessage != null) {
  73.                 failMessage.Append(" ");
  74.                 failMessage.Append(detailMessage);
  75.             }
  76.            
  77.             this.TraceEvent(null, SR.GetString(SR.TraceAsTraceSource), TraceEventType.Error, 0, failMessage.ToString());
  78.         }
  79.        
  80.         public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
  81.         {
  82.             if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, format, args))
  83.                 return;
  84.            
  85.             WriteHeader(source, eventType, id, eventCache);
  86.            
  87.             string message;
  88.             if (args != null)
  89.                 message = String.Format(CultureInfo.InvariantCulture, format, args);
  90.             else
  91.                 message = format;
  92.            
  93.             WriteEscaped(message);
  94.            
  95.             WriteFooter(eventCache);
  96.         }
  97.        
  98.         public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
  99.         {
  100.             if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, message))
  101.                 return;
  102.            
  103.             WriteHeader(source, eventType, id, eventCache);
  104.             WriteEscaped(message);
  105.             WriteFooter(eventCache);
  106.         }
  107.        
  108.         public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
  109.         {
  110.             if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data))
  111.                 return;
  112.            
  113.             WriteHeader(source, eventType, id, eventCache);
  114.            
  115.             InternalWrite("<TraceData>");
  116.             if (data != null) {
  117.                 InternalWrite("<DataItem>");
  118.                 WriteData(data);
  119.                 InternalWrite("</DataItem>");
  120.             }
  121.             InternalWrite("</TraceData>");
  122.            
  123.             WriteFooter(eventCache);
  124.         }
  125.        
  126.         public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data)
  127.         {
  128.             if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, null, data))
  129.                 return;
  130.            
  131.             WriteHeader(source, eventType, id, eventCache);
  132.             InternalWrite("<TraceData>");
  133.             if (data != null) {
  134.                 for (int i = 0; i < data.Length; i++) {
  135.                     InternalWrite("<DataItem>");
  136.                     if (data[i] != null)
  137.                         WriteData(data[i]);
  138.                     InternalWrite("</DataItem>");
  139.                 }
  140.             }
  141.             InternalWrite("</TraceData>");
  142.            
  143.             WriteFooter(eventCache);
  144.         }
  145.        
  146.         // Special case XPathNavigator dataitems to write out XML blob unescaped
  147.         private void WriteData(object data)
  148.         {
  149.             XPathNavigator xmlBlob = data as XPathNavigator;
  150.            
  151.             if (xmlBlob == null)
  152.                 WriteEscaped(data.ToString());
  153.             else {
  154.                 if (strBldr == null) {
  155.                     strBldr = new StringBuilder();
  156.                     xmlBlobWriter = new XmlTextWriter(new StringWriter(strBldr, CultureInfo.CurrentCulture));
  157.                 }
  158.                 else
  159.                     strBldr.Length = 0;
  160.                
  161.                 try {
  162.                     // Rewind the blob to point to the root, this is needed to support multiple XMLTL in one TraceData call
  163.                     xmlBlob.MoveToRoot();
  164.                     xmlBlobWriter.WriteNode(xmlBlob, false);
  165.                     InternalWrite(strBldr.ToString());
  166.                 }
  167.                 catch (Exception) {
  168.                     // We probably only care about XmlException for ill-formed XML though
  169.                     InternalWrite(data.ToString());
  170.                 }
  171.             }
  172.         }
  173.        
  174.         public override void Close()
  175.         {
  176.             base.Close();
  177.             if (xmlBlobWriter != null)
  178.                 xmlBlobWriter.Close();
  179.             xmlBlobWriter = null;
  180.             strBldr = null;
  181.         }
  182.        
  183.         public override void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
  184.         {
  185.             WriteHeader(source, TraceEventType.Transfer, id, eventCache, relatedActivityId);
  186.             WriteEscaped(message);
  187.             WriteFooter(eventCache);
  188.         }
  189.        
  190.         private void WriteHeader(string source, TraceEventType eventType, int id, TraceEventCache eventCache, Guid relatedActivityId)
  191.         {
  192.             WriteStartHeader(source, eventType, id, eventCache);
  193.             InternalWrite("\" RelatedActivityID=\"");
  194.             InternalWrite(relatedActivityId.ToString("B"));
  195.             WriteEndHeader(eventCache);
  196.         }
  197.        
  198.         private void WriteHeader(string source, TraceEventType eventType, int id, TraceEventCache eventCache)
  199.         {
  200.             WriteStartHeader(source, eventType, id, eventCache);
  201.             WriteEndHeader(eventCache);
  202.         }
  203.        
  204.         private void WriteStartHeader(string source, TraceEventType eventType, int id, TraceEventCache eventCache)
  205.         {
  206.             InternalWrite(fixedHeader);
  207.            
  208.             InternalWrite("<EventID>");
  209.             InternalWrite(((uint)id).ToString(CultureInfo.InvariantCulture));
  210.             InternalWrite("</EventID>");
  211.            
  212.             InternalWrite("<Type>3</Type>");
  213.            
  214.             InternalWrite("<SubType Name=\"");
  215.             InternalWrite(eventType.ToString());
  216.             InternalWrite("\">0</SubType>");
  217.            
  218.             InternalWrite("<Level>");
  219.             int sev = (int)eventType;
  220.             if (sev > 255)
  221.                 sev = 255;
  222.             if (sev < 0)
  223.                 sev = 0;
  224.             InternalWrite(sev.ToString(CultureInfo.InvariantCulture));
  225.             InternalWrite("</Level>");
  226.            
  227.             InternalWrite("<TimeCreated SystemTime=\"");
  228.             if (eventCache != null)
  229.                 InternalWrite(eventCache.DateTime.ToString("o", CultureInfo.InvariantCulture));
  230.             else
  231.                 InternalWrite(DateTime.Now.ToString("o", CultureInfo.InvariantCulture));
  232.             InternalWrite("\" />");
  233.            
  234.             InternalWrite("<Source Name=\"");
  235.             WriteEscaped(source);
  236.             InternalWrite("\" />");
  237.            
  238.             InternalWrite("<Correlation ActivityID=\"");
  239.             if (eventCache != null)
  240.                 InternalWrite(eventCache.ActivityId.ToString("B"));
  241.             else
  242.                 InternalWrite(Guid.Empty.ToString("B"));
  243.         }
  244.        
  245.         private void WriteEndHeader(TraceEventCache eventCache)
  246.         {
  247.             InternalWrite("\" />");
  248.            
  249.             InternalWrite("<Execution ProcessName=\"");
  250.             InternalWrite(TraceEventCache.GetProcessName());
  251.             InternalWrite("\" ProcessID=\"");
  252.             InternalWrite(((uint)TraceEventCache.GetProcessId()).ToString(CultureInfo.InvariantCulture));
  253.             InternalWrite("\" ThreadID=\"");
  254.             if (eventCache != null)
  255.                 WriteEscaped(eventCache.ThreadId.ToString(CultureInfo.InvariantCulture));
  256.             else
  257.                 WriteEscaped(TraceEventCache.GetThreadId().ToString(CultureInfo.InvariantCulture));
  258.             InternalWrite("\" />");
  259.            
  260.             InternalWrite("<Channel/>");
  261.            
  262.             InternalWrite("<Computer>");
  263.             InternalWrite(machineName);
  264.             InternalWrite("</Computer>");
  265.            
  266.             InternalWrite("</System>");
  267.            
  268.             InternalWrite("<ApplicationData>");
  269.         }
  270.        
  271.         private void WriteFooter(TraceEventCache eventCache)
  272.         {
  273.             bool writeLogicalOps = IsEnabled(TraceOptions.LogicalOperationStack);
  274.             bool writeCallstack = IsEnabled(TraceOptions.Callstack);
  275.            
  276.             if (eventCache != null && (writeLogicalOps || writeCallstack)) {
  277.                 InternalWrite("<System.Diagnostics xmlns=\"http://schemas.microsoft.com/2004/08/System.Diagnostics\">");
  278.                
  279.                 if (writeLogicalOps) {
  280.                     InternalWrite("<LogicalOperationStack>");
  281.                    
  282.                     Stack s = eventCache.LogicalOperationStack as Stack;
  283.                    
  284.                     if (s != null) {
  285.                         foreach (object correlationId in s) {
  286.                             InternalWrite("<LogicalOperation>");
  287.                             WriteEscaped(correlationId.ToString());
  288.                             InternalWrite("</LogicalOperation>");
  289.                         }
  290.                     }
  291.                     InternalWrite("</LogicalOperationStack>");
  292.                 }
  293.                
  294.                 InternalWrite("<Timestamp>");
  295.                 InternalWrite(eventCache.Timestamp.ToString(CultureInfo.InvariantCulture));
  296.                 InternalWrite("</Timestamp>");
  297.                
  298.                 if (writeCallstack) {
  299.                     InternalWrite("<Callstack>");
  300.                     WriteEscaped(eventCache.Callstack);
  301.                     InternalWrite("</Callstack>");
  302.                 }
  303.                
  304.                 InternalWrite("</System.Diagnostics>");
  305.             }
  306.            
  307.             InternalWrite("</ApplicationData></E2ETraceEvent>");
  308.         }
  309.        
  310.         private void WriteEscaped(string str)
  311.         {
  312.             if (str == null)
  313.                 return;
  314.            
  315.             int lastIndex = 0;
  316.             for (int i = 0; i < str.Length; i++) {
  317.                 switch (str[i]) {
  318.                     case '&':
  319.                         InternalWrite(str.Substring(lastIndex, i - lastIndex));
  320.                         InternalWrite("&amp;");
  321.                         lastIndex = i + 1;
  322.                         break;
  323.                     case '<':
  324.                         InternalWrite(str.Substring(lastIndex, i - lastIndex));
  325.                         InternalWrite("&lt;");
  326.                         lastIndex = i + 1;
  327.                         break;
  328.                     case '>':
  329.                         InternalWrite(str.Substring(lastIndex, i - lastIndex));
  330.                         InternalWrite("&gt;");
  331.                         lastIndex = i + 1;
  332.                         break;
  333.                     case '"':
  334.                         InternalWrite(str.Substring(lastIndex, i - lastIndex));
  335.                         InternalWrite("&quot;");
  336.                         lastIndex = i + 1;
  337.                         break;
  338.                     case '\'':
  339.                         InternalWrite(str.Substring(lastIndex, i - lastIndex));
  340.                         InternalWrite("&apos;");
  341.                         lastIndex = i + 1;
  342.                         break;
  343.                     case (char)13:
  344.                         InternalWrite(str.Substring(lastIndex, i - lastIndex));
  345.                         InternalWrite("&#xD;");
  346.                         lastIndex = i + 1;
  347.                         break;
  348.                     case (char)10:
  349.                         InternalWrite(str.Substring(lastIndex, i - lastIndex));
  350.                         InternalWrite("&#xA;");
  351.                         lastIndex = i + 1;
  352.                         break;
  353.                 }
  354.             }
  355.             InternalWrite(str.Substring(lastIndex, str.Length - lastIndex));
  356.         }
  357.        
  358.         private void InternalWrite(string message)
  359.         {
  360.             if (!EnsureWriter())
  361.                 return;
  362.             // NeedIndent is nop
  363.             writer.Write(message);
  364.         }
  365.     }
  366. }

Developer Fusion