You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by dp...@apache.org on 2017/05/25 21:27:59 UTC
[1/4] logging-log4net git commit: First version of ProcMonAppender
Repository: logging-log4net
Updated Branches:
refs/heads/develop [created] f5fdf89fd
refs/heads/pr/old/10 [created] b4bc43eed
refs/heads/pr/old/22 [created] 675e7cba2
refs/heads/pr/old/7 [created] 3c930d8d9
refs/heads/pr/old/9 [created] f33118151
Updated Tags: refs/tags/1.2.13RC1 [created] 6dc3da926
First version of ProcMonAppender
Project: http://git-wip-us.apache.org/repos/asf/logging-log4net/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4net/commit/f3311815
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4net/tree/f3311815
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4net/diff/f3311815
Branch: refs/heads/pr/old/9
Commit: f331181519b36aebf9203bead1cce6e57c58b373
Parents: 610157a
Author: Justin Dearing <zi...@gmail.com>
Authored: Thu Mar 20 19:12:19 2014 -0400
Committer: Dominik Psenner <dp...@apache.org>
Committed: Wed May 24 23:25:47 2017 +0200
----------------------------------------------------------------------
src/log4net/Appender/ProcMonAppender.cs | 170 +++++++++++++++++++++++++++
src/log4net/log4net.vs2010.csproj | 5 +-
2 files changed, 173 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/f3311815/src/log4net/Appender/ProcMonAppender.cs
----------------------------------------------------------------------
diff --git a/src/log4net/Appender/ProcMonAppender.cs b/src/log4net/Appender/ProcMonAppender.cs
new file mode 100644
index 0000000..cfd8af6
--- /dev/null
+++ b/src/log4net/Appender/ProcMonAppender.cs
@@ -0,0 +1,170 @@
+#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.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+using log4net.Core;
+using Microsoft.Win32.SafeHandles;
+
+namespace log4net.Appender
+{
+ /// <summary>
+ /// Appends log events to Sysinternals Process Monitor.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The application configuration file can be used to control what listeners
+ /// are actually used.
+ /// </para>
+ /// <para>
+ /// Events are written using a write only file handle that procmon listens for. Process Monitor will then display these messages amongst the IO data.
+ /// </para>
+ /// </remarks>
+ /// <author>Justin Dearing</author>
+ /// <seealso cref="http://www.wintellect.com/blogs/jrobbins/see-the-i-o-you-caused-by-getting-your-diagnostic-tracing-into-process-monitor"/>
+ /// <seealso cref="http://www.wintellect.com/blogs/jrobbins/procmondebugoutput-now-on-github"/>
+ /// <seealso cref="https://github.com/Wintellect/ProcMonDebugOutput"/>
+ public class ProcMonAppender : AppenderSkeleton
+ {
+ // Constants to represent C preprocessor macros for PInvokes
+ const uint GENERIC_WRITE = 0x40000000;
+ const uint OPEN_EXISTING = 3;
+ const uint FILE_WRITE_ACCESS = 0x0002;
+ const uint FILE_SHARE_WRITE = 0x00000002;
+ const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
+ const uint METHOD_BUFFERED = 0;
+
+ // Procmon Constants
+ const uint FILE_DEVICE_PROCMON_LOG = 0x00009535;
+ const string PROCMON_DEBUGGER_HANDLER = "\\\\.\\Global\\ProcmonDebugLogger";
+
+ /// <summary>
+ /// The handle to the procmon log device.
+ /// </summary>
+ private static SafeFileHandle hProcMon;
+
+ /// <summary>
+ /// Get the IO Control code for the ProcMon log.
+ /// </summary>
+ private static uint IOCTL_EXTERNAL_LOG_DEBUGOUT { get { return CTL_CODE(); } }
+
+ /// <seealso href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff543023(v=vs.85).aspx"/>
+ private static uint CTL_CODE(
+ uint DeviceType = FILE_DEVICE_PROCMON_LOG,
+ uint Function = 0x81,
+ uint Method = METHOD_BUFFERED,
+ uint Access = FILE_WRITE_ACCESS)
+ {
+ return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
+ }
+
+ /// <remarks>This is only used for opening the procmon log handle, hence the default parameters.</remarks>
+ /// <seealso href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx"/>
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern SafeFileHandle CreateFile(
+ string lpFileName = PROCMON_DEBUGGER_HANDLER,
+ uint dwDesiredAccess = GENERIC_WRITE,
+ uint dwShareMode = FILE_SHARE_WRITE,
+ IntPtr lpSecurityAttributes = default(IntPtr),
+ uint dwCreationDisposition = OPEN_EXISTING,
+ uint dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
+ IntPtr hTemplateFile = default(IntPtr));
+
+ [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern bool DeviceIoControl(
+ SafeFileHandle hDevice, uint dwIoControlCode,
+ StringBuilder lpInBuffer, uint nInBufferSize,
+ IntPtr lpOutBuffer, uint nOutBufferSize,
+ out uint lpBytesReturned, IntPtr lpOverlapped);
+
+
+ static ProcMonAppender()
+ {
+ AppDomain.CurrentDomain.ProcessExit += (sender, args) =>
+ {
+ if (!hProcMon.IsInvalid) hProcMon.Close();
+ };
+ }
+
+ /// <summary>
+ /// Does the actual tracing to Process Monitor.
+ /// </summary>
+ /// <param name="message">
+ /// The message to display.
+ /// </param>
+ /// <param name="args">
+ /// The formatting arguments for the message
+ /// </param>
+ /// <returns>
+ /// True if the trace succeeded, false otherwise.
+ /// </returns>
+ private static bool ProcMonDebugOutput(string message, params object[] args)
+ {
+ bool returnValue = false;
+ try
+ {
+ StringBuilder renderedMessage = new StringBuilder();
+ renderedMessage.AppendFormat(message, args);
+ uint outLen;
+ if (hProcMon == null || hProcMon.IsInvalid)
+ {
+ hProcMon = CreateFile();
+ }
+ DeviceIoControl(
+ hProcMon, IOCTL_EXTERNAL_LOG_DEBUGOUT,
+ renderedMessage, (uint)(message.Length * Marshal.SizeOf(typeof(char))),
+ IntPtr.Zero, 0, out outLen, IntPtr.Zero);
+ }
+ catch (EntryPointNotFoundException notFoundException)
+ {
+ // This means the appropriate ProcMonDebugOutput[Win32|x64].DLL
+ // file could not be found. I'll eat this exception so it does
+ // not take down the application.
+ Debug.WriteLine(notFoundException.Message);
+ }
+
+ return returnValue;
+ }
+
+ /// <summary>
+ /// This appender requires a <see cref="AppenderSkeleton.Layout"/> to be set.
+ /// </summary>
+ /// <value><c>true</c></value>
+ override protected bool RequiresLayout
+ {
+ get { return true; }
+ }
+
+ /// <summary>
+ /// Writes the logging event to Sysinternals Process Monitor.
+ /// </summary>
+ /// <param name="loggingEvent">The event to log.</param>
+ /// <remarks>
+ /// <para>
+ /// Writes the logging event to Sysinternals Process Monitor.
+ /// </para>
+ /// </remarks>
+ protected override void Append(LoggingEvent loggingEvent)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/f3311815/src/log4net/log4net.vs2010.csproj
----------------------------------------------------------------------
diff --git a/src/log4net/log4net.vs2010.csproj b/src/log4net/log4net.vs2010.csproj
index 45e2c58..8c6a7a5 100644
--- a/src/log4net/log4net.vs2010.csproj
+++ b/src/log4net/log4net.vs2010.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
@@ -179,6 +179,7 @@
<Compile Include="Appender\OutputDebugStringAppender.cs">
<SubType>Code</SubType>
</Compile>
+ <Compile Include="Appender\ProcMonAppender.cs" />
<Compile Include="Appender\RemoteSyslogAppender.cs">
<SubType>Code</SubType>
</Compile>
@@ -793,4 +794,4 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
-</Project>
+</Project>
\ No newline at end of file
[4/4] logging-log4net git commit: Only look at relevant log files for
backup size at initialization time.
Posted by dp...@apache.org.
Only look at relevant log files for backup size at initialization time.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4net/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4net/commit/675e7cba
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4net/tree/675e7cba
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4net/diff/675e7cba
Branch: refs/heads/pr/old/22
Commit: 675e7cba232433f99e3ab0800e59c6740d6ecb37
Parents: 655233d
Author: Sotirios Delimanolis <se...@yahoo-inc.com>
Authored: Fri Jan 29 10:06:25 2016 -0800
Committer: Dominik Psenner <dp...@apache.org>
Committed: Thu May 25 23:16:48 2017 +0200
----------------------------------------------------------------------
src/Appender/RollingFileAppender.cs | 149 +++++++++++++------------------
1 file changed, 62 insertions(+), 87 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/675e7cba/src/Appender/RollingFileAppender.cs
----------------------------------------------------------------------
diff --git a/src/Appender/RollingFileAppender.cs b/src/Appender/RollingFileAppender.cs
index c1b7705..3068ce7 100644
--- a/src/Appender/RollingFileAppender.cs
+++ b/src/Appender/RollingFileAppender.cs
@@ -867,100 +867,75 @@ namespace log4net.Appender
}
}
- /// <summary>
- /// Does the work of bumping the 'current' file counter higher
- /// to the highest count when an incremental file name is seen.
- /// The highest count is either the first file (when count direction
- /// is greater than 0) or the last file (when count direction less than 0).
- /// In either case, we want to know the highest count that is present.
- /// </summary>
- /// <param name="baseFile"></param>
- /// <param name="curFileName"></param>
- private void InitializeFromOneFile(string baseFile, string curFileName)
- {
- if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFile)) == false)
- {
- // This is not a log file, so ignore
- return;
- }
- if (curFileName.Equals(baseFile))
- {
- // Base log file is not an incremented logfile (.1 or .2, etc)
- return;
- }
-
- /*
- if (m_staticLogFileName)
- {
- int endLength = curFileName.Length - index;
- if (baseFile.Length + endLength != curFileName.Length)
- {
- // file is probably scheduledFilename + .x so I don't care
- return;
- }
- }
- */
-
- // Only look for files in the current roll point
- if (m_rollDate && !m_staticLogFileName)
- {
- string date = m_dateTime.Now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
- string prefix = m_preserveLogFileNameExtension ? Path.GetFileNameWithoutExtension(baseFile) + date : baseFile + date;
- string suffix = m_preserveLogFileNameExtension ? Path.GetExtension(baseFile) : "";
- if (!curFileName.StartsWith(prefix) || !curFileName.EndsWith(suffix))
- {
- LogLog.Debug(declaringType, "Ignoring file ["+curFileName+"] because it is from a different date period");
- return;
- }
- }
-
- try
- {
- // Bump the counter up to the highest count seen so far
- int backup = GetBackUpIndex(curFileName);
-
- // caution: we might get a false positive when certain
- // date patterns such as yyyyMMdd are used...those are
- // valid number but aren't the kind of back up index
- // we're looking for
- if (backup > m_curSizeRollBackups)
- {
- if (0 == m_maxSizeRollBackups)
- {
- // Stay at zero when zero backups are desired
- }
- else if (-1 == m_maxSizeRollBackups)
- {
- // Infinite backups, so go as high as the highest value
- m_curSizeRollBackups = backup;
+ /// <summary>
+ /// Does the work of bumping the 'current' file counter higher
+ /// to the highest count when an incremental file name is seen.
+ /// The highest count is either the first file (when count direction
+ /// is greater than 0) or the last file (when count direction less than 0).
+ /// In either case, we want to know the highest count that is present.
+ /// </summary>
+ /// <param name="origBaseFile"></param>
+ /// <param name="origCurFileName"></param>
+ private void InitializeFromOneFile(string origBaseFile, string origCurFileName)
+ {
+ // keep originals for logging
+ string baseFile = origBaseFile;
+ string curFileName = origCurFileName;
+
+ if (m_preserveLogFileNameExtension) {
+ curFileName = Path.GetFileNameWithoutExtension (curFileName);
+ baseFile = Path.GetFileNameWithoutExtension (baseFile);
+ }
+
+ if (!m_staticLogFileName) {
+ // Generate expected target file name
+ string date = m_dateTime.Now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+ baseFile = baseFile + date;
+
+ // Only look for files in the current roll point
+ if (m_rollDate) {
+ if (!origCurFileName.StartsWith (baseFile) || (m_preserveLogFileNameExtension && !origCurFileName.EndsWith (Path.GetExtension (origBaseFile)))) {
+ LogLog.Debug (declaringType, "Ignoring file [" + origCurFileName + "] because it is from a different date period");
+ return;
}
- else
- {
- // Backups limited to a finite number
- if (m_countDirection >= 0)
- {
- // Go with the highest file when counting up
+ }
+ }
+
+ // remove baseFile prefix
+ string datePatternOrBackup = curFileName.Substring (baseFile.Length);
+
+ if (datePatternOrBackup.Length == 0) {
+ LogLog.Debug (declaringType, "Encountered the base file [" + origCurFileName + "]");
+ } else if (datePatternOrBackup [0] != '.') {
+ LogLog.Debug (declaringType, "Encountered a file that definitely isn't a size backup for the current log file [" + origCurFileName + "]");
+ } else {
+ int backup;
+ if (!int.TryParse (datePatternOrBackup.Substring (1), out backup)) {
+ LogLog.Debug (declaringType, "Encountered a backup file not ending in .N [" + origCurFileName + "]");
+ } else {
+ if (backup > m_curSizeRollBackups) {
+ if (0 == m_maxSizeRollBackups) {
+ // Stay at zero when zero backups are desired
+ } else if (-1 == m_maxSizeRollBackups) {
+ // Infinite backups, so go as high as the highest value
m_curSizeRollBackups = backup;
- }
- else
- {
- // Clip to the limit when counting down
- if (backup <= m_maxSizeRollBackups)
- {
+ } else {
+ // Backups limited to a finite number
+ if (m_countDirection >= 0) {
+ // Go with the highest file when counting up
m_curSizeRollBackups = backup;
+ } else {
+ // Clip to the limit when counting down
+ if (backup <= m_maxSizeRollBackups) {
+ m_curSizeRollBackups = backup;
+ }
}
}
+ LogLog.Debug (declaringType, "File name [" + origCurFileName + "] moves current count to [" + m_curSizeRollBackups + "]");
}
- LogLog.Debug(declaringType, "File name [" + curFileName + "] moves current count to [" + m_curSizeRollBackups + "]");
}
- }
- catch(FormatException)
- {
- //this happens when file.log -> file.log.yyyy-MM-dd which is normal
- //when staticLogFileName == false
- LogLog.Debug(declaringType, "Encountered a backup file not ending in .x ["+curFileName+"]");
- }
- }
+ }
+ }
/// <summary>
/// Attempts to extract a number from the end of the file name that indicates
[2/4] logging-log4net git commit: add ColoredSmtpAppender. allow user
send colorful log email.
Posted by dp...@apache.org.
add ColoredSmtpAppender. allow user send colorful log email.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4net/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4net/commit/3c930d8d
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4net/tree/3c930d8d
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4net/diff/3c930d8d
Branch: refs/heads/pr/old/7
Commit: 3c930d8d9b35cbfe1ba3e7ad93ff888d71f94f01
Parents: b584368
Author: Devin <st...@gmail.com>
Authored: Fri Dec 13 09:35:41 2013 -0800
Committer: Dominik Psenner <dp...@apache.org>
Committed: Wed May 24 23:26:39 2017 +0200
----------------------------------------------------------------------
src/log4net/Appender/ColoredSmtpAppender.cs | 315 +++++++++++++++++++++++
src/log4net/log4net.vs2010.csproj | 7 +-
2 files changed, 320 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/3c930d8d/src/log4net/Appender/ColoredSmtpAppender.cs
----------------------------------------------------------------------
diff --git a/src/log4net/Appender/ColoredSmtpAppender.cs b/src/log4net/Appender/ColoredSmtpAppender.cs
new file mode 100644
index 0000000..d9a8573
--- /dev/null
+++ b/src/log4net/Appender/ColoredSmtpAppender.cs
@@ -0,0 +1,315 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Mail;
+using System.Text;
+using System.Web;
+using log4net.Appender;
+using log4net.Core;
+using log4net.Util;
+
+namespace log4net.Appender
+{
+ /// <summary>
+ /// Appends colorful logging events to the email html content
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// When configuring the colored console appender, mappings should be
+ /// specified to map logging levels to colors and css styles. For example:
+ /// </para>
+ /// <code lang="XML" escaped="true">
+ /// <mapping>
+ /// <level value="ERROR" />
+ /// <foreColor value="Red" />
+ /// <backColor value="White" />
+ /// <style value="font-size: larger;font-weight: bold" />
+ /// </mapping>
+ /// <mapping>
+ /// <level value="WARN" />
+ /// <foreColor value="#FFFF00" />
+ /// </mapping>
+ /// <mapping>
+ /// <level value="INFO" />
+ /// <foreColor value="#000" />
+ /// </mapping>
+ /// <mapping>
+ /// <level value="DEBUG" />
+ /// <foreColor value="#eee" />
+ /// </mapping>
+ /// </code>
+ /// <para>
+ /// The Level is the standard log4net logging level while
+ /// ForeColor and BackColor are the values of CSS color value
+ /// Style is the CSS style.
+ /// </para>
+ /// </remarks>
+ /// <author>Devin Zeng</author>
+ public class ColoredSmtpAppender : SmtpAppender
+ {
+ private LevelMapping m_levelMapping = new LevelMapping();
+
+ protected override void SendBuffer(LoggingEvent[] events)
+ {
+ // Note: this code already owns the monitor for this
+ // appender. This frees us from needing to synchronize again.
+ try
+ {
+ StringWriter writer = new StringWriter(System.Globalization.CultureInfo.InvariantCulture);
+
+ string t = Layout.Header;
+ if (t != null)
+ {
+ writer.Write(t);
+ }
+
+ for (int i = 0; i < events.Length; i++)
+ {
+ // Render the event and append the text to the buffer
+ RenderColoredLoggingEvent(writer, events[i]);
+ }
+
+ t = Layout.Footer;
+ if (t != null)
+ {
+ writer.Write(t);
+ }
+
+ SendEmail(writer.ToString());
+ }
+ catch (Exception e)
+ {
+ ErrorHandler.Error("Error occurred while sending e-mail notification.", e);
+ }
+ }
+ /// <summary>
+ /// Based on loggingEvent configration, render the html formatted log content.
+ /// </summary>
+ /// <param name="writer"></param>
+ /// <param name="loggingEvent"></param>
+ protected void RenderColoredLoggingEvent(TextWriter writer, LoggingEvent loggingEvent)
+ {
+ if (Layout == null)
+ {
+ throw new InvalidOperationException("A layout must be set");
+ }
+ if (Layout.IgnoresException)
+ {
+ string exceptionStr = loggingEvent.GetExceptionString();
+ if (exceptionStr != null && exceptionStr.Length > 0)
+ {
+ writer.WriteLine(HtmlMessage(exceptionStr));
+ }
+ }
+ writer.WriteLine(BuildHtmlLoggingMessage(loggingEvent));
+
+ }
+ /// <summary>
+ /// Build loggingEvent html format message
+ /// </summary>
+ /// <param name="loggingEvent"></param>
+ /// <returns>Log content</returns>
+ private string BuildHtmlLoggingMessage(LoggingEvent loggingEvent)
+ {
+ StringBuilder style = new StringBuilder();
+ LevelColors levelColors = m_levelMapping.Lookup(loggingEvent.Level) as LevelColors;
+ if (levelColors != null)
+ {
+ // if the backColor has been explicitly set
+ if (levelColors.HasBackColor)
+ {
+ style.Append("background-color:" + levelColors.BackColor + ";");
+ }
+ // if the foreColor has been explicitly set
+ if (levelColors.HasForeColor)
+ {
+ style.Append("color:" + levelColors.ForeColor + ";");
+ }
+ if (!String.IsNullOrEmpty(levelColors.Style))
+ {
+ style.Append(levelColors.Style);
+ }
+ }
+ var css = style.ToString();
+ string strLoggingMessage = RenderLoggingEvent(loggingEvent);
+ return HtmlMessage(strLoggingMessage, css);
+ }
+
+ private string HtmlMessage(string strLoggingMessage, string css = "")
+ {
+ return "<span style='white-space:pre;" + css + "'>" + HttpUtility.HtmlEncode(strLoggingMessage) + "</span>";
+ }
+
+ /// <summary>
+ /// Allow HTML content
+ /// </summary>
+ /// <param name="messageBody"></param>
+ protected override void SendEmail(string messageBody)
+ {
+ // .NET 2.0 has a new API for SMTP email System.Net.Mail
+ // This API supports credentials and multiple hosts correctly.
+ // The old API is deprecated.
+
+ // Create and configure the smtp client
+ SmtpClient smtpClient = new SmtpClient();
+ if (!String.IsNullOrEmpty(SmtpHost))
+ {
+ smtpClient.Host = SmtpHost;
+ }
+ smtpClient.Port = Port;
+ smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
+ smtpClient.EnableSsl = EnableSsl;
+
+ if (Authentication == SmtpAuthentication.Basic)
+ {
+ // Perform basic authentication
+ smtpClient.Credentials = new System.Net.NetworkCredential(Username, Password);
+ }
+ else if (Authentication == SmtpAuthentication.Ntlm)
+ {
+ // Perform integrated authentication (NTLM)
+ smtpClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
+ }
+
+ using (MailMessage mailMessage = new MailMessage())
+ {
+ mailMessage.Body = messageBody;
+ mailMessage.IsBodyHtml = true;
+ mailMessage.BodyEncoding = BodyEncoding;
+ mailMessage.From = new MailAddress(From);
+ mailMessage.To.Add(To);
+ if (!String.IsNullOrEmpty(Cc))
+ {
+ mailMessage.CC.Add(Cc);
+ }
+ if (!String.IsNullOrEmpty(Bcc))
+ {
+ mailMessage.Bcc.Add(Bcc);
+ }
+ if (!String.IsNullOrEmpty(ReplyTo))
+ {
+ // .NET 4.0 warning CS0618: 'System.Net.Mail.MailMessage.ReplyTo' is obsolete:
+ // 'ReplyTo is obsoleted for this type. Please use ReplyToList instead which can accept multiple addresses. http://go.microsoft.com/fwlink/?linkid=14202'
+#if !FRAMEWORK_4_0_OR_ABOVE
+ mailMessage.ReplyTo = new MailAddress(ReplyTo);
+#else
+ mailMessage.ReplyToList.Add(new MailAddress(ReplyTo));
+#endif
+ }
+ mailMessage.Subject = Subject;
+ mailMessage.SubjectEncoding = SubjectEncoding;
+ mailMessage.Priority = Priority;
+
+ // TODO: Consider using SendAsync to send the message without blocking. This would be a change in
+ // behaviour compared to .NET 1.x. We would need a SendCompletedCallback to log errors.
+ smtpClient.Send(mailMessage);
+ }
+ }
+
+ /// <summary>
+ /// Add a mapping of level to color - done by the config file
+ /// </summary>
+ /// <param name="mapping">The mapping to add</param>
+ /// <remarks>
+ /// <para>
+ /// Add a <see cref="LevelColors"/> mapping to this appender.
+ /// Each mapping defines the foreground and background colors
+ /// for a level.
+ /// </para>
+ /// </remarks>
+ public void AddMapping(LevelColors mapping)
+ {
+ m_levelMapping.Add(mapping);
+ }
+
+ /// <summary>
+ /// Initialize the options for this appender
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Initialize the level to color mappings set on this appender.
+ /// </para>
+ /// </remarks>
+ public override void ActivateOptions()
+ {
+ base.ActivateOptions();
+ m_levelMapping.ActivateOptions();
+ }
+
+ /// <summary>
+ /// Copy from ManagedColoredConsoleAppender, add Style propertity
+ /// </summary>
+ public class LevelColors : LevelMappingEntry
+ {
+ /// <summary>
+ /// The mapped foreground color for the specified level
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Required property.
+ /// The mapped foreground color for the specified level.
+ /// </para>
+ /// </remarks>
+ public string ForeColor
+ {
+ get { return (this.foreColor); }
+ // Keep a flag that the color has been set
+ // and is no longer the default.
+ set
+ {
+ this.foreColor = value;
+ this.hasForeColor = true;
+ }
+ }
+
+ private string foreColor;
+ private bool hasForeColor;
+
+ internal bool HasForeColor
+ {
+ get
+ {
+ return hasForeColor;
+ }
+ }
+ /// <summary>
+ /// CSS style
+ /// </summary>
+ public string Style
+ { get; set; }
+
+ /// <summary>
+ /// The mapped background color for the specified level
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Required property.
+ /// The mapped background color for the specified level.
+ /// </para>
+ /// </remarks>
+ public string BackColor
+ {
+ get { return (this.backColor); }
+ // Keep a flag that the color has been set
+ // and is no longer the default.
+ set
+ {
+ this.backColor = value;
+ this.hasBackColor = true;
+ }
+ }
+
+ private string backColor;
+ private bool hasBackColor;
+
+ internal bool HasBackColor
+ {
+ get
+ {
+ return hasBackColor;
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/3c930d8d/src/log4net/log4net.vs2010.csproj
----------------------------------------------------------------------
diff --git a/src/log4net/log4net.vs2010.csproj b/src/log4net/log4net.vs2010.csproj
index 45e2c58..569ec4c 100644
--- a/src/log4net/log4net.vs2010.csproj
+++ b/src/log4net/log4net.vs2010.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
@@ -145,6 +145,9 @@
<Compile Include="Appender\ColoredConsoleAppender.cs">
<SubType>Code</SubType>
</Compile>
+ <Compile Include="Appender\ColoredSmtpAppender.cs">
+ <SubType>Code</SubType>
+ </Compile>
<Compile Include="Appender\ConsoleAppender.cs">
<SubType>Code</SubType>
</Compile>
@@ -793,4 +796,4 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
-</Project>
+</Project>
\ No newline at end of file
[3/4] logging-log4net git commit: Support for types of
non-parameterless constructors in XmlConfigurator.
Posted by dp...@apache.org.
Support for types of non-parameterless constructors in XmlConfigurator.
The constructor parameters are taken from the corresponding values of
the child nodes.
You can add for instance
<standardunit type="Amazon.CloudWatch.StandardUnit">
<value value="Kilobytes"/>
</standardunit>
where StandardUnit has only one constructor that has a string parameter
named "value".
Project: http://git-wip-us.apache.org/repos/asf/logging-log4net/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4net/commit/b4bc43ee
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4net/tree/b4bc43ee
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4net/diff/b4bc43ee
Branch: refs/heads/pr/old/10
Commit: b4bc43eed24d1152772141652d68002f396c615d
Parents: 610157a
Author: Martin Camitz <ma...@gmail.com>
Authored: Tue Apr 22 15:36:29 2014 +0200
Committer: Dominik Psenner <dp...@apache.org>
Committed: Thu May 25 00:06:48 2017 +0200
----------------------------------------------------------------------
.../Hierarchy/XmlHierarchyConfigurator.cs | 54 ++++++++++++++++++--
1 file changed, 50 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/b4bc43ee/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs
----------------------------------------------------------------------
diff --git a/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs b/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs
index ae415d7..a251b47 100644
--- a/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs
+++ b/src/log4net/Repository/Hierarchy/XmlHierarchyConfigurator.cs
@@ -19,7 +19,9 @@
using System;
using System.Collections;
+using System.Collections.Generic;
using System.Globalization;
+using System.Linq;
using System.Reflection;
using System.Xml;
@@ -986,13 +988,57 @@ namespace log4net.Repository.Hierarchy
// Create using the default constructor
object createdObject = null;
- try
+
+ //Try parameterless constructor
+ if (objectType.GetConstructor(Type.EmptyTypes) != null)
{
- createdObject = Activator.CreateInstance(objectType);
+ try
+ {
+ createdObject = Activator.CreateInstance(objectType);
+ }
+ catch (Exception createInstanceEx)
+ {
+ LogLog.Error(declaringType,
+ "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName +
+ "] Exception: " + createInstanceEx.ToString());
+ }
+
}
- catch(Exception createInstanceEx)
+ else
{
- LogLog.Error(declaringType, "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName + "] Exception: "+createInstanceEx.ToString());
+ //See if there is a constructor matching supplied values, most specific first.
+ Exception lastException = null;
+ foreach (var constructorInfo in objectType.GetConstructors().OrderByDescending(x => x.GetParameters().Count()))
+ {
+
+ try
+ {
+ var nodes = new List<XmlNode>(element.ChildNodes.Cast<XmlNode>());
+ var parameterInfos = constructorInfo.GetParameters();
+ LogLog.Debug(declaringType, "Trying constructor with parameters: " + string.Join(",", parameterInfos.Select(p => p.Name)));
+
+ var args = parameterInfos.Select(p => nodes.SingleOrDefault(n => n.Name == p.Name));
+ LogLog.Debug(declaringType, "Matching args from config: " + string.Join(",", args.Select(n => n.Name)));
+ LogLog.Debug(declaringType, "Matching arg values from config: " + string.Join(",", args.Select(a => a.Attributes["value"].Value)));
+ if (args.All(a => a != null))
+ {
+ createdObject = constructorInfo.Invoke(args.Select(a => a.Attributes["value"].Value).ToArray());
+ break;
+ }
+ }
+ catch (Exception e)
+ {
+ lastException = e;
+ }
+ }
+
+ if (createdObject == null)
+ {
+ LogLog.Error(declaringType,
+ "XmlHierarchyConfigurator: Failed to construct object of type [" + objectType.FullName +
+ "] No matching constructor found. LastException: " +
+ (lastException != null ? lastException.ToString() : "None caught."));
+ }
}
// Set any params on object