ASP.NET MVC logs using Log4net

Keywords: ASP.NET Apache Windows Database SDK

Log4net introduction

Log4net, Apache's next open source project, is a clone of Log4j. We can control the destination of log information output. Log4net defines a variety of log information output modes. It can output logs to console, text files, windows log event viewer, including database, mail and other locations, so that we can quickly track program bug s.

Log4net provides seven log levels from high to low: OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL.

Log4net has three main members, loggers, appenders and layouts.  

  • Logger introduction
    Logger is the logger. Assuming that we need to record some normal runtime logs and error logs when an exception occurs, we can add two loggers to the configuration file. Logger is mainly used to record the classification of logs and control the level of logs. It can output log information in many formats, and it can also control the output level of the log.
    log4net uses inheritance system, that is, if there are two loggers, the names are a.b.c and a.b. So A. B is the ancestor of A. B. C. Each Logger inherits the attributes of its ancestors
  • Appender introduction
    Provides the output source of log records, we can output the log to the console, text files, windows log event viewer (view in Window s Log > application), database, mail, etc. These output sources are configured through Appender.
    It is not recommended to save the log files to the database, because it is still difficult to use sql to sort out the logs. It is better to save the log files by the log management service or Elastic search, which can provide good full-text indexing and other functions.
  • Layout introduction
    Layout is used to control the output format of Appender.
    String Conversion Interpretation of PatternLayout Agreement in Layout
        Log messages output by% m,% message
        % d,% datetime outputs the time when the current statement is running, in the format% date {yyyy-MM-d D HH: mm: ss, fff}
        Milliseconds consumed by the% r,% timestamp output program from running to executing to the current statement
        Current priority of% p,% level logs
        The name of the current log object for% c,% logger
        Line numbers for% L,% line output statements
        The filename where the% F and% file output statements are located. Warning: Only valid when debugging, calling local information can affect performance
        The name of the application domain where% a,% appdomain causes log events.
        Full names of classes that cause log requests in% C,% class,% type, warning: performance will be affected
        % exception exception exception information
        The names of the current active users of% u and% identity are empty when I test them. Warning: This can affect performance
        The namespace, class name, method, line number of log events triggered by% l and% location. Warning: It can affect performance, depending on pdb files
        Method names for log requests in% M,% method, warning: performance will be affected
        % n,% newline newline newline newline
        %x,%ndc             NDC(nested diagnostic context)
        % X,% mdc,% P,% properties and so on are between% property.
        % property output {log4net:Identity=, log4net:UserName=, log4net:HostName=} 
        Threads that cause log events in% t and% threads use thread numbers if there is no thread name.
        Windows Identity for current users of% w and% username, similar to: HostName/Username. Warning: This can affect performance
        UTC time for log events in% utcdate. For example:% utcdate{HH:mm:ss,fff}
        %% Output a percentage sign

    For more information, see http://logging.apache.org/log4net/release/sdk/html/T_log4net_Layout_PatternLayout.htm

How to use

Take ASP.NET MVC project as an example

1. Use Nuget to install log4net.

PM> Install-Package log4net

2. Create log4net.config configuration file and modify the file's attribute "Copy to Output Directory" to "Always Copy"

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net-net-2.0"/>
  </configSections>
  <log4net>
    <root>
      <level value="ALL" />
      <appender-ref ref="LogFileAppender" />
      <!--<appender-ref ref="EventLogAppender" />-->
    </root>
    <!--Define output to file-->
    <appender name ="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <!--Define file storage location-->
      <param name="File" value ="App_Data\"/>
      <param name="AppendToFile" value="true" />
      <param name="MaxSizeRollBackups" value="100" />
      <param name="MaxFileSize" value="10240" />
      <param name="StaticLogFileName" value="false" />
      <!--File name format-->
      <param name="DatePattern" value="yyyy.MM.dd'.txt'" />
      <param name="RollingStyle" value ="Date" />
      <!--Do not log exclusively,Lock only for the shortest time that each log is recorded,The log cannot be downloaded because files are occupied when deployed to the server-->
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <layout type="log4net.Layout.PatternLayout">
        <!--Define output format-->
        <!--Example 2018-08-20 12:10:49,348 -thread ID:[21] log level:[INFO ] : [log information]-->
        <param name="ConversionPattern" value="%date thread ID:[%thread] log level:[%-5level] : [%message]%newline"/>
      </layout>
      <!--Filter level FATAL > ERROR > WARN > INFO > DEBUG-->
      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="DEBUG" />
        <param name="LevelMax" value="FATAL" />
      </filter>
    </appender>
    <!--Define output to windows Incident-->
    <appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"></conversionPattern>
      </layout>
    </appender>
  </log4net>
</configuration>

3. Create LogHelper class to provide logging methods

