maxArchiveFiles: max file number for each fileName
maxArchiveFiles="50"
according by combination of fileName, such as xxx-2019-12-27-info.log
if this log size more than 20M, it will be backed and renamed with xxx-2019-12-27-infoINTEGER.log
Level:
Trace
Debug
Info
Warn
Error
Fatal
Off
Sample
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="info" internalLogFile="Log\internal-nlog.log">
<!-- log file directory -->
<variable name="logDirectory" value="Log"/>
<!-- log file name prefix -->
<variable name="serviceName" value="xxxx"/>
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets async="true">
<!-- write logs to file -->
<target xsi:type="File" name="tracefile" fileName="${logDirectory}/${serviceName}-${shortdate}-trace.log" archiveAboveSize="20000000" archiveNumbering="Rolling" maxArchiveFiles="50" concurrentWrites="false" keepFileOpen="false" encoding="utf-8" createDirs="true" layout="${longdate}|${pad:padding=-5:inner=${level:uppercase=true}}|thread-${threadid}|${logger}|${message} ${exception:format=tostring}" />
<target xsi:type="File" name="infofile" fileName="${logDirectory}/${serviceName}-${shortdate}-info.log" archiveAboveSize="20000000" archiveNumbering="Rolling" maxArchiveFiles="50" concurrentWrites="false" keepFileOpen="false" encoding="utf-8" createDirs="true" layout="${longdate}|${pad:padding=-5:inner=${level:uppercase=true}}|thread-${threadid}|${logger}|${message} ${exception:format=tostring}" />
<target xsi:type="File" name="errorfile" fileName="${logDirectory}/${serviceName}-${shortdate}-error.log" archiveAboveSize="20000000" archiveNumbering="Rolling" maxArchiveFiles="50" concurrentWrites="false" keepFileOpen="false" encoding="utf-8" createDirs="true" layout="${longdate}|${pad:padding=-5:inner=${level:uppercase=true}}|thread-${threadid}|${logger}|${message} ${exception:format=tostring}" />
<target xsi:type="File" name="accessfile" fileName="${logDirectory}/${serviceName}-${shortdate}-access.log" archiveAboveSize="20000000" archiveNumbering="Rolling" maxArchiveFiles="50" concurrentWrites="false" keepFileOpen="false" encoding="utf-8" createDirs="true" layout="${longdate}|${pad:padding=-5:inner=${level:uppercase=true}}|thread-${threadid}|${message}"/>
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="tracefile" />
<logger name="*" minlevel="Error" writeTo="errorfile" />
<logger name="Microsoft.AspNetCore.Hosting.Internal.WebHost" minlevel="Trace" writeTo="accessfile" />
<!-- this is also can be disbled in app settings by change root level of efcore class -->
<logger name="Microsoft.EntityFrameworkCore.Model.Validation" minlevel="Warn" final="true" />
<logger name="Microsoft.EntityFrameworkCore.Database.Command" minlevel="Info" final="true"/>
<logger name="*" minlevel="Info" writeTo="infofile" />
</rules>
</nlog>
log utils code, which is controlled in nlog
get log object from IOC container
logger = LogManager.GetLogger(loggerName);
custom static class sample
using System.Text;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using NLog;
using RestSharp;
using System.Text.RegularExpressions;
using System.Linq;
using Newtonsoft.Json;
namespace Augmentum.Foundation.Core.Utils
{
public class LogUtil
{
protected const string TRACE_LEVEL = "TRACE";
protected const string DEBUG_LEVEL = "DEBUG";
protected const string INFO_LEVEL = "INFO";
protected const string WARN_LEVEL = "WARN";
protected const string ERROR_LEVEL = "ERROR";
protected const string FATAL_LEVEL = "FATAL";
private static IDictionary<string, Logger> Loggers = new Dictionary<string, Logger>();
#region common log
public static void Trace<T>(T value)
{
WriteLog(value, TRACE_LEVEL);
}
public static void Debug<T>(T value)
{
WriteLog(value, DEBUG_LEVEL);
}
public static void Info<T>(T value)
{
WriteLog(value, INFO_LEVEL);
}
public static void Warn<T>(T value)
{
WriteLog(value, WARN_LEVEL);
}
public static void Error<T>(T value)
{
WriteLog(value, ERROR_LEVEL);
}
public static void Fatal<T>(T value)
{
WriteLog(value, FATAL_LEVEL);
}
#endregion
#region log rest request and response
public static void LogRestRequest(string requestUrl, IRestRequest request, object requestData)
{
// Masks the PIN.
var maskedServiceUrl = Regex.Replace(requestUrl, "(authentication/.+?/).+?$", "$1****");
var sb = new StringBuilder();
sb.AppendLine(String.Format(@"{0} {1} HTTP/1.1", request.Method, maskedServiceUrl));
foreach (var parameter in request.Parameters.Where(x => x.Type == ParameterType.HttpHeader))
{
sb.AppendFormat("{0}: {1}\r\n", parameter.Name, parameter.Value);
}
var data = JsonConvert.SerializeObject(requestData, Formatting.Indented);
sb.AppendLine(data);
Debug(sb.ToString());
}
public static void LogRestResponse(string requestUrl, IRestResponse response)
{
// Masks the PIN.
var maskedServiceUrl = Regex.Replace(requestUrl, "(authentication/.+?/).+?$", "$1****");
var sb = new StringBuilder();
sb.AppendLine(maskedServiceUrl);
sb.AppendFormat("HTTP/1.1 {0} {1}\r\n", (int)response.StatusCode, response.StatusDescription);
foreach (var parameter in response.Headers)
{
sb.AppendFormat("{0}: {1}\r\n", parameter.Name, parameter.Value);
}
sb.AppendLine(response.Content);
Debug(sb.ToString());
}
#endregion
#region private method
private static void WriteLog<T>(T value, string level)
{
Logger logger = GetLogger();
if (logger == null)
{
throw new Exception("Error occurred during initialize logger");
}
switch (level)
{
case TRACE_LEVEL:
logger.Trace(value);
break;
case DEBUG_LEVEL:
logger.Debug(value);
break;
case INFO_LEVEL:
logger.Info(value);
break;
case WARN_LEVEL:
logger.Warn(value);
break;
case ERROR_LEVEL:
logger.Error(value);
break;
case FATAL_LEVEL:
logger.Fatal(value);
break;
default:
logger.Info(value);
break;
}
}
private static string GetLoggerName()
{
StackTrace stackTrace = new StackTrace(4, true);
StackFrame stackFrame = stackTrace.GetFrame(0);
var method = stackFrame.GetMethod();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(stackFrame.GetMethod().DeclaringType.FullName)
.Append("-")
.Append(stackFrame.GetMethod().Name)
.AppendFormat("[{0}]", stackFrame.GetFileLineNumber());
return stringBuilder.ToString();
}
private static Logger GetLogger()
{
Logger logger = null;
string loggerName = GetLoggerName();
Loggers.TryGetValue(loggerName, out logger);
if (logger == null)
{
logger = LogManager.GetLogger(loggerName);
Loggers.Add(loggerName, logger);
}
return logger;
}
#endregion
}
}
use Middleware to log, and should inspect in startup as singleton
app settings config root level
nlog config
elements: use the following elements to customize the log config for scenarios.
targets
– defines log targets/outputsrules
– defines log routing rulesextensions
– loads NLog extensions from the *.dll fileinclude
– includes an external configuration filevariable
– sets the value of a configuration variableRules
name
– logger name filter - may include wildcard characters*, ?
minlevel
– minimal level to logmaxlevel
– maximum level to loglevel, levels
writeTo
– targets to write tofinal
– no rules are processed after a final rule matchesenabled
- set tofalse
to disable the rule without deleting itCustomize Rules with Wildcard
*, ?
Target
name
- name of the targetlayout
- text to be renderedencoding
archiveAboveSize
- size in bytes, and above it, log files will be automatically archived.maxArchiveFiles
- max number of archive files, and above it, log files will be automatically rolled.archiveFileName
- name of archive filearchiveNumbering
- way file archives are numbered, recommend useRolling
, which is numberingarchiveOldFileOnStartup
- auto-archive old log file on startupfileName
- named file to write tocreateDirs
concurrentWrites
- concurrent writes to same log file and defaulttrue
keepFileOpen
- keep log file open instead of opening and closing it on each logging event and default:false
enableArchiveFileCompression
- compress the archive files into the zip files, and defaultfalse
Customize Roll
daily roll:
size roll:
fileName
Level:
Sample
log utils code, which is controlled in nlog
reference