Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Diagnostics / EventSchemaTraceListener.cs / 1305376 / EventSchemaTraceListener.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- using System; using Microsoft.Win32; using System.Text; using System.IO; using System.Globalization; using System.Collections; using System.Threading; using System.Security.Permissions; using System.Runtime.Versioning; namespace System.Diagnostics { [HostProtection(Synchronization=true)] [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public class EventSchemaTraceListener : TextWriterTraceListener { private const string s_optionBufferSize = "bufferSize"; private const string s_optionLogRetention = "logRetentionOption"; private const string s_optionMaximumFileSize = "maximumFileSize"; private const string s_optionMaximumNumberOfFiles = "maximumNumberOfFiles"; private const string s_userDataHeader = ""; private const string s_eventHeader = " "); } BuildFooter(writer, eventType, eventCache, true, this.TraceOutputOptions); _InternalWriteRaw(writer); } //TraceLogRetentionOption.SingleFileBoundedSize) throw new ArgumentOutOfRangeException(s_optionLogRetention, SR.GetString(SR.ArgumentOutOfRange_NeedValidLogRetention)); base.Name = name; this.fileName = fileName; if (!String.IsNullOrEmpty(this.fileName) && (fileName[0] != Path.DirectorySeparatorChar) && (fileName[0] != Path.AltDirectorySeparatorChar) && !Path.IsPathRooted(fileName)) { this.fileName = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile), this.fileName); } this._retention = logRetentionOption; this._bufferSize = bufferSize; _SetMaxFileSize(maximumFileSize, false); _SetMaxNumberOfFiles(maximumNumberOfFiles, false); } // Hide base class version new public TextWriter Writer { // // [System.Security.SecurityCritical] get { EnsureWriter(); return traceWriter; } set { throw new NotSupportedException(SR.GetString(SR.NotSupported_SetTextWriter)); } } public override bool IsThreadSafe { get { return true; } } public int BufferSize { get { Init(); return _bufferSize; } } public TraceLogRetentionOption TraceLogRetentionOption { get { Init(); return _retention; } } public long MaximumFileSize { get { Init(); return _maxFileSize; } } public int MaximumNumberOfFiles { get { Init(); return _maxNumberOfFiles; } } public override void Close() { try { if (traceWriter != null) { traceWriter.Flush(); traceWriter.Close(); } } finally { traceWriter = null; //fileName = null; // It is more useful to allow the listener to be reopened upon subsequent write base.Close(); // This should be No-op } } //// // [System.Security.SecurityCritical] public override void Flush() { if (!EnsureWriter()) return; traceWriter.Flush(); } public override void Write(string message) { this.WriteLine(message); } public override void WriteLine(string message) { this.TraceEvent(null, SR.GetString(SR.TraceAsTraceSource), TraceEventType.Information, 0, message); } public override void Fail(string message, string detailMessage) { StringBuilder failMessage = new StringBuilder(message); if (detailMessage != null) { failMessage.Append(" "); failMessage.Append(detailMessage); } this.TraceEvent(null, SR.GetString(SR.TraceAsTraceSource), TraceEventType.Error, 0, failMessage.ToString()); } //// // [System.Security.SecurityCritical] public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, int id, string format, params object[] args) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, format, args, null, null)) return; StringBuilder writer = new StringBuilder(s_defaultPayloadSize); BuildHeader(writer, source, eventType, id, eventCache, null, false, this.TraceOutputOptions); string message; if (args != null) message = String.Format(CultureInfo.InvariantCulture, format, args); else message = format; BuildMessage(writer, message); BuildFooter(writer, eventType, eventCache, false, this.TraceOutputOptions); _InternalWriteRaw(writer); } //// // // [System.Security.SecurityCritical] public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, int id, string message) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, message, null, null, null)) return; StringBuilder writer = new StringBuilder(s_defaultPayloadSize); BuildHeader(writer, source, eventType, id, eventCache, null, false, this.TraceOutputOptions); BuildMessage(writer, message); BuildFooter(writer, eventType, eventCache, false, this.TraceOutputOptions); _InternalWriteRaw(writer); } //// // // [System.Security.SecurityCritical] public override void TraceData(TraceEventCache eventCache, String source, TraceEventType eventType, int id, object data) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null)) return; StringBuilder writer = new StringBuilder(s_defaultPayloadSize); BuildHeader(writer, source, eventType, id, eventCache, null, true, this.TraceOutputOptions); // No validation of user provided data. No explicit namespace scope. The data should identify the XML schema by itself. if (data != null) { _InternalBuildRaw(writer, s_userDataHeader); BuildUserData(writer, data); _InternalBuildRaw(writer, "// // // [System.Security.SecurityCritical] public override void TraceData(TraceEventCache eventCache, String source, TraceEventType eventType, int id, params object[] data) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, null, data)) return; StringBuilder writer = new StringBuilder(s_defaultPayloadSize); BuildHeader(writer, source, eventType, id, eventCache, null, true, this.TraceOutputOptions); // No validation of user provided data. No explicit namespace scope. The data should identify the XML schema by itself. if ((data != null) && (data.Length > 0)) { _InternalBuildRaw(writer, s_userDataHeader); for (int i=0; i// // "); } BuildFooter(writer, eventType, eventCache, true, this.TraceOutputOptions); _InternalWriteRaw(writer); } // // [System.Security.SecurityCritical] public override void TraceTransfer(TraceEventCache eventCache, String source, int id, string message, Guid relatedActivityId) { StringBuilder writer = new StringBuilder(s_defaultPayloadSize); BuildHeader(writer, source, TraceEventType.Transfer, id, eventCache, relatedActivityId.ToString("B"), false, this.TraceOutputOptions); BuildMessage(writer, message); BuildFooter(writer, TraceEventType.Transfer, eventCache, false, this.TraceOutputOptions); _InternalWriteRaw(writer); } private static void BuildMessage(StringBuilder writer, string message) { _InternalBuildRaw(writer, ""); BuildEscaped(writer, message); _InternalBuildRaw(writer, ""); } // Writes the system properties //// // // [System.Security.SecurityCritical] private static void BuildHeader(StringBuilder writer, String source, TraceEventType eventType, int id, TraceEventCache eventCache, string relatedActivityId, bool isUserData, TraceOptions opts) { _InternalBuildRaw(writer, s_eventHeader); // Ideally, we want to enable provider guid at the TraceSource level // We can't blindly use the source param here as we need to a valid guid! //_InternalBuildRaw(writer, source); // For now, trace empty guid for provider id _InternalBuildRaw(writer, "{00000000-0000-0000-0000-000000000000}"); _InternalBuildRaw(writer, "\"/>// "); _InternalBuildRaw(writer, ((uint)((id <0)?0:id)).ToString(CultureInfo.InvariantCulture)); _InternalBuildRaw(writer, " "); _InternalBuildRaw(writer, ""); int sev = (int)eventType; int op = sev; // Treat overflow conditions as Information // Logical operation events (>255) such as Start/Stop will fall into this bucket if ((sev > 255) || (sev < 0)) sev = 0x08; _InternalBuildRaw(writer, sev.ToString(CultureInfo.InvariantCulture)); _InternalBuildRaw(writer, " "); // Logical operation events (>255) such as Start/Stop will be morphed into a byte value if (op > 255) { op /= 256; _InternalBuildRaw(writer, ""); _InternalBuildRaw(writer, op.ToString(CultureInfo.InvariantCulture)); _InternalBuildRaw(writer, " "); } if ((TraceOptions.DateTime & opts) != 0) { _InternalBuildRaw(writer, ""); } // Currently correlation is always traced, we could optimize this further _InternalBuildRaw(writer, " "); // Currently not tracing ProcessName as there is no place for it in the SystemProperties // Should we bother adding this to our own section? if (eventCache != null && ((TraceOptions.ProcessId | TraceOptions.ThreadId) & opts) != 0) { _InternalBuildRaw(writer, " "); } //_InternalBuildRaw(writer, " "); _InternalBuildRaw(writer, " "); _InternalBuildRaw(writer, machineName); _InternalBuildRaw(writer, " "); _InternalBuildRaw(writer, ""); if (!isUserData) { _InternalBuildRaw(writer, ""); } else { _InternalBuildRaw(writer, " "); } else { _InternalBuildRaw(writer, ""); } // Provide English resource string for EventType _InternalBuildRaw(writer, ""); } } private static void BuildFooter(StringBuilder writer, TraceEventType eventType, TraceEventCache eventCache, bool isUserData, TraceOptions opts) { if (!isUserData) { _InternalBuildRaw(writer, " "); //Avoid Enum.ToString which uses reflection switch (eventType) { case TraceEventType.Critical: _InternalBuildRaw(writer, " "); // Custom System.Diagnostics information as its own schema if (eventCache != null && ((TraceOptions.LogicalOperationStack | TraceOptions.Callstack | TraceOptions.Timestamp) & opts) != 0) { _InternalBuildRaw(writer, "Critical "); break; case TraceEventType.Error: _InternalBuildRaw(writer, "Error "); break; case TraceEventType.Warning: _InternalBuildRaw(writer, "Warning "); break; case TraceEventType.Information: _InternalBuildRaw(writer, "Information "); break; case TraceEventType.Verbose: _InternalBuildRaw(writer, "Verbose "); break; case TraceEventType.Start: _InternalBuildRaw(writer, "Information Start "); break; case TraceEventType.Stop: _InternalBuildRaw(writer, "Information Stop "); break; case TraceEventType.Suspend: _InternalBuildRaw(writer, "Information Suspend "); break; case TraceEventType.Resume: _InternalBuildRaw(writer, "Information Resume "); break; case TraceEventType.Transfer: _InternalBuildRaw(writer, "Information Transfer "); break; default: break; } _InternalBuildRaw(writer, ""); if ((TraceOptions.Timestamp & opts) != 0) { _InternalBuildRaw(writer, " "); } _InternalBuildRaw(writer, ""); } private static void BuildEscaped(StringBuilder writer, string str) { if (str == null) return; int lastIndex = 0; for (int i=0; i"); _InternalBuildRaw(writer, eventCache.Timestamp.ToString(CultureInfo.InvariantCulture)); _InternalBuildRaw(writer, " "); } if ((TraceOptions.LogicalOperationStack & opts) != 0) { Stack stk = eventCache.LogicalOperationStack as Stack; _InternalBuildRaw(writer, ""); if ((stk != null) && (stk.Count > 0)) { foreach (object obj in stk) { _InternalBuildRaw(writer, " "); } if ((TraceOptions.Callstack & opts) != 0) { _InternalBuildRaw(writer, ""); BuildEscaped(writer, obj.ToString()); _InternalBuildRaw(writer, " "); } } _InternalBuildRaw(writer, ""); BuildEscaped(writer, eventCache.Callstack); _InternalBuildRaw(writer, " "); } _InternalBuildRaw(writer, "': _InternalBuildRaw(writer, str.Substring(lastIndex, i-lastIndex)); _InternalBuildRaw(writer, ">"); lastIndex = i +1; break; case '"': _InternalBuildRaw(writer, str.Substring(lastIndex, i-lastIndex)); _InternalBuildRaw(writer, """); lastIndex = i +1; break; case '\'': _InternalBuildRaw(writer, str.Substring(lastIndex, i-lastIndex)); _InternalBuildRaw(writer, "'"); lastIndex = i +1; break; case (char)0xD: _InternalBuildRaw(writer, str.Substring(lastIndex, i-lastIndex)); _InternalBuildRaw(writer, " "); lastIndex = i +1; break; case (char)0xA: _InternalBuildRaw(writer, str.Substring(lastIndex, i-lastIndex)); _InternalBuildRaw(writer, " "); lastIndex = i +1; break; } } _InternalBuildRaw(writer, str.Substring(lastIndex, str.Length-lastIndex)); } // Special case UnescapedXmlDiagnosticData items to write out XML blob unescaped private static void BuildUserData(StringBuilder writer, object data) { UnescapedXmlDiagnosticData xmlBlob = data as UnescapedXmlDiagnosticData; if(xmlBlob == null) { BuildMessage(writer, data.ToString()); } else { _InternalBuildRaw(writer, xmlBlob.ToString()); } } private static void _InternalBuildRaw(StringBuilder writer, string message) { writer.Append(message); } // // [System.Security.SecurityCritical] private void _InternalWriteRaw(StringBuilder writer) { if (!EnsureWriter()) return; // NeedIndent is nop traceWriter.Write(writer.ToString()); } protected override string[] GetSupportedAttributes() { return new String[]{s_optionBufferSize, s_optionLogRetention, s_optionMaximumFileSize, s_optionMaximumNumberOfFiles}; } private void Init() { if (!_initialized) { // We could use Interlocked but this one time overhead is probably not a concern lock (m_lockObject) { if (!_initialized) { try { if (Attributes.ContainsKey(s_optionBufferSize)) { int bufferSize = Int32.Parse(Attributes[s_optionBufferSize], CultureInfo.InvariantCulture); if (bufferSize > 0) _bufferSize = bufferSize; } if (Attributes.ContainsKey(s_optionLogRetention)) { // Enum.Parse is costly! string retOption = Attributes[s_optionLogRetention]; if (String.Compare(retOption, "SingleFileUnboundedSize", StringComparison.OrdinalIgnoreCase) == 0) _retention = TraceLogRetentionOption.SingleFileUnboundedSize; else if (String.Compare(retOption, "LimitedCircularFiles", StringComparison.OrdinalIgnoreCase) == 0) _retention = TraceLogRetentionOption.LimitedCircularFiles; else if (String.Compare(retOption, "UnlimitedSequentialFiles", StringComparison.OrdinalIgnoreCase) == 0) _retention = TraceLogRetentionOption.UnlimitedSequentialFiles; else if (String.Compare(retOption, "SingleFileBoundedSize", StringComparison.OrdinalIgnoreCase) == 0) _retention = TraceLogRetentionOption.SingleFileBoundedSize; else if (String.Compare(retOption, "LimitedSequentialFiles", StringComparison.OrdinalIgnoreCase) == 0) _retention = TraceLogRetentionOption.LimitedSequentialFiles; else { _retention = TraceLogRetentionOption.SingleFileUnboundedSize; } } if (Attributes.ContainsKey(s_optionMaximumFileSize)) { long maxFileSize = Int64.Parse(Attributes[s_optionMaximumFileSize], CultureInfo.InvariantCulture); _SetMaxFileSize(maxFileSize, false); } if (Attributes.ContainsKey(s_optionMaximumNumberOfFiles)) { int maxNumberOfFiles = Int32.Parse(Attributes[s_optionMaximumNumberOfFiles], CultureInfo.InvariantCulture); _SetMaxNumberOfFiles(maxNumberOfFiles, false); } } catch(Exception) { // Avoid trhowing errors from populating config values, let the defaults stand Debug.Assert(false, "Exception while populating config values for EventSchemaTraceListener!"); } finally { _initialized = true; } } } } } private void _SetMaxFileSize(long maximumFileSize, bool throwOnError) { switch (this._retention) { case TraceLogRetentionOption.SingleFileUnboundedSize: this._maxFileSize = -1; break; case TraceLogRetentionOption.SingleFileBoundedSize: case TraceLogRetentionOption.UnlimitedSequentialFiles: case TraceLogRetentionOption.LimitedSequentialFiles: case TraceLogRetentionOption.LimitedCircularFiles: if ((maximumFileSize < 0) && throwOnError) throw new ArgumentOutOfRangeException(s_optionMaximumFileSize, SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNum)); if (maximumFileSize < this._bufferSize) { if (throwOnError) { throw new ArgumentOutOfRangeException(s_optionMaximumFileSize, SR.GetString(SR.ArgumentOutOfRange_NeedMaxFileSizeGEBufferSize)); } else { this._maxFileSize = this._bufferSize; } } else this._maxFileSize = maximumFileSize; break; } } private void _SetMaxNumberOfFiles(int maximumNumberOfFiles, bool throwOnError) { switch (this._retention) { case TraceLogRetentionOption.SingleFileUnboundedSize: case TraceLogRetentionOption.SingleFileBoundedSize: this._maxNumberOfFiles = 1; break; case TraceLogRetentionOption.UnlimitedSequentialFiles: this._maxNumberOfFiles = -1; break; case TraceLogRetentionOption.LimitedSequentialFiles: if (maximumNumberOfFiles < 1) { if (throwOnError) { throw new ArgumentOutOfRangeException(s_optionMaximumNumberOfFiles, SR.GetString(SR.ArgumentOutOfRange_NeedValidMaxNumFiles, 1)); } this._maxNumberOfFiles = 1; } else { this._maxNumberOfFiles = maximumNumberOfFiles; } break; case TraceLogRetentionOption.LimitedCircularFiles: if (maximumNumberOfFiles < 2) { if (throwOnError) { throw new ArgumentOutOfRangeException(s_optionMaximumNumberOfFiles, SR.GetString(SR.ArgumentOutOfRange_NeedValidMaxNumFiles, 2)); } this._maxNumberOfFiles = 2; } else { this._maxNumberOfFiles = maximumNumberOfFiles; } break; } } // This uses a machine resource, scoped by the fileName variable. [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] //// // [System.Security.SecurityCritical] private bool EnsureWriter() { if (traceWriter == null) { if (String.IsNullOrEmpty(fileName)) return false; // We could use Interlocked but this one time overhead is probably not a concern lock (m_lockObject) { if (traceWriter != null) return true; // To support multiple appdomains/instances tracing to the same file, // we will try to open the given file for append but if we encounter // IO errors, we will suffix the file name with a unique GUID value // and try one more time string path = fileName; for (int i=0; i<_retryThreshold; i++) { try { Init(); traceWriter = new TraceWriter(path, _bufferSize, _retention, _maxFileSize, _maxNumberOfFiles); break; } catch (IOException ) { // Should we do this only for ERROR_SHARING_VIOLATION? //if (UnsafeNativeMethods.MakeErrorCodeFromHR(Marshal.GetHRForException(ioexc)) != InternalResources.ERROR_SHARING_VIOLATION) break; string fileNameWithoutExt = Path.GetFileNameWithoutExtension(fileName); string fileExt = Path.GetExtension(fileName); path = fileNameWithoutExt + Guid.NewGuid().ToString() + fileExt; continue; } catch (UnauthorizedAccessException ) { //ERROR_ACCESS_DENIED, mostly ACL issues break; } catch (Exception ) { break; } } // Disable tracing to this listener. Every Write will be nop. // We need to think of a central way to deal with the listener // init errors in the future. The default should be that we eat // up any errors from listener and optionally notify the user if (traceWriter == null) fileName = null; } } return traceWriter != null; } private sealed class TraceWriter : TextWriter { Encoding encNoBOMwithFallback; Stream stream; private object m_lockObject = new object(); //// // [System.Security.SecurityCritical] internal TraceWriter(string _fileName, int bufferSize, TraceLogRetentionOption retention, long maxFileSize, int maxNumberOfFiles): base(CultureInfo.InvariantCulture) { stream = new LogStream(_fileName, bufferSize, (LogRetentionOption)retention, maxFileSize, maxNumberOfFiles); } // This is defined in TWTL as well, we should look into refactoring/relayering at a later time private static Encoding GetEncodingWithFallback(Encoding encoding) { // Clone it and set the "?" replacement fallback Encoding fallbackEncoding = (Encoding)encoding.Clone(); fallbackEncoding.EncoderFallback = EncoderFallback.ReplacementFallback; fallbackEncoding.DecoderFallback = DecoderFallback.ReplacementFallback; return fallbackEncoding; } public override Encoding Encoding { get { if (encNoBOMwithFallback == null) { lock (m_lockObject) { if (encNoBOMwithFallback == null) { // It is bad for tracing APIs to throw on encoding errors. Instead, we should // provide a "?" replacement fallback encoding to substitute illegal chars. // For ex, In case of high surrogate character D800-DBFF without a following // low surrogate character DC00-DFFF. We also need to use an encoding that // does't emit BOM whics is StreamWriter's default (for compatibility) encNoBOMwithFallback = GetEncodingWithFallback(new UTF8Encoding(false)); } } } return encNoBOMwithFallback; } } public override void Write(String value) { try { byte[] buffer = Encoding.GetBytes(value); stream.Write(buffer, 0, buffer.Length); } catch (Exception) { Debug.Assert(false, "UnExpected exc! Possible encoding error or failure on write! DATA LOSS!!!"); if (stream is BufferedStream2) { ((BufferedStream2)stream).DiscardBuffer(); } } } public override void Flush() { stream.Flush(); } protected override void Dispose(bool disposing) { try { if (disposing) stream.Close(); } finally { base.Dispose(disposing); // Essentially no-op } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- using System; using Microsoft.Win32; using System.Text; using System.IO; using System.Globalization; using System.Collections; using System.Threading; using System.Security.Permissions; using System.Runtime.Versioning; namespace System.Diagnostics { [HostProtection(Synchronization=true)] [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public class EventSchemaTraceListener : TextWriterTraceListener { private const string s_optionBufferSize = "bufferSize"; private const string s_optionLogRetention = "logRetentionOption"; private const string s_optionMaximumFileSize = "maximumFileSize"; private const string s_optionMaximumNumberOfFiles = "maximumNumberOfFiles"; private const string s_userDataHeader = ""; private const string s_eventHeader = " "); } BuildFooter(writer, eventType, eventCache, true, this.TraceOutputOptions); _InternalWriteRaw(writer); } //TraceLogRetentionOption.SingleFileBoundedSize) throw new ArgumentOutOfRangeException(s_optionLogRetention, SR.GetString(SR.ArgumentOutOfRange_NeedValidLogRetention)); base.Name = name; this.fileName = fileName; if (!String.IsNullOrEmpty(this.fileName) && (fileName[0] != Path.DirectorySeparatorChar) && (fileName[0] != Path.AltDirectorySeparatorChar) && !Path.IsPathRooted(fileName)) { this.fileName = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile), this.fileName); } this._retention = logRetentionOption; this._bufferSize = bufferSize; _SetMaxFileSize(maximumFileSize, false); _SetMaxNumberOfFiles(maximumNumberOfFiles, false); } // Hide base class version new public TextWriter Writer { // // [System.Security.SecurityCritical] get { EnsureWriter(); return traceWriter; } set { throw new NotSupportedException(SR.GetString(SR.NotSupported_SetTextWriter)); } } public override bool IsThreadSafe { get { return true; } } public int BufferSize { get { Init(); return _bufferSize; } } public TraceLogRetentionOption TraceLogRetentionOption { get { Init(); return _retention; } } public long MaximumFileSize { get { Init(); return _maxFileSize; } } public int MaximumNumberOfFiles { get { Init(); return _maxNumberOfFiles; } } public override void Close() { try { if (traceWriter != null) { traceWriter.Flush(); traceWriter.Close(); } } finally { traceWriter = null; //fileName = null; // It is more useful to allow the listener to be reopened upon subsequent write base.Close(); // This should be No-op } } //// // [System.Security.SecurityCritical] public override void Flush() { if (!EnsureWriter()) return; traceWriter.Flush(); } public override void Write(string message) { this.WriteLine(message); } public override void WriteLine(string message) { this.TraceEvent(null, SR.GetString(SR.TraceAsTraceSource), TraceEventType.Information, 0, message); } public override void Fail(string message, string detailMessage) { StringBuilder failMessage = new StringBuilder(message); if (detailMessage != null) { failMessage.Append(" "); failMessage.Append(detailMessage); } this.TraceEvent(null, SR.GetString(SR.TraceAsTraceSource), TraceEventType.Error, 0, failMessage.ToString()); } //// // [System.Security.SecurityCritical] public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, int id, string format, params object[] args) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, format, args, null, null)) return; StringBuilder writer = new StringBuilder(s_defaultPayloadSize); BuildHeader(writer, source, eventType, id, eventCache, null, false, this.TraceOutputOptions); string message; if (args != null) message = String.Format(CultureInfo.InvariantCulture, format, args); else message = format; BuildMessage(writer, message); BuildFooter(writer, eventType, eventCache, false, this.TraceOutputOptions); _InternalWriteRaw(writer); } //// // // [System.Security.SecurityCritical] public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, int id, string message) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, message, null, null, null)) return; StringBuilder writer = new StringBuilder(s_defaultPayloadSize); BuildHeader(writer, source, eventType, id, eventCache, null, false, this.TraceOutputOptions); BuildMessage(writer, message); BuildFooter(writer, eventType, eventCache, false, this.TraceOutputOptions); _InternalWriteRaw(writer); } //// // // [System.Security.SecurityCritical] public override void TraceData(TraceEventCache eventCache, String source, TraceEventType eventType, int id, object data) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null)) return; StringBuilder writer = new StringBuilder(s_defaultPayloadSize); BuildHeader(writer, source, eventType, id, eventCache, null, true, this.TraceOutputOptions); // No validation of user provided data. No explicit namespace scope. The data should identify the XML schema by itself. if (data != null) { _InternalBuildRaw(writer, s_userDataHeader); BuildUserData(writer, data); _InternalBuildRaw(writer, "// // // [System.Security.SecurityCritical] public override void TraceData(TraceEventCache eventCache, String source, TraceEventType eventType, int id, params object[] data) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, null, null, null, data)) return; StringBuilder writer = new StringBuilder(s_defaultPayloadSize); BuildHeader(writer, source, eventType, id, eventCache, null, true, this.TraceOutputOptions); // No validation of user provided data. No explicit namespace scope. The data should identify the XML schema by itself. if ((data != null) && (data.Length > 0)) { _InternalBuildRaw(writer, s_userDataHeader); for (int i=0; i// // "); } BuildFooter(writer, eventType, eventCache, true, this.TraceOutputOptions); _InternalWriteRaw(writer); } // // [System.Security.SecurityCritical] public override void TraceTransfer(TraceEventCache eventCache, String source, int id, string message, Guid relatedActivityId) { StringBuilder writer = new StringBuilder(s_defaultPayloadSize); BuildHeader(writer, source, TraceEventType.Transfer, id, eventCache, relatedActivityId.ToString("B"), false, this.TraceOutputOptions); BuildMessage(writer, message); BuildFooter(writer, TraceEventType.Transfer, eventCache, false, this.TraceOutputOptions); _InternalWriteRaw(writer); } private static void BuildMessage(StringBuilder writer, string message) { _InternalBuildRaw(writer, ""); BuildEscaped(writer, message); _InternalBuildRaw(writer, ""); } // Writes the system properties //// // // [System.Security.SecurityCritical] private static void BuildHeader(StringBuilder writer, String source, TraceEventType eventType, int id, TraceEventCache eventCache, string relatedActivityId, bool isUserData, TraceOptions opts) { _InternalBuildRaw(writer, s_eventHeader); // Ideally, we want to enable provider guid at the TraceSource level // We can't blindly use the source param here as we need to a valid guid! //_InternalBuildRaw(writer, source); // For now, trace empty guid for provider id _InternalBuildRaw(writer, "{00000000-0000-0000-0000-000000000000}"); _InternalBuildRaw(writer, "\"/>// "); _InternalBuildRaw(writer, ((uint)((id <0)?0:id)).ToString(CultureInfo.InvariantCulture)); _InternalBuildRaw(writer, " "); _InternalBuildRaw(writer, ""); int sev = (int)eventType; int op = sev; // Treat overflow conditions as Information // Logical operation events (>255) such as Start/Stop will fall into this bucket if ((sev > 255) || (sev < 0)) sev = 0x08; _InternalBuildRaw(writer, sev.ToString(CultureInfo.InvariantCulture)); _InternalBuildRaw(writer, " "); // Logical operation events (>255) such as Start/Stop will be morphed into a byte value if (op > 255) { op /= 256; _InternalBuildRaw(writer, ""); _InternalBuildRaw(writer, op.ToString(CultureInfo.InvariantCulture)); _InternalBuildRaw(writer, " "); } if ((TraceOptions.DateTime & opts) != 0) { _InternalBuildRaw(writer, ""); } // Currently correlation is always traced, we could optimize this further _InternalBuildRaw(writer, " "); // Currently not tracing ProcessName as there is no place for it in the SystemProperties // Should we bother adding this to our own section? if (eventCache != null && ((TraceOptions.ProcessId | TraceOptions.ThreadId) & opts) != 0) { _InternalBuildRaw(writer, " "); } //_InternalBuildRaw(writer, " "); _InternalBuildRaw(writer, " "); _InternalBuildRaw(writer, machineName); _InternalBuildRaw(writer, " "); _InternalBuildRaw(writer, ""); if (!isUserData) { _InternalBuildRaw(writer, ""); } else { _InternalBuildRaw(writer, " "); } else { _InternalBuildRaw(writer, ""); } // Provide English resource string for EventType _InternalBuildRaw(writer, ""); } } private static void BuildFooter(StringBuilder writer, TraceEventType eventType, TraceEventCache eventCache, bool isUserData, TraceOptions opts) { if (!isUserData) { _InternalBuildRaw(writer, " "); //Avoid Enum.ToString which uses reflection switch (eventType) { case TraceEventType.Critical: _InternalBuildRaw(writer, " "); // Custom System.Diagnostics information as its own schema if (eventCache != null && ((TraceOptions.LogicalOperationStack | TraceOptions.Callstack | TraceOptions.Timestamp) & opts) != 0) { _InternalBuildRaw(writer, "Critical "); break; case TraceEventType.Error: _InternalBuildRaw(writer, "Error "); break; case TraceEventType.Warning: _InternalBuildRaw(writer, "Warning "); break; case TraceEventType.Information: _InternalBuildRaw(writer, "Information "); break; case TraceEventType.Verbose: _InternalBuildRaw(writer, "Verbose "); break; case TraceEventType.Start: _InternalBuildRaw(writer, "Information Start "); break; case TraceEventType.Stop: _InternalBuildRaw(writer, "Information Stop "); break; case TraceEventType.Suspend: _InternalBuildRaw(writer, "Information Suspend "); break; case TraceEventType.Resume: _InternalBuildRaw(writer, "Information Resume "); break; case TraceEventType.Transfer: _InternalBuildRaw(writer, "Information Transfer "); break; default: break; } _InternalBuildRaw(writer, ""); if ((TraceOptions.Timestamp & opts) != 0) { _InternalBuildRaw(writer, " "); } _InternalBuildRaw(writer, ""); } private static void BuildEscaped(StringBuilder writer, string str) { if (str == null) return; int lastIndex = 0; for (int i=0; i"); _InternalBuildRaw(writer, eventCache.Timestamp.ToString(CultureInfo.InvariantCulture)); _InternalBuildRaw(writer, " "); } if ((TraceOptions.LogicalOperationStack & opts) != 0) { Stack stk = eventCache.LogicalOperationStack as Stack; _InternalBuildRaw(writer, ""); if ((stk != null) && (stk.Count > 0)) { foreach (object obj in stk) { _InternalBuildRaw(writer, " "); } if ((TraceOptions.Callstack & opts) != 0) { _InternalBuildRaw(writer, ""); BuildEscaped(writer, obj.ToString()); _InternalBuildRaw(writer, " "); } } _InternalBuildRaw(writer, ""); BuildEscaped(writer, eventCache.Callstack); _InternalBuildRaw(writer, " "); } _InternalBuildRaw(writer, "': _InternalBuildRaw(writer, str.Substring(lastIndex, i-lastIndex)); _InternalBuildRaw(writer, ">"); lastIndex = i +1; break; case '"': _InternalBuildRaw(writer, str.Substring(lastIndex, i-lastIndex)); _InternalBuildRaw(writer, """); lastIndex = i +1; break; case '\'': _InternalBuildRaw(writer, str.Substring(lastIndex, i-lastIndex)); _InternalBuildRaw(writer, "'"); lastIndex = i +1; break; case (char)0xD: _InternalBuildRaw(writer, str.Substring(lastIndex, i-lastIndex)); _InternalBuildRaw(writer, " "); lastIndex = i +1; break; case (char)0xA: _InternalBuildRaw(writer, str.Substring(lastIndex, i-lastIndex)); _InternalBuildRaw(writer, " "); lastIndex = i +1; break; } } _InternalBuildRaw(writer, str.Substring(lastIndex, str.Length-lastIndex)); } // Special case UnescapedXmlDiagnosticData items to write out XML blob unescaped private static void BuildUserData(StringBuilder writer, object data) { UnescapedXmlDiagnosticData xmlBlob = data as UnescapedXmlDiagnosticData; if(xmlBlob == null) { BuildMessage(writer, data.ToString()); } else { _InternalBuildRaw(writer, xmlBlob.ToString()); } } private static void _InternalBuildRaw(StringBuilder writer, string message) { writer.Append(message); } // // [System.Security.SecurityCritical] private void _InternalWriteRaw(StringBuilder writer) { if (!EnsureWriter()) return; // NeedIndent is nop traceWriter.Write(writer.ToString()); } protected override string[] GetSupportedAttributes() { return new String[]{s_optionBufferSize, s_optionLogRetention, s_optionMaximumFileSize, s_optionMaximumNumberOfFiles}; } private void Init() { if (!_initialized) { // We could use Interlocked but this one time overhead is probably not a concern lock (m_lockObject) { if (!_initialized) { try { if (Attributes.ContainsKey(s_optionBufferSize)) { int bufferSize = Int32.Parse(Attributes[s_optionBufferSize], CultureInfo.InvariantCulture); if (bufferSize > 0) _bufferSize = bufferSize; } if (Attributes.ContainsKey(s_optionLogRetention)) { // Enum.Parse is costly! string retOption = Attributes[s_optionLogRetention]; if (String.Compare(retOption, "SingleFileUnboundedSize", StringComparison.OrdinalIgnoreCase) == 0) _retention = TraceLogRetentionOption.SingleFileUnboundedSize; else if (String.Compare(retOption, "LimitedCircularFiles", StringComparison.OrdinalIgnoreCase) == 0) _retention = TraceLogRetentionOption.LimitedCircularFiles; else if (String.Compare(retOption, "UnlimitedSequentialFiles", StringComparison.OrdinalIgnoreCase) == 0) _retention = TraceLogRetentionOption.UnlimitedSequentialFiles; else if (String.Compare(retOption, "SingleFileBoundedSize", StringComparison.OrdinalIgnoreCase) == 0) _retention = TraceLogRetentionOption.SingleFileBoundedSize; else if (String.Compare(retOption, "LimitedSequentialFiles", StringComparison.OrdinalIgnoreCase) == 0) _retention = TraceLogRetentionOption.LimitedSequentialFiles; else { _retention = TraceLogRetentionOption.SingleFileUnboundedSize; } } if (Attributes.ContainsKey(s_optionMaximumFileSize)) { long maxFileSize = Int64.Parse(Attributes[s_optionMaximumFileSize], CultureInfo.InvariantCulture); _SetMaxFileSize(maxFileSize, false); } if (Attributes.ContainsKey(s_optionMaximumNumberOfFiles)) { int maxNumberOfFiles = Int32.Parse(Attributes[s_optionMaximumNumberOfFiles], CultureInfo.InvariantCulture); _SetMaxNumberOfFiles(maxNumberOfFiles, false); } } catch(Exception) { // Avoid trhowing errors from populating config values, let the defaults stand Debug.Assert(false, "Exception while populating config values for EventSchemaTraceListener!"); } finally { _initialized = true; } } } } } private void _SetMaxFileSize(long maximumFileSize, bool throwOnError) { switch (this._retention) { case TraceLogRetentionOption.SingleFileUnboundedSize: this._maxFileSize = -1; break; case TraceLogRetentionOption.SingleFileBoundedSize: case TraceLogRetentionOption.UnlimitedSequentialFiles: case TraceLogRetentionOption.LimitedSequentialFiles: case TraceLogRetentionOption.LimitedCircularFiles: if ((maximumFileSize < 0) && throwOnError) throw new ArgumentOutOfRangeException(s_optionMaximumFileSize, SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNum)); if (maximumFileSize < this._bufferSize) { if (throwOnError) { throw new ArgumentOutOfRangeException(s_optionMaximumFileSize, SR.GetString(SR.ArgumentOutOfRange_NeedMaxFileSizeGEBufferSize)); } else { this._maxFileSize = this._bufferSize; } } else this._maxFileSize = maximumFileSize; break; } } private void _SetMaxNumberOfFiles(int maximumNumberOfFiles, bool throwOnError) { switch (this._retention) { case TraceLogRetentionOption.SingleFileUnboundedSize: case TraceLogRetentionOption.SingleFileBoundedSize: this._maxNumberOfFiles = 1; break; case TraceLogRetentionOption.UnlimitedSequentialFiles: this._maxNumberOfFiles = -1; break; case TraceLogRetentionOption.LimitedSequentialFiles: if (maximumNumberOfFiles < 1) { if (throwOnError) { throw new ArgumentOutOfRangeException(s_optionMaximumNumberOfFiles, SR.GetString(SR.ArgumentOutOfRange_NeedValidMaxNumFiles, 1)); } this._maxNumberOfFiles = 1; } else { this._maxNumberOfFiles = maximumNumberOfFiles; } break; case TraceLogRetentionOption.LimitedCircularFiles: if (maximumNumberOfFiles < 2) { if (throwOnError) { throw new ArgumentOutOfRangeException(s_optionMaximumNumberOfFiles, SR.GetString(SR.ArgumentOutOfRange_NeedValidMaxNumFiles, 2)); } this._maxNumberOfFiles = 2; } else { this._maxNumberOfFiles = maximumNumberOfFiles; } break; } } // This uses a machine resource, scoped by the fileName variable. [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] //// // [System.Security.SecurityCritical] private bool EnsureWriter() { if (traceWriter == null) { if (String.IsNullOrEmpty(fileName)) return false; // We could use Interlocked but this one time overhead is probably not a concern lock (m_lockObject) { if (traceWriter != null) return true; // To support multiple appdomains/instances tracing to the same file, // we will try to open the given file for append but if we encounter // IO errors, we will suffix the file name with a unique GUID value // and try one more time string path = fileName; for (int i=0; i<_retryThreshold; i++) { try { Init(); traceWriter = new TraceWriter(path, _bufferSize, _retention, _maxFileSize, _maxNumberOfFiles); break; } catch (IOException ) { // Should we do this only for ERROR_SHARING_VIOLATION? //if (UnsafeNativeMethods.MakeErrorCodeFromHR(Marshal.GetHRForException(ioexc)) != InternalResources.ERROR_SHARING_VIOLATION) break; string fileNameWithoutExt = Path.GetFileNameWithoutExtension(fileName); string fileExt = Path.GetExtension(fileName); path = fileNameWithoutExt + Guid.NewGuid().ToString() + fileExt; continue; } catch (UnauthorizedAccessException ) { //ERROR_ACCESS_DENIED, mostly ACL issues break; } catch (Exception ) { break; } } // Disable tracing to this listener. Every Write will be nop. // We need to think of a central way to deal with the listener // init errors in the future. The default should be that we eat // up any errors from listener and optionally notify the user if (traceWriter == null) fileName = null; } } return traceWriter != null; } private sealed class TraceWriter : TextWriter { Encoding encNoBOMwithFallback; Stream stream; private object m_lockObject = new object(); //// // [System.Security.SecurityCritical] internal TraceWriter(string _fileName, int bufferSize, TraceLogRetentionOption retention, long maxFileSize, int maxNumberOfFiles): base(CultureInfo.InvariantCulture) { stream = new LogStream(_fileName, bufferSize, (LogRetentionOption)retention, maxFileSize, maxNumberOfFiles); } // This is defined in TWTL as well, we should look into refactoring/relayering at a later time private static Encoding GetEncodingWithFallback(Encoding encoding) { // Clone it and set the "?" replacement fallback Encoding fallbackEncoding = (Encoding)encoding.Clone(); fallbackEncoding.EncoderFallback = EncoderFallback.ReplacementFallback; fallbackEncoding.DecoderFallback = DecoderFallback.ReplacementFallback; return fallbackEncoding; } public override Encoding Encoding { get { if (encNoBOMwithFallback == null) { lock (m_lockObject) { if (encNoBOMwithFallback == null) { // It is bad for tracing APIs to throw on encoding errors. Instead, we should // provide a "?" replacement fallback encoding to substitute illegal chars. // For ex, In case of high surrogate character D800-DBFF without a following // low surrogate character DC00-DFFF. We also need to use an encoding that // does't emit BOM whics is StreamWriter's default (for compatibility) encNoBOMwithFallback = GetEncodingWithFallback(new UTF8Encoding(false)); } } } return encNoBOMwithFallback; } } public override void Write(String value) { try { byte[] buffer = Encoding.GetBytes(value); stream.Write(buffer, 0, buffer.Length); } catch (Exception) { Debug.Assert(false, "UnExpected exc! Possible encoding error or failure on write! DATA LOSS!!!"); if (stream is BufferedStream2) { ((BufferedStream2)stream).DiscardBuffer(); } } } public override void Flush() { stream.Flush(); } protected override void Dispose(bool disposing) { try { if (disposing) stream.Close(); } finally { base.Dispose(disposing); // Essentially no-op } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.//
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AccessKeyManager.cs
- SafeArrayTypeMismatchException.cs
- ExpressionBindings.cs
- Highlights.cs
- SafeEventLogWriteHandle.cs
- PictureBoxDesigner.cs
- ConsoleEntryPoint.cs
- InternalEnumValidator.cs
- Point3DCollectionConverter.cs
- GradientSpreadMethodValidation.cs
- ClientSettings.cs
- ObjectNotFoundException.cs
- PackWebRequestFactory.cs
- ColumnHeader.cs
- EntityCommandCompilationException.cs
- OperationAbortedException.cs
- TextCompositionManager.cs
- DataGridViewTextBoxCell.cs
- ComboBox.cs
- ObjectViewFactory.cs
- HtmlInputReset.cs
- filewebrequest.cs
- CharEnumerator.cs
- OpenTypeLayout.cs
- Calendar.cs
- TemplateComponentConnector.cs
- RegexNode.cs
- ServiceProviders.cs
- ByteStream.cs
- IsolationInterop.cs
- WpfKnownType.cs
- DirectionalLight.cs
- EntityProviderServices.cs
- SimpleMailWebEventProvider.cs
- StreamWriter.cs
- XmlSignificantWhitespace.cs
- PlaceHolder.cs
- SurrogateChar.cs
- TemplatePartAttribute.cs
- PersistenceTask.cs
- RoleManagerModule.cs
- DrawingContextDrawingContextWalker.cs
- FilterQuery.cs
- ParameterBuilder.cs
- DataGridCell.cs
- BCLDebug.cs
- Types.cs
- PersonalizationProviderCollection.cs
- AppDomainResourcePerfCounters.cs
- WrapPanel.cs
- PkcsMisc.cs
- LoginDesigner.cs
- StateDesigner.cs
- DataGridLength.cs
- DataSourceXmlSubItemAttribute.cs
- ProtocolsConfigurationHandler.cs
- SerializationHelper.cs
- XmlSchemaInfo.cs
- CacheDict.cs
- CharacterHit.cs
- DesigntimeLicenseContext.cs
- WindowsHyperlink.cs
- ListItemCollection.cs
- EntityUtil.cs
- DataGridViewCellEventArgs.cs
- SelectionChangedEventArgs.cs
- DefaultPrintController.cs
- PersonalizationStateInfoCollection.cs
- ExeContext.cs
- FieldBuilder.cs
- Drawing.cs
- CapabilitiesPattern.cs
- CurrentChangingEventManager.cs
- XmlUnspecifiedAttribute.cs
- SimpleTableProvider.cs
- CalculatedColumn.cs
- VectorCollectionValueSerializer.cs
- ThaiBuddhistCalendar.cs
- RawStylusInputCustomDataList.cs
- ResourceType.cs
- Socket.cs
- Rectangle.cs
- PhonemeConverter.cs
- AdCreatedEventArgs.cs
- ModifierKeysValueSerializer.cs
- OracleRowUpdatedEventArgs.cs
- AndCondition.cs
- XPathException.cs
- TemplateAction.cs
- Tool.cs
- DataSourceListEditor.cs
- DataError.cs
- URIFormatException.cs
- MouseEventArgs.cs
- MetadataCollection.cs
- TextCollapsingProperties.cs
- SystemException.cs
- EventsTab.cs
- DynamicValueConverter.cs
- LoginUtil.cs