LOG4NET-553 allow DebugAppender to skip category

Patch by Jean-Francois Beaulac 

diff --git a/netstandard/log4net.tests/log4net.tests.xproj b/netstandard/log4net.tests/log4net.tests.xproj
index 92eecae..604afde 100644
--- a/netstandard/log4net.tests/log4net.tests.xproj
+++ b/netstandard/log4net.tests/log4net.tests.xproj
@@ -32,6 +32,7 @@
     <Compile Include="../../tests/src/Appender/AppenderCollectionTest.cs" />
     <Compile Include="../../tests/src/Appender/BufferingAppenderTest.cs" />
     <Compile Include="../../tests/src/Appender/CountingAppender.cs" />
+    <Compile Include="../../tests/src/Appender/DebugAppenderTest.cs" />
     <Compile Include="../../tests/src/Appender/RollingFileAppenderTest.cs" />
     <Compile Include="../../tests/src/Appender/SmtpPickupDirAppenderTest.cs" />
     <Compile Include="../../tests/src/Appender/StringAppender.cs" />
diff --git a/netstandard/log4net.tests/project.json b/netstandard/log4net.tests/project.json
index 49af8d7..a7d9a86 100644
--- a/netstandard/log4net.tests/project.json
+++ b/netstandard/log4net.tests/project.json
@@ -6,6 +6,7 @@
       "../../tests/src/Appender/AppenderCollectionTest.cs",
       "../../tests/src/Appender/BufferingAppenderTest.cs",
       "../../tests/src/Appender/CountingAppender.cs",
+      "../../tests/src/Appender/DebugAppenderTest.cs",
       "../../tests/src/Appender/MemoryAppenderTest.cs",
       "../../tests/src/Appender/RollingFileAppenderTest.cs",
       "../../tests/src/Appender/SmtpPickupDirAppenderTest.cs",
diff --git a/src/Appender/DebugAppender.cs b/src/Appender/DebugAppender.cs
index 3cc5640..df6a618 100644
--- a/src/Appender/DebugAppender.cs
+++ b/src/Appender/DebugAppender.cs
@@ -100,6 +100,23 @@
 			set { m_immediateFlush = value; }
 		}
 
+        /// <summary>
+        /// Formats the category parameter sent to the Debug method.
+        /// </summary>
+        /// <remarks>
+        /// <para>
+        /// Defaults to a <see cref="Layout.PatternLayout"/> with %logger as the pattern which will use the logger name of the current 
+        /// <see cref="LoggingEvent"/> as the category parameter.
+        /// </para>
+        /// <para>
+        /// </para> 
+        /// </remarks>
+        public PatternLayout Category
+        {
+            get { return m_category; }
+            set { m_category = value; }
+        }
+ 
 		#endregion Public Instance Properties
 
 #if !NETSTANDARD1_3
@@ -138,7 +155,22 @@
 			//
 			// Write the string to the Debug system
 			//
-			System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent), loggingEvent.LoggerName);
+            if(m_category == null)
+            {
+                System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent));
+            }
+            else
+            {
+                string category = m_category.Format(loggingEvent);
+                if (string.IsNullOrEmpty(category))
+                {
+                    System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent));
+                }
+                else
+                {
+                    System.Diagnostics.Debug.Write(RenderLoggingEvent(loggingEvent), category);
+                }
+            }
 #if !NETSTANDARD1_3
 			//
 			// Flush the Debug system if needed
@@ -185,6 +217,11 @@
 		/// </remarks>
 		private bool m_immediateFlush = true;
 
+        /// <summary>
+        /// Defaults to a <see cref="Layout.PatternLayout"/> with %logger as the pattern.
+        /// </summary>
+        private PatternLayout m_category = new PatternLayout("%logger");
+
 		#endregion Private Instance Fields
 	}
 }
