You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by bo...@apache.org on 2018/05/29 19:02:42 UTC
logging-log4net git commit: LOG4NET-586 first cut at a namespace
aware log4j XML layout
Repository: logging-log4net
Updated Branches:
refs/heads/feature/LOG4NET-586 aed08e074 -> 48dfe2864
LOG4NET-586 first cut at a namespace aware log4j XML layout
Project: http://git-wip-us.apache.org/repos/asf/logging-log4net/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4net/commit/48dfe286
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4net/tree/48dfe286
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4net/diff/48dfe286
Branch: refs/heads/feature/LOG4NET-586
Commit: 48dfe28642de31ca2087e34cbdb3ffde0ed8362e
Parents: aed08e0
Author: Stefan Bodewig <bo...@apache.org>
Authored: Tue May 29 21:01:59 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Tue May 29 21:01:59 2018 +0200
----------------------------------------------------------------------
src/Layout/XmlLayoutSchemaLog4jNS.cs | 282 ++++++++++++++++++++++++++++++
src/log4net.csproj | 3 +
2 files changed, 285 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/48dfe286/src/Layout/XmlLayoutSchemaLog4jNS.cs
----------------------------------------------------------------------
diff --git a/src/Layout/XmlLayoutSchemaLog4jNS.cs b/src/Layout/XmlLayoutSchemaLog4jNS.cs
new file mode 100644
index 0000000..aa7c33b
--- /dev/null
+++ b/src/Layout/XmlLayoutSchemaLog4jNS.cs
@@ -0,0 +1,282 @@
+#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 similar to the log4j 1.2 schema
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Formats the log events according to the
+ /// http://logging.apache.org/log4j schema and actually puts the
+ /// elements into a namespace. This may break tooling that doesn't
+ /// handle XML using namespaces.
+ /// </para>
+ /// </remarks>
+ /// <author>Nicko Cadell</author>
+ public class XmlLayoutSchemaLog4jNS : XmlLayoutBaseNS
+ {
+ #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 XMLLayoutSchemaLog4jNS
+ /// </summary>
+ public XmlLayoutSchemaLog4jNS() : base()
+ {
+ }
+
+ /// <summary>
+ /// Constructs an XMLLayoutSchemaLog4jNS.
+ /// </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 XmlLayoutSchemaLog4jNS(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");
+ }
+ }
+ }
+
+ /// <summary>
+ /// The namespace URI to use for the elements and attributes written by this layout.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Unless configured explicitly http://logging.apache.org/log4j is used.
+ /// </para>
+ /// </remarks>
+ public override string NamespaceUri
+ {
+ get { return base.NamespaceUri == null ? LOG4J_SCHEMA : base.NamespaceUri; }
+ }
+
+ /// <summary>
+ /// The prefix to use for the elements and attributes written by this layout.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Unless configured explicitly log4j is used.
+ /// </para>
+ /// </remarks>
+ public override string Prefix
+ {
+ get { return base.Prefix == null ? LOG4J_PREFIX : base.Prefix; }
+ }
+ #endregion
+
+ /* Example log4j schema event
+
+<log4j:event logger="first logger" level="ERROR" thread="Thread-3" timestamp="1051494121460" xmlns:log4j="http://logging.apache.org/log4j">
+ <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(Prefix, "event", NamespaceUri);
+ 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(Prefix, "message", NamespaceUri);
+ 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(Prefix, "NDC", NamespaceUri);
+ Transform.WriteEscapedXmlString(writer, valueStr,this.InvalidCharReplacement);
+ writer.WriteEndElement();
+ }
+ }
+
+ // Append the properties text
+ PropertiesDictionary properties = loggingEvent.GetProperties();
+ if (properties.Count > 0)
+ {
+ writer.WriteStartElement(Prefix, "properties", NamespaceUri);
+ foreach(System.Collections.DictionaryEntry entry in properties)
+ {
+ writer.WriteStartElement(Prefix, "data", NamespaceUri);
+ 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(Prefix, "throwable", NamespaceUri);
+ Transform.WriteEscapedXmlString(writer, exceptionStr,this.InvalidCharReplacement);
+ writer.WriteEndElement();
+ }
+
+ if (LocationInfo)
+ {
+ LocationInfo locationInfo = loggingEvent.LocationInformation;
+
+ writer.WriteStartElement(Prefix, "locationInfo", NamespaceUri);
+ writer.WriteAttributeString("class", locationInfo.ClassName);
+ writer.WriteAttributeString("method", locationInfo.MethodName);
+ writer.WriteAttributeString("file", locationInfo.FileName);
+ writer.WriteAttributeString("line", locationInfo.LineNumber);
+ writer.WriteEndElement();
+ }
+
+ writer.WriteEndElement();
+ }
+
+ private const string LOG4J_SCHEMA = "http://logging.apache.org/log4j";
+ private const string LOG4J_PREFIX = "log4j";
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/48dfe286/src/log4net.csproj
----------------------------------------------------------------------
diff --git a/src/log4net.csproj b/src/log4net.csproj
index b638481..2b09c54 100644
--- a/src/log4net.csproj
+++ b/src/log4net.csproj
@@ -515,6 +515,9 @@
<Compile Include="Layout\XmlLayoutSchemaLog4j.cs">
<SubType>Code</SubType>
</Compile>
+ <Compile Include="Layout\XmlLayoutSchemaLog4jNS.cs">
+ <SubType>Code</SubType>
+ </Compile>
<Compile Include="LogicalThreadContext.cs">
<SubType>Code</SubType>
</Compile>