123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- #region Apache License
- //
- // Licensed to the Apache Software Foundation (ASF) under one or more
- // contributor license agreements. See the NOTICE file distributed with
- // this work for additional information regarding copyright ownership.
- // The ASF licenses this file to you under the Apache License, Version 2.0
- // (the "License"); you may not use this file except in compliance with
- // the License. You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- //
- #endregion
- using System;
- using System.Text;
- using System.Xml;
- using System.IO;
- using log4net.Core;
- using log4net.Util;
- namespace log4net.Layout
- {
- /// <summary>
- /// Layout that formats the log events as XML elements compatible with the log4j schema
- /// </summary>
- /// <remarks>
- /// <para>
- /// Formats the log events according to the http://logging.apache.org/log4j schema.
- /// </para>
- /// </remarks>
- /// <author>Nicko Cadell</author>
- public class XmlLayoutSchemaLog4j : XmlLayoutBase
- {
- #region Static Members
- /// <summary>
- /// The 1st of January 1970 in UTC
- /// </summary>
- private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1);
- #endregion
- #region Constructors
- /// <summary>
- /// Constructs an XMLLayoutSchemaLog4j
- /// </summary>
- public XmlLayoutSchemaLog4j() : base()
- {
- }
- /// <summary>
- /// Constructs an XMLLayoutSchemaLog4j.
- /// </summary>
- /// <remarks>
- /// <para>
- /// The <b>LocationInfo</b> option takes a boolean value. By
- /// default, it is set to false which means there will be no location
- /// information output by this layout. If the the option is set to
- /// true, then the file name and line number of the statement
- /// at the origin of the log statement will be output.
- /// </para>
- /// <para>
- /// If you are embedding this layout within an SMTPAppender
- /// then make sure to set the <b>LocationInfo</b> option of that
- /// appender as well.
- /// </para>
- /// </remarks>
- public XmlLayoutSchemaLog4j(bool locationInfo) : base(locationInfo)
- {
- }
- #endregion
- #region Public Properties
- /// <summary>
- /// The version of the log4j schema to use.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Only version 1.2 of the log4j schema is supported.
- /// </para>
- /// </remarks>
- public string Version
- {
- get { return "1.2"; }
- set
- {
- if (value != "1.2")
- {
- throw new ArgumentException("Only version 1.2 of the log4j schema is currently supported");
- }
- }
- }
- #endregion
- /* 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.TimeStampUtc - 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();
- }
- }
- }
|