diff --git a/tests/src/Appender/DebugAppenderTest.cs b/tests/src/Appender/DebugAppenderTest.cs
new file mode 100644
index 0000000..53cb116
--- /dev/null
+++ b/tests/src/Appender/DebugAppenderTest.cs
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ *
+*/
+
+using System;
+using System.Diagnostics;
+using log4net.Appender;
+using log4net.Config;
+using log4net.Core;
+using log4net.Layout;
+using log4net.Repository;
+using NUnit.Framework;
+
+namespace log4net.Tests.Appender
+{
+    [TestFixture]
+    public class DebugAppenderTest
+    {
+        [Test]
+        public void NullCategoryTest()
+        {
+            CategoryTraceListener categoryTraceListener = new CategoryTraceListener();
+            Debug.Listeners.Add(categoryTraceListener);
+
+            ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
+
+            DebugAppender debugAppender = new DebugAppender();
+            debugAppender.Layout = new SimpleLayout();
+            debugAppender.ActivateOptions();
+
+            debugAppender.Category = null;
+
+            TestErrorHandler testErrHandler = new TestErrorHandler();
+            debugAppender.ErrorHandler = testErrHandler;            
+
+            BasicConfigurator.Configure(rep, debugAppender);
+
+            ILog log = LogManager.GetLogger(rep.Name, GetType());
+            log.Debug("Message");
+
+            Assert.AreEqual(
+                null,
+                categoryTraceListener.Category);
+
+            Assert.IsFalse(testErrHandler.ErrorOccured);
+
+            Debug.Listeners.Remove(categoryTraceListener);
+        }
+
+        [Test]
+        public void EmptyStringCategoryTest()
+        {
+            CategoryTraceListener categoryTraceListener = new CategoryTraceListener();
+            Debug.Listeners.Add(categoryTraceListener);
+
+            ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
+
+            DebugAppender debugAppender = new DebugAppender();
+            debugAppender.Layout = new SimpleLayout();
+            debugAppender.ActivateOptions();
+
+            debugAppender.Category = new PatternLayout("");
+
+            BasicConfigurator.Configure(rep, debugAppender);
+
+            ILog log = LogManager.GetLogger(rep.Name, GetType());
+            log.Debug("Message");
+
+            Assert.AreEqual(
+                null,
+                categoryTraceListener.Category);
+
+            Debug.Listeners.Remove(categoryTraceListener);
+        }
+
+        [Test]
+        public void DefaultCategoryTest()
+        {
+            CategoryTraceListener categoryTraceListener = new CategoryTraceListener();
+            Debug.Listeners.Add(categoryTraceListener);
+
+            ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
+
+            DebugAppender debugAppender = new DebugAppender();
+            debugAppender.Layout = new SimpleLayout();
+            debugAppender.ActivateOptions();
+
+            BasicConfigurator.Configure(rep, debugAppender);
+
+            ILog log = LogManager.GetLogger(rep.Name, GetType());
+            log.Debug("Message");
+
+            Assert.AreEqual(
+                GetType().ToString(),
+                categoryTraceListener.Category);
+
+            Debug.Listeners.Remove(categoryTraceListener);
+        }
+
+#if !NETSTANDARD1_3 // "LocationInfo can't get method names on NETSTANDARD1_3 due to unavailable stack frame APIs"
+        [Test]
+        public void MethodNameCategoryTest()
+        {
+            CategoryTraceListener categoryTraceListener = new CategoryTraceListener();
+            Debug.Listeners.Add(categoryTraceListener);
+
+            ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
+
+            DebugAppender debugAppender = new DebugAppender();
+            PatternLayout methodLayout = new PatternLayout("%method");
+            methodLayout.ActivateOptions();
+            debugAppender.Category = methodLayout;
+            debugAppender.Layout = new SimpleLayout();
+            debugAppender.ActivateOptions();
+
+            BasicConfigurator.Configure(rep, debugAppender);
+
+            ILog log = LogManager.GetLogger(rep.Name, GetType());
+            log.Debug("Message");
+
+            Assert.AreEqual(
+                System.Reflection.MethodInfo.GetCurrentMethod().Name,
+                categoryTraceListener.Category);
+
+            Debug.Listeners.Remove(categoryTraceListener);
+        }
+#endif
+
+        private class TestErrorHandler : IErrorHandler
+        {
+            private bool m_errorOccured = false;
+
+            public bool ErrorOccured
+            { 
+                get { return m_errorOccured; }
+            }
+            #region IErrorHandler Members
+
+            public void Error(string message, Exception e, ErrorCode errorCode)
+            {
+                m_errorOccured = true;
+            }
+
+            public void Error(string message, Exception e)
+            {
+                Error(message, e, ErrorCode.GenericFailure);
+            }
+
+            public void Error(string message)
+            {
+                Error(message, null, ErrorCode.GenericFailure);
+            }
+
+            #endregion
+        }
+    }
+}
diff --git a/tests/src/log4net.Tests.vs2008.csproj b/tests/src/log4net.Tests.vs2008.csproj
index aa8f63b..5bbb7c9 100644
--- a/tests/src/log4net.Tests.vs2008.csproj
+++ b/tests/src/log4net.Tests.vs2008.csproj
@@ -130,6 +130,9 @@
     <Compile Include="Appender\CountingAppender.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Appender\DebugAppenderTest.cs">
+    	<SubType>Code</SubType>
+    </Compile>
     <Compile Include="Appender\EventLogAppenderTest.cs">
       <SubType>Code</SubType>
     </Compile>
diff --git a/tests/src/log4net.Tests.vs2010.csproj b/tests/src/log4net.Tests.vs2010.csproj
index d2e5fcc..407fc68 100644
--- a/tests/src/log4net.Tests.vs2010.csproj
+++ b/tests/src/log4net.Tests.vs2010.csproj
@@ -147,6 +147,9 @@
     <Compile Include="Appender\CountingAppender.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Appender\DebugAppenderTest.cs">
+    	<SubType>Code</SubType>
+    </Compile>
     <Compile Include="Appender\EventLogAppenderTest.cs">
       <SubType>Code</SubType>
     </Compile>
diff --git a/tests/src/log4net.Tests.vs2012.csproj b/tests/src/log4net.Tests.vs2012.csproj
index 81bbb16..7629c5a 100644
--- a/tests/src/log4net.Tests.vs2012.csproj
+++ b/tests/src/log4net.Tests.vs2012.csproj
@@ -147,6 +147,7 @@
     <Compile Include="Appender\CountingAppender.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Appender\DebugAppenderTest.cs" />
     <Compile Include="Appender\EventLogAppenderTest.cs">
       <SubType>Code</SubType>
     </Compile>