public class LogHelper
    {
        private ILog _log4Net = null;
        private const string DEFAULT_LOGGER_NAME = "Logger";
        /// <summary>
        /// Prevents a default instance of the <see cref="LogWriter"/> class from being created.
        /// </summary>
        /// <param name="log4NetInstance">The log4net instance to be used.</param>
        private LogHelper(ILog log4NetInstance)
        {
            _log4Net = log4NetInstance;
        }

        /// <summary>
        /// Gets a logger with the specified configuration name.
        /// </summary>
        /// <param name="configName">Name of the logger in the configuration.</param>
        /// <returns>The logger obtained.</returns>
        /// <exception cref="System.Configuration.ConfigurationException">Thrown when no logger with the specified configuration name was found.</exception>
        public static LogHelper GetLogger(string configName)
        {
            var logger = LogManager.GetLogger(configName);
            if (logger == null)
            {
                throw new ArgumentException(string.Format("No logger configuration named '{0}' was found in the configuration.", configName), "configName");
            }
            return new LogHelper(logger);
        }

        /// <summary>
        /// Gets the default.
        /// </summary>
        public static LogHelper Default
        {
            get
            {
                return GetLogger(DEFAULT_LOGGER_NAME);
            }
        }

        /// <summary>
        /// Writes an information level logging message.
        /// </summary>
        /// <param name="message">The message to be written.</param>
        public void WriteInfo(object message)
        {
            _log4Net.Info(message);
        }

        /// <summary>
        /// Writes a warning level logging message.
        /// </summary>
        /// <param name="message">The message to be written.</param>
        public void WriteWarning(object message)
        {
            _log4Net.Warn(message);
        }

        /// <summary>
        /// Writes a warning level logging message.
        /// </summary>
        /// <param name="message">The message to be written.</param>
        /// <param name="exception">The exception.</param>
        public void WriteWarning(object message, System.Exception exception)
        {
            _log4Net.Warn(message, exception);
        }

        /// <summary>
        /// Writes the error.
        /// </summary>
        /// <param name="message">The message to be written.</param>
        public void WriteError(object message)
        {
            _log4Net.Error(message);
        }

        /// <summary>
        /// Writes the error level logging message..
        /// </summary>
        /// <param name="message">The message to be written.</param>
        /// <param name="exception">The exception.</param>
        public void WriteError(object message, System.Exception exception)
        {
            _log4Net.Error(message, exception);
        }

        /// <summary>
        /// Writes the fatal error level logging message..
        /// </summary>
        /// <param name="message">The message to be written.</param>
        public void WriteFatal(object message)
        {
            _log4Net.Fatal(message);
        }

        /// <summary>
        /// Writes the fatal error level logging message..
        /// </summary>
        /// <param name="message">The message to be written.</param>
        /// <param name="exception">The exception.</param>
        public void WriteFatal(object message, System.Exception exception)
        {
            _log4Net.Fatal(message, exception);
        }

        public void DeleteLog()
        {
            string logDirPath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Log");
            if (!Directory.Exists(logDirPath)) return;
            int days = 30;
            foreach (string filePath in Directory.GetFiles(logDirPath))
            {
                DateTime dt;
                DateTime.TryParse(Path.GetFileNameWithoutExtension(filePath).Replace(@"Log\", "").Replace(".", "-"), out dt);
                if (dt.AddDays(days).CompareTo(DateTime.Now) < 0)
                {
                    File.Delete(filePath);
                }
            }
        }
    }

 

4. Load your log4net.config file in the Application_Start method of the Global.asax file and call the LogHelper class to test the log.

log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/log4net.config")));
LogHelper.Default.WriteInfo(
"AppStart"); LogHelper.Default.WriteWarning("Warning"); LogHelper.Default.WriteError("Error"); LogHelper.Default.WriteFatal("Fatal"); try { int a = 3 / 4; int r = 4 / a; } catch (Exception ex) { LogHelper.Default.WriteError(ex.Message, ex); }

5. log effect map

 

Possible problems

Because log4net is an exclusive file by default, if the program is deployed in FTP space and needs to download the log file, it will find that it can not download (the process is occupied), at this time, it needs to change the locking model of Appender (output source).

For more information on Locking Model, see https://logging.apache.org/log4net/release/sdk/html/P_log4net_Appender_FileAppender_Locking Model.htm.

<! - Logs are not recorded exclusively, but are locked only for the shortest time to record each log, because files are occupied and cannot be downloaded when deployed to the server - >
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

Sample download

 

Reference resources

https://logging.apache.org/log4net/release/manual/introduction.html

https://github.com/apache/logging-log4net/

https://stackify.com/log4net-guide-dotnet-logging/?utm_referrer=https://www.google.com/

http://www.cnblogs.com/LiZhiW/p/4317198.html?utm_source=tuicool&utm_medium=referral

http://lovecjh.com/2018/06/08/log4net%E4%BD%BF%E7%94%A8/

Posted by kgahn on Tue, 11 Dec 2018 03:42:05 -0800