将Root元素添加到XML log4net

时间:2019-04-16 11:55:10

标签: c# xml log4net

我尝试使用log4net创建XML日志文件,它成功创建了日志,但是没有根元素

我的问题如何创建根元素

<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
      <file value="logger.xml" type="log4net.Util.PatternString" />
      <appendToFile value="true"/>
      <rollingStyle value="Size"/>
      <maxSizeRollBackups value="20"/>
      <maximumFileSize value="10000KB"/>
      <staticLogFileName value="true"/>
      <preserveLogFileNameExtension value="true" />
      <layout type="Log4net1.CustomXmlLayoutSchemaLog4j">
        <locationInfo value="true" />
      </layout>
    </appender>
<event logger="SomeName2" time="4/16/2019 2:45:15 PM" level="ERROR" thread="1"><message>Exception Caught: </message><properties><data name="log4jmachinename" value="IbrahimS-LPT" /><data name="log4japp" value="Log4net.exe" /><data name="log4net:Identity" value="" /><data name="log4net:UserName" value="SSS-PROCESS\ibrahims" /><data name="log4net:HostName" value="IbrahimS-LPT" /></properties><throwable>System.InvalidCastException: hhhhh ---&gt; System.Exception: sub
   --- End of inner exception stack trace ---</throwable><locationInfo class="Log4net.LoggingHelper" method="LogError" file="" line="0" /></event>
<event logger="SomeName2" time="4/16/2019 2:45:15 PM" level="ERROR" thread="1"><message>Exception Caught: </message><properties><data name="log4jmachinename" value="IbrahimS-LPT" /><data name="log4japp" value="Log4net.exe" /><data name="log4net:Identity" value="" /><data name="log4net:UserName" value="SSS-PROCESS\ibrahims" /><data name="log4net:HostName" value="IbrahimS-LPT" /></properties><throwable>System.InvalidCastException: hhhhh ---&gt; System.Exception: sub
   --- End of inner exception stack trace ---</throwable><locationInfo class="Log4net.LoggingHelper" method="LogError" file="" line="0" /></event>

当尝试以xml格式打开文件时,出现此错误,无法解析任何XML输入

但是当手动添加根元素时,我可以查看

我需要像这样

<app>
<event logger="SomeName2" time="4/16/2019 2:45:15 PM" level="ERROR" thread="1"></event>
<event logger="SomeName2" time="4/16/2019 2:45:15 PM" level="ERROR" thread="1"></event>
</app>
class CustomXmlLayoutSchemaLog4j : 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 CustomXmlLayoutSchemaLog4j() : 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 CustomXmlLayoutSchemaLog4j(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
<event logger="first logger" level="ERROR" thread="Thread-3" timestamp="1051494121460">
  <message><![CDATA[errormsg 3]]></message>
  <NDC><![CDATA[third]]></NDC>
  <MDC>
    <data name="some string" value="some valuethird"/>
  </MDC>
  <throwable><![CDATA[java.lang.Exception: someexception-third
    at org.apache.log4j.chainsaw.Generator.run(Generator.java:94)
]]></throwable>
  <locationInfo class="org.apache.log4j.chainsaw.Generator"
method="run" file="Generator.java" line="94"/>
  <properties>
    <data name="log4jmachinename" value="windows"/>
    <data name="log4japp" value="udp-generator"/>
  </properties>
</event>
        */

        /* Since log4j 1.3 the MDC has been combined into the 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
            Header = "App";
            // 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("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("time", DateTime.Now.ToString());
            writer.WriteAttributeString("level", loggingEvent.Level.DisplayName);
            writer.WriteAttributeString("thread", loggingEvent.ThreadName);

            // Append the message text
            writer.WriteStartElement("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("NDC");
                    Transform.WriteEscapedXmlString(writer, valueStr, this.InvalidCharReplacement);
                    writer.WriteEndElement();
                }
            }

            // Append the properties text
            PropertiesDictionary properties = loggingEvent.GetProperties();
            if (properties.Count > 0)
            {
                writer.WriteStartElement("properties");
                foreach (System.Collections.DictionaryEntry entry in properties)
                {
                    writer.WriteStartElement("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("throwable");
                Transform.WriteEscapedXmlString(writer, exceptionStr, this.InvalidCharReplacement);
                writer.WriteEndElement();
            }

            if (LocationInfo)
            {
                LocationInfo locationInfo = loggingEvent.LocationInformation;

                writer.WriteStartElement("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();
        }
    }

1 个答案:

答案 0 :(得分:0)

您需要做的是下一个:

在这部分代码之前:

// Write the start element
writer.WriteStartElement("event");
writer.WriteAttributeString("logger", loggingEvent.LoggerName);

您需要添加以下行:

writer.WriteStartElement("App");

另外,在当前代码中的最后一个后面添加一个writer.WriteEndElement();

因此您的代码将如下所示:

// Write the start element
writer.WriteStartElement("App");
writer.WriteStartElement("event");
writer.WriteAttributeString("logger", loggingEvent.LoggerName);
.
.
.
.
writer.WriteEndElement();
writer.WriteEndElement();