Я не знаю, как сделать это очень легко.Тем не менее, все приведенные вами примеры доступны (или довольно легко доступны с некоторым пользовательским кодом), которые можно добавить к каждому сообщению журнала.То есть каждое зарегистрированное сообщение может быть помечено именем исполняемого файла, версией файла, датой выпуска, идентификатором пользователя Windows и т. Д. С помощью Layout и LayoutRenderers.
Это, очевидно, не то же самое, что создание заголовка сверхуфайла журнала, поэтому он может быть бесполезен для вас.
С другой стороны, вы можете использовать технику, упомянутую в ответе Пата в этом посте , чтобы связать несколько средств визуализации макета ста же цель.Вы можете определить макет, который содержит поля, которые вы хотите в своем заголовке, и установить фильтр в FilteringWrapper, чтобы применять этот макет только для первого сообщения сеанса (или вы можете использовать другой метод, добавляемый в выходной файл).только один раз).
Используя его файл NLog.config, мы можем достичь желаемого.Обратите внимание, что я не пробовал это, поэтому я не знаю, является ли этот файл конфигурации действительным или, если это так, генерирует ли он требуемые результаты.
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.mono2.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Warn"
internalLogFile="nlog log.log"
>
<variable name="HeaderLayout" value="${processname} ${gdc:item=version} ${gdc:item=releasedate} ${windows-identity}" />
<variable name="NormalLayout" value="${longdate} ${logger} ${level} ${message} />
<targets async="true">
<target name="file" xsi:type="File" fileName="log.log"
layout="${NormalLayout}">
</target>
<target name="fileHeader" xsi:type="File" fileName="log.log"
layout="${HeaderLayout}">
</target>
</targets>
<rules>
<logger name="HeaderLogger" minlevel="Trace" writeTo="fileHeader" final="true" />
<logger name="*" minlevel="Trace" writeTo="file" />
</rules>
</nlog>
В вашем коде вашЛогика запуска может выглядеть следующим образом:
public void Main()
{
AddHeaderToLogFile();
}
public void AddHeaderToLogFile()
{
Logger headerlogger = LogManager.GetLogger("HeaderLogger");
//Use GlobalDiagnosticContext in 2.0, GDC in pre-2.0
GlobalDiagnosticContext["releasedate"] = GetReleaseDate();
GlobalDiagnosticContext["version"] = GetFileVersion();
GlobalDiagnosticContext["someotherproperty"] = GetSomeOtherProperty();
headerlogger.Info("message doesn't matter since it is not specified in the layout");
//Log file should now have the header as defined by the HeaderLayout
//You could remove the global properties now if you are not going to log them in any
//more messages.
}
Идея в том, что вы должны поместить версию файла, дату выпуска и т. д. в GDC при запуске программы.Зарегистрируйте сообщение с помощью регистратора «HeaderLogger».Это сообщение будет записано в файл журнала с использованием «HeaderLayout», поскольку «HeaderLogger» связан с целью «fileHeader», которая связана с «HeaderLayout».Поля, определенные в макете заголовка, записываются в файл журнала.Сообщения журнала подпоследовательности, поскольку они не будут использовать «HeaderLogger», будут использовать макет «root» (*).Они будут идти к одному и тому же файлу, так как цели «file» и «fileHeader» в конечном итоге будут указывать на одно и то же имя файла.
До того, как я начал печатать этот ответ, я не был уверен, как легко можно было бы добавить заголовокв ваш лог-файл.Набрав это, я думаю, что на самом деле это может быть довольно просто!
Удачи!
[РЕДАКТИРОВАТЬ] Что-то вроде этого может работать для изменения макета в зависимости от уровня.В первом разделе я определил несколько переменных, каждая из которых определяет макет.В следующем разделе я определил несколько целей, каждая из которых использует один и тот же файл, но отфильтрован, чтобы разрешить запись только сообщений определенного уровня.В последнем разделе я определяю единственное правило, которое будет отправлять все сообщения (отсюда и имя «*») всем адресатам.Поскольку каждая цель фильтруется по уровню, цель «trace» будет писать только сообщения «trace» и т. Д. Таким образом, сообщения «trace» будут записываться с использованием макета «trace», сообщения «debug» будут записываться с использованием «debug».макет и т. д. Поскольку все цели в конечном итоге записывают в один и тот же файл, все сообщения будут в конечном итоге в одном файле.Я не пробовал это, но я думаю, что это, вероятно, будет работать.
<variable name="TraceLayout" value="THIS IS A TRACE: ${longdate} ${level:upperCase=true} ${message}" />
<variable name="DebugLayout" value="THIS IS A DEBUG: ${longdate} ${level:upperCase=true} ${message}" />
<variable name="InfoLayout" value="THIS IS AN INFO: ${longdate} ${level:upperCase=true} ${message}" />
<targets async="true">
<target name="fileAsTrace" xsi:type="FilteringWrapper" condition="level==LogLevel.Trace">
<target xsi:type="File" fileName="log.log" layout="${TraceLayout}" />
</target>
<target name="fileAsDebug" xsi:type="FilteringWrapper" condition="level==LogLevel.Debug">
<target xsi:type="File" fileName="log.log" layout="${DebugLayout}" />
</target>
<target name="fileAsInfo" xsi:type="FilteringWrapper" condition="level==LogLevel.Info">
<target xsi:type="File" fileName="log.log" layout="${InfoLayout}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="fileAsTrace, fileAsDebug, fileAsInfo" />
</rules>
(Обратите внимание, что я включил здесь только 3 уровня).
Показав, как (если это работаетво всяком случае), чтобы применить другой макет, основанный на уровне, это похоже на необычный вариант использования.Я не говорю, что это хорошая идея или плохая идея, но я не могу сказать, что я действительно видел, что это сделано очень много.В зависимости от того, как именно вы хотите, чтобы ваш конечный результат выглядел, то, что я показал вам, может быть, а может и не быть лучшим способом достижения этого.Возможно, вы могли бы опубликовать несколько примеров того, как вы хотите, чтобы ваш вывод выглядел.
Вы могли бы также принять мой оригинальный ответ, а затем задать новый вопрос об изменении формата вывода для уровня, чтобы мы могли сосредоточить обсуждение наэтот вопрос на уровне уровня / макета.Это зависит от вас, если это кажется полезным или нет.
Это работает:
<variable name="TraceLayout" value="This is a TRACE - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="DebugLayout" value="This is a DEBUG - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="InfoLayout" value="This is an INFO - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="WarnLayout" value="This is a WARN - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="ErrorLayout" value="This is an ERROR - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="FatalLayout" value="This is a FATAL - ${longdate} | ${logger} | ${level} | ${message}"/>
<targets>
<target name="fileAsTrace" xsi:type="FilteringWrapper" condition="level==LogLevel.Trace">
<target xsi:type="File" fileName="xxx.log" layout="${TraceLayout}" />
</target>
<target name="fileAsDebug" xsi:type="FilteringWrapper" condition="level==LogLevel.Debug">
<target xsi:type="File" fileName="xxx.log" layout="${DebugLayout}" />
</target>
<target name="fileAsInfo" xsi:type="FilteringWrapper" condition="level==LogLevel.Info">
<target xsi:type="File" fileName="xxx.log" layout="${InfoLayout}" />
</target>
<target name="fileAsWarn" xsi:type="FilteringWrapper" condition="level==LogLevel.Warn">
<target xsi:type="File" fileName="xxx.log" layout="${WarnLayout}" />
</target>
<target name="fileAsError" xsi:type="FilteringWrapper" condition="level==LogLevel.Error">
<target xsi:type="File" fileName="xxx.log" layout="${ErrorLayout}" />
</target>
<target name="fileAsFatal" xsi:type="FilteringWrapper" condition="level==LogLevel.Fatal">
<target xsi:type="File" fileName="xxx.log" layout="${FatalLayout}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="fileAsTrace,fileAsDebug,fileAsInfo,fileAsWarn,fileAsError,fileAsFatal" />
<logger name="*" minlevel="Info" writeTo="dbg" />
</rules>
Я установил один макет для каждого уровня ведения журнала, добавив в начале буквальную строку, которая описывает уровень сообщения (это показывает, что для каждого уровня используется другой формат). Каждый макет связан с FilteringWrapper, который фильтрует на основе уровня сообщения и направляет любые сообщения, которые проходят через фильтр, для регистрации в выходном файле. Каждый FilteringWrapper упаковывает один и тот же выходной файл, поэтому все сообщения журнала будут записываться в один и тот же файл.
Вот фрагмент кода, который я использовал для тестирования:
logger.Trace("Trace msg");
logger.Debug("Debug msg");
logger.Info("Info msg");
logger.Warn("Warn msg");
logger.Error("Error msg");
logger.Fatal("Fatal msg");
А вот как выглядит результат:
This is a TRACE - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Trace | Trace msg
This is a DEBUG - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Debug | Debug msg
This is an INFO - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Info | Info msg
This is a WARN - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Warn | Warn msg
This is an ERROR - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Error | Error msg
This is a FATAL - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Fatal | Fatal msg
Видимо, проблема в моей более ранней информации о конфигурации заключалась в пробеле между значениями "writeTo"
. Я думаю, что NLog чувствителен к этому. У меня было что-то вроде "writeTo=blah1, blah2, blah3".
Когда я изменил это на "writeTo=blah1,blah2,blah3"
, ошибка исчезла.
Удачи!