/// <summary> /// Gets the exception text from the logging event /// </summary> /// <param name="writer">The TextWriter to write the formatted event to</param> /// <param name="loggingEvent">the event being logged</param> /// <remarks> /// <para> /// Write the exception string to the <see cref="TextWriter"/>. /// The exception string is retrieved from <see cref="LoggingEvent.GetExceptionString()"/>. /// </para> /// </remarks> override public void Format(TextWriter writer, LoggingEvent loggingEvent) { if (loggingEvent == null) { throw new ArgumentNullException("loggingEvent"); } writer.Write(loggingEvent.GetExceptionString()); }
/// <summary> /// Does the actual writing of the XML. /// </summary> /// <param name="writer">The writer to use to output the event to.</param> /// <param name="loggingEvent">The event to write.</param> /// <remarks> /// <para> /// Override the base class <see cref="XmlLayoutBase.FormatXml"/> method /// to write the <see cref="LoggingEvent"/> to the <see cref="XmlWriter"/>. /// </para> /// </remarks> override protected void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) { writer.WriteStartElement(m_elmEvent); writer.WriteAttributeString(ATTR_LOGGER, loggingEvent.LoggerName); #if NET_2_0 || NETCF_2_0 || MONO_2_0 writer.WriteAttributeString(ATTR_TIMESTAMP, XmlConvert.ToString(loggingEvent.TimeStamp, XmlDateTimeSerializationMode.Local)); #else writer.WriteAttributeString(ATTR_TIMESTAMP, XmlConvert.ToString(loggingEvent.TimeStamp)); #endif writer.WriteAttributeString(ATTR_LEVEL, loggingEvent.Level.DisplayName); writer.WriteAttributeString(ATTR_THREAD, loggingEvent.ThreadName); if (loggingEvent.Domain != null && loggingEvent.Domain.Length > 0) { writer.WriteAttributeString(ATTR_DOMAIN, loggingEvent.Domain); } if (loggingEvent.Identity != null && loggingEvent.Identity.Length > 0) { writer.WriteAttributeString(ATTR_IDENTITY, loggingEvent.Identity); } if (loggingEvent.UserName != null && loggingEvent.UserName.Length > 0) { writer.WriteAttributeString(ATTR_USERNAME, loggingEvent.UserName); } // Append the message text writer.WriteStartElement(m_elmMessage); if (!this.Base64EncodeMessage) { Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, this.InvalidCharReplacement); } else { byte[] messageBytes = Encoding.UTF8.GetBytes(loggingEvent.RenderedMessage); string base64Message = Convert.ToBase64String(messageBytes, 0, messageBytes.Length); Transform.WriteEscapedXmlString(writer, base64Message, this.InvalidCharReplacement); } writer.WriteEndElement(); PropertiesDictionary properties = loggingEvent.GetProperties(); // Append the properties text if (properties.Count > 0) { writer.WriteStartElement(m_elmProperties); foreach (System.Collections.DictionaryEntry entry in properties) { writer.WriteStartElement(m_elmData); writer.WriteAttributeString(ATTR_NAME, Transform.MaskXmlInvalidCharacters((string)entry.Key, this.InvalidCharReplacement)); // Use an ObjectRenderer to convert the object to a string string valueStr = null; if (!this.Base64EncodeProperties) { valueStr = Transform.MaskXmlInvalidCharacters(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value), this.InvalidCharReplacement); } else { byte[] propertyValueBytes = Encoding.UTF8.GetBytes(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value)); valueStr = Convert.ToBase64String(propertyValueBytes, 0, propertyValueBytes.Length); } writer.WriteAttributeString(ATTR_VALUE, valueStr); writer.WriteEndElement(); } writer.WriteEndElement(); } string exceptionStr = loggingEvent.GetExceptionString(); if (exceptionStr != null && exceptionStr.Length > 0) { // Append the stack trace line writer.WriteStartElement(m_elmException); Transform.WriteEscapedXmlString(writer, exceptionStr, this.InvalidCharReplacement); writer.WriteEndElement(); } if (LocationInfo) { LocationInfo locationInfo = loggingEvent.LocationInformation; writer.WriteStartElement(m_elmLocation); writer.WriteAttributeString(ATTR_CLASS, locationInfo.ClassName); writer.WriteAttributeString(ATTR_METHOD, locationInfo.MethodName); writer.WriteAttributeString(ATTR_FILE, locationInfo.FileName); writer.WriteAttributeString(ATTR_LINE, locationInfo.LineNumber); writer.WriteEndElement(); } writer.WriteEndElement(); }
/// <summary> /// Write the exception text to the output /// </summary> /// <param name="writer"><see cref="TextWriter" /> that will receive the formatted result.</param> /// <param name="loggingEvent">the event being logged</param> /// <remarks> /// <para> /// If an exception object is stored in the logging event /// it will be rendered into the pattern output with a /// trailing newline. /// </para> /// <para> /// If there is no exception or the exception property specified /// by the Option value does not exist then nothing will be output /// and no trailing newline will be appended. /// It is typical to put a newline before the exception /// and to have the exception as the last data in the pattern. /// </para> /// <para> /// Recognized values for the Option parameter are: /// </para> /// <list type="bullet"> /// <item> /// <description>Message</description> /// </item> /// <item> /// <description>Source</description> /// </item> /// <item> /// <description>StackTrace</description> /// </item> /// <item> /// <description>TargetSite</description> /// </item> /// <item> /// <description>HelpLink</description> /// </item> /// </list> /// </remarks> override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { if (loggingEvent.ExceptionObject != null && Option != null && Option.Length > 0) { switch (Option.ToLower()) { case "message": WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.Message); break; #if !NETCF case "source": WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.Source); break; case "stacktrace": WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.StackTrace); break; case "targetsite": WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.TargetSite); break; case "helplink": WriteObject(writer, loggingEvent.Repository, loggingEvent.ExceptionObject.HelpLink); break; #endif default: // do not output SystemInfo.NotAvailableText break; } } else { string exceptionString = loggingEvent.GetExceptionString(); if (exceptionString != null && exceptionString.Length > 0) { writer.WriteLine(exceptionString); } else { // do not output SystemInfo.NotAvailableText } } }
/// <summary> /// Renders the <see cref="LoggingEvent"/> to a string. /// </summary> /// <param name="loggingEvent">The event to render.</param> /// <param name="writer">The TextWriter to write the formatted event to</param> /// <remarks> /// <para> /// Helper method to render a <see cref="LoggingEvent"/> to /// a string. This appender must have a <see cref="Layout"/> /// set to render the <paramref name="loggingEvent"/> to /// a string. /// </para> /// <para>If there is exception data in the logging event and /// the layout does not process the exception, this method /// will append the exception text to the rendered string. /// </para> /// <para> /// Use this method in preference to <see cref="RenderLoggingEvent(LoggingEvent)"/> /// where possible. If, however, the caller needs to render the event /// to a string then <see cref="RenderLoggingEvent(LoggingEvent)"/> does /// provide an efficient mechanism for doing so. /// </para> /// </remarks> protected void RenderLoggingEvent(TextWriter writer, LoggingEvent loggingEvent) { if (m_layout == null) { throw new InvalidOperationException("A layout must be set"); } if (m_layout.IgnoresException) { string exceptionStr = loggingEvent.GetExceptionString(); if (exceptionStr != null && exceptionStr.Length > 0) { // render the event and the exception m_layout.Format(writer, loggingEvent); writer.WriteLine(exceptionStr); } else { // there is no exception to render m_layout.Format(writer, loggingEvent); } } else { // The layout will render the exception m_layout.Format(writer, loggingEvent); } }
/* Example log4j schema event <log4j:event logger="first logger" level="ERROR" thread="Thread-3" timestamp="1051494121460"> <log4j:message><![CDATA[errormsg 3]]></log4j:message> <log4j:NDC><![CDATA[third]]></log4j:NDC> <log4j:MDC> <log4j:data name="some string" value="some valuethird"/> </log4j:MDC> <log4j:throwable><![CDATA[java.lang.Exception: someexception-third at org.apache.log4j.chainsaw.Generator.run(Generator.java:94) ]]></log4j:throwable> <log4j:locationInfo class="org.apache.log4j.chainsaw.Generator" method="run" file="Generator.java" line="94"/> <log4j:properties> <log4j:data name="log4jmachinename" value="windows"/> <log4j:data name="log4japp" value="udp-generator"/> </log4j:properties> </log4j:event> */ /* Since log4j 1.3 the log4j:MDC has been combined into the log4j:properties element */ /// <summary> /// Actually do the writing of the xml /// </summary> /// <param name="writer">the writer to use</param> /// <param name="loggingEvent">the event to write</param> /// <remarks> /// <para> /// Generate XML that is compatible with the log4j schema. /// </para> /// </remarks> override protected void FormatXml(XmlWriter writer, LoggingEvent loggingEvent) { // Translate logging events for log4j // Translate hostname property if (loggingEvent.LookupProperty(LoggingEvent.HostNameProperty) != null && loggingEvent.LookupProperty("log4jmachinename") == null) { loggingEvent.GetProperties()["log4jmachinename"] = loggingEvent.LookupProperty(LoggingEvent.HostNameProperty); } // translate appdomain name if (loggingEvent.LookupProperty("log4japp") == null && loggingEvent.Domain != null && loggingEvent.Domain.Length > 0) { loggingEvent.GetProperties()["log4japp"] = loggingEvent.Domain; } // translate identity name if (loggingEvent.Identity != null && loggingEvent.Identity.Length > 0 && loggingEvent.LookupProperty(LoggingEvent.IdentityProperty) == null) { loggingEvent.GetProperties()[LoggingEvent.IdentityProperty] = loggingEvent.Identity; } // translate user name if (loggingEvent.UserName != null && loggingEvent.UserName.Length > 0 && loggingEvent.LookupProperty(LoggingEvent.UserNameProperty) == null) { loggingEvent.GetProperties()[LoggingEvent.UserNameProperty] = loggingEvent.UserName; } // Write the start element writer.WriteStartElement("log4j:event"); writer.WriteAttributeString("logger", loggingEvent.LoggerName); // Calculate the timestamp as the number of milliseconds since january 1970 // // We must convert the TimeStamp to UTC before performing any mathematical // operations. This allows use to take into account discontinuities // caused by daylight savings time transitions. TimeSpan timeSince1970 = loggingEvent.TimeStamp.ToUniversalTime() - s_date1970; writer.WriteAttributeString("timestamp", XmlConvert.ToString((long)timeSince1970.TotalMilliseconds)); writer.WriteAttributeString("level", loggingEvent.Level.DisplayName); writer.WriteAttributeString("thread", loggingEvent.ThreadName); // Append the message text writer.WriteStartElement("log4j:message"); Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, this.InvalidCharReplacement); writer.WriteEndElement(); object ndcObj = loggingEvent.LookupProperty("NDC"); if (ndcObj != null) { string valueStr = loggingEvent.Repository.RendererMap.FindAndRender(ndcObj); if (valueStr != null && valueStr.Length > 0) { // Append the NDC text writer.WriteStartElement("log4j:NDC"); Transform.WriteEscapedXmlString(writer, valueStr, this.InvalidCharReplacement); writer.WriteEndElement(); } } // Append the properties text PropertiesDictionary properties = loggingEvent.GetProperties(); if (properties.Count > 0) { writer.WriteStartElement("log4j:properties"); foreach (System.Collections.DictionaryEntry entry in properties) { writer.WriteStartElement("log4j:data"); writer.WriteAttributeString("name", (string)entry.Key); // Use an ObjectRenderer to convert the object to a string string valueStr = loggingEvent.Repository.RendererMap.FindAndRender(entry.Value); writer.WriteAttributeString("value", valueStr); writer.WriteEndElement(); } writer.WriteEndElement(); } string exceptionStr = loggingEvent.GetExceptionString(); if (exceptionStr != null && exceptionStr.Length > 0) { // Append the stack trace line writer.WriteStartElement("log4j:throwable"); Transform.WriteEscapedXmlString(writer, exceptionStr, this.InvalidCharReplacement); writer.WriteEndElement(); } if (LocationInfo) { LocationInfo locationInfo = loggingEvent.LocationInformation; writer.WriteStartElement("log4j:locationInfo"); writer.WriteAttributeString("class", locationInfo.ClassName); writer.WriteAttributeString("method", locationInfo.MethodName); writer.WriteAttributeString("file", locationInfo.FileName); writer.WriteAttributeString("line", locationInfo.LineNumber); writer.WriteEndElement(); } writer.WriteEndElement(); }