#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 // Compatibility: // http://msdn.microsoft.com/en-us/library/system.console.foregroundcolor.aspx // Disable for unsupported targets #if !NETCF #if !SSCLI #if !CLI_1_0 #if !MONO_1_0 #if !NET_1_0 #if !NET_1_1 // The original ColoredConsoleAppender was written before the .NET framework // (and Mono) had built-in support for console colors so it was written using // Win32 API calls. The AnsiColorTerminalAppender, while it works, isn't // understood by the Windows command prompt. // This is a replacement for both that uses the new (.NET 2) Console colors // and works on both platforms. // On Mono/Linux (at least), setting the background color to 'Black' is // not the same as the default background color, as it is after // Console.Reset(). The difference becomes apparent while running in a // terminal application that supports background transparency; the // default color is treated as transparent while 'Black' isn't. // For this reason, we always reset the colors and only set those // explicitly specified in the configuration (Console.BackgroundColor // isn't set if ommited). using System; using log4net.Layout; using log4net.Util; using System.Globalization; namespace log4net.Appender { /// /// Appends colorful logging events to the console, using the .NET 2 /// built-in capabilities. /// /// /// /// ManagedColoredConsoleAppender appends log events to the standard output stream /// or the error output stream using a layout specified by the /// user. It also allows the color of a specific type of message to be set. /// /// /// By default, all output is written to the console's standard output stream. /// The property can be set to direct the output to the /// error stream. /// /// /// When configuring the colored console appender, mappings should be /// specified to map logging levels to colors. For example: /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// The Level is the standard log4net logging level while /// ForeColor and BackColor are the values of /// enumeration. /// /// /// Based on the ColoredConsoleAppender /// /// /// Rick Hobbs /// Nicko Cadell /// Pavlos Touboulidis public class ManagedColoredConsoleAppender: AppenderSkeleton { /// /// Initializes a new instance of the class. /// /// /// The instance of the class is set up to write /// to the standard output stream. /// public ManagedColoredConsoleAppender() { } #region Public Instance Properties /// /// Target is the value of the console output stream. /// This is either "Console.Out" or "Console.Error". /// /// /// Target is the value of the console output stream. /// This is either "Console.Out" or "Console.Error". /// /// /// /// Target is the value of the console output stream. /// This is either "Console.Out" or "Console.Error". /// /// virtual public string Target { get { return m_writeToErrorStream ? ConsoleError : ConsoleOut; } set { string v = value.Trim(); if (string.Compare(ConsoleError, v, true, CultureInfo.InvariantCulture) == 0) { m_writeToErrorStream = true; } else { m_writeToErrorStream = false; } } } /// /// Add a mapping of level to color - done by the config file /// /// The mapping to add /// /// /// Add a mapping to this appender. /// Each mapping defines the foreground and background colors /// for a level. /// /// public void AddMapping(LevelColors mapping) { m_levelMapping.Add(mapping); } #endregion // Public Instance Properties #region Override implementation of AppenderSkeleton /// /// This method is called by the method. /// /// The event to log. /// /// /// Writes the event to the console. /// /// /// The format of the output will depend on the appender's layout. /// /// override protected void Append(log4net.Core.LoggingEvent loggingEvent) { System.IO.TextWriter writer; if (m_writeToErrorStream) writer = Console.Error; else writer = Console.Out; // Reset color Console.ResetColor(); // see if there is a specified lookup LevelColors levelColors = m_levelMapping.Lookup(loggingEvent.Level) as LevelColors; if (levelColors != null) { // if the backColor has been explicitly set if (levelColors.HasBackColor) Console.BackgroundColor = levelColors.BackColor; // if the foreColor has been explicitly set if (levelColors.HasForeColor) Console.ForegroundColor = levelColors.ForeColor; } // Render the event to a string string strLoggingMessage = RenderLoggingEvent(loggingEvent); // and write it writer.Write(strLoggingMessage); // Reset color again Console.ResetColor(); } /// /// This appender requires a to be set. /// /// true /// /// /// This appender requires a to be set. /// /// override protected bool RequiresLayout { get { return true; } } /// /// Initialize the options for this appender /// /// /// /// Initialize the level to color mappings set on this appender. /// /// public override void ActivateOptions() { base.ActivateOptions(); m_levelMapping.ActivateOptions(); } #endregion // Override implementation of AppenderSkeleton #region Public Static Fields /// /// The to use when writing to the Console /// standard output stream. /// /// /// /// The to use when writing to the Console /// standard output stream. /// /// public const string ConsoleOut = "Console.Out"; /// /// The to use when writing to the Console /// standard error output stream. /// /// /// /// The to use when writing to the Console /// standard error output stream. /// /// public const string ConsoleError = "Console.Error"; #endregion // Public Static Fields #region Private Instances Fields /// /// Flag to write output to the error stream rather than the standard output stream /// private bool m_writeToErrorStream = false; /// /// Mapping from level object to color value /// private LevelMapping m_levelMapping = new LevelMapping(); #endregion // Private Instances Fields #region LevelColors LevelMapping Entry /// /// A class to act as a mapping between the level that a logging call is made at and /// the color it should be displayed as. /// /// /// /// Defines the mapping between a level and the color it should be displayed in. /// /// public class LevelColors : LevelMappingEntry { /// /// The mapped foreground color for the specified level /// /// /// /// Required property. /// The mapped foreground color for the specified level. /// /// public ConsoleColor 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 ConsoleColor foreColor; private bool hasForeColor; internal bool HasForeColor { get { return hasForeColor; } } /// /// The mapped background color for the specified level /// /// /// /// Required property. /// The mapped background color for the specified level. /// /// public ConsoleColor 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 ConsoleColor backColor; private bool hasBackColor; internal bool HasBackColor { get { return hasBackColor; } } } #endregion // LevelColors LevelMapping Entry } } #endif #endif #endif // !MONO_1_0 #endif // !CLI_1_0 #endif // !SSCLI #endif // !NETCF