Для логирования сервис NOMAD 2.x использует библиотеку NLog. Это значит, что огромное число возможностей NLog доступно при работе с логами сервиса. Настройки задаются в файле LogSettings.config. При старте сервиса создается рабочая копия файла конфигурации LogSettings.live.config, изменение которого подхватывается без перезагрузки сервиса и затирается значениями LogSettings.config при рестарте сервиса.
Для записи данных необходимо добавить новый logger в файл конфигурации, аналогично уже существующим:
<logger name="*" minlevel="Debug" writeTo="file"/>
<logger name="*" minlevel="Trace" writeTo="file-trace"/>
<logger name="Nomad.Request" writeTo="request"/>
Формат записи и путь определяются таргетами. Таргеты file и file-trace используются для записи основной информации о работе сервиса, request — для записи запросов к сервису и его ответов.
<target name="file" xsi:type="File"
fileName="${logs-path}\server.${shortdate}.log"
header="${newline}${date:Format=yyyy-MM-dd HH\:mm\:ss.fff K} ************** ${processname} started (${version}) **************${newline}"
footer="${newline}${date:Format=yyyy-MM-dd HH\:mm\:ss.fff K} ************** ${processname} closed (${version}) **************${newline}"
layout="${file-layout}"
encoding="utf-8" />
Формат вывода задан в переменной file-layout:
<variable name="file-layout"
value="${date:Format=yyyy-MM-dd HH\:mm\:ss.fff K}${char:Code=9}${level:padding=-5}${char:Code=9}${message}${ex-additional-info} ${onexception:${newline}${exception:format=tostring}} ${onexception:${event-context:item=description:WhenEmpty=Contact your system administrator}}${char:Code=9}${vc:LoginName}${char:Code=9}${vc:IPAddress}${char:Code=9}${vc:RequestURL}${char:Code=9}${vc:ApplicationName}${char:Code=9}${vc:UserAgent}${char:Code=9}RequestNumber=${vc:RequestNumber}${char:Code=9}${version}${char:Code=9}${fixed-length:inner=${logger}:maxLength=45:keepRightPart=true:padding=45}${char:Code=9}Process=${processid}:${threadid:padding=-2}" />
NLog умеет выполнять перенос архивных лог-файлов. Правила архивирования добавляются в уже существующие file targets.
<target name="file" xsi:type="File"
fileName="${logs-path}\server.${shortdate}.log"
header="${newline}${date:Format=yyyy-MM-dd HH\:mm\:ss.fff K} ************** ${processname}started (${version}) **************${newline}"
footer="${newline}${date:Format=yyyy-MM-dd HH\:mm\:ss.fff K} ************** ${processname}closed (${version}) **************${newline}"
layout="${file-layout}"
encoding="utf-8"
archiveFileName="${archive-path}\server.{##}.${shortdate}.zip"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="5"
concurrentWrites="true"
enableArchiveFileCompression="true" />
Удобным может оказаться хранение лог-файлов в базе данных. Предварительно нужно создать таблицу, в которую будут записываться данные, например, так:
create database NOMAD_LOG_STORAGE
go
if not exists (select * from dbo.sysobjects where id = object_id(N'[NOMAD_LOG_STORAGE].[dbo].[NOMADLogs]') and objectproperty(id, N'IsUserTable') = 1)
begin
create table [NOMAD_LOG_STORAGE].[dbo].[NOMADLogs](
[Id] int primary key identity(1,1) not null,
[LogDateTime] varchar (30),
[LogLevel] varchar(5),
[LogMessage] varchar(500),
[Exception] varchar(1000),
[UserLogin] varchar(30),
[IpAddress] varchar (15),
[Url] varchar(50),
[UserAgent] varchar (100),
[RequestNumber] varchar (10),
[Version] varchar (50),
[Logger] varchar (100),
[ProcessId] varchar(10),
[ThreadId] varchar(5)
)
end
В параметрах database target необходимо указать строку подключения к базе данных, и написать запрос, добавляющий информацию в таблицу. Параметр dbProvider здесь не указан, так как используется значение по умолчанию sqlserver.
<target name="database" xsi:type="Database"
connectionString="Data Source=***;Initial Catalog=NOMAD_LOG_STORAGE;Integrated Security=False;User ID=***;Password=***">
<commandText>
INSERT INTO [NOMAD_LOG_STORAGE].[dbo].[NOMADLogs]
(
[LogDateTime],
[LogLevel],
[LogMessage],
[Exception],
[UserLogin],
[IpAddress],
[Url],
[UserAgent],
[RequestNumber],
[Version],
[Logger],
[ProcessId],
[ThreadId]
)
VALUES
(
@logDateTime,
@level,
@message,
@exception,
@login,
@ipAddress,
@url,
@userAgent,
@requestNumber,
@version,
@logger,
@processId,
@threadId
)
</commandText>
<parameter name="@logDateTime" layout="${date:Format=yyyy-MM-dd HH\:mm\:ss.fff K}"/>
<parameter name="@level" layout="${fixed-length:inner=${level}:maxLength=5}"/>
<parameter name="@message" layout="${fixed-length:inner=${message}:maxLength=500}"/>
<parameter name="@exception" layout="${fixed-length:inner=${exception:format=tostring}:maxLength=1000}"/>
<parameter name="@login" layout="${fixed-length:inner=${vc:LoginName}:maxLength=30}"/>
<parameter name="@ipAddress" layout="${fixed-length:inner=${vc:IPAddress}:maxLength=15}"/>
<parameter name="@url" layout="${fixed-length:inner=${vc:RequestURL}:maxLength=50:keepRightPart=true}"/>
<parameter name="@userAgent" layout="${fixed-length:inner=${vc:UserAgent}:maxLength=100}"/>
<parameter name="@requestNumber" layout="${fixed-length:inner=${vc:RequestNumber}:maxLength=10}"/>
<parameter name="@version" layout="${fixed-length:inner=${version}:maxLength=50}"/>
<parameter name="@logger" layout="${fixed-length:inner=${logger}:maxLength=50:keepRightPart=true:padding=50}"/>
<parameter name="@processId" layout="${fixed-length:inner=${processid}:maxLength=10}"/>
<parameter name="@threadId" layout="${fixed-length:inner=${threadid}:maxLength=5}"/>
</target>
Для отладки и поиска ошибок конфигурации полезно использовать атрибуты throwExceptions и internalLogFile элемента nlog.
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
throwExceptions="true"
internalLogFile="${basedir}\NLogLogs\internal_log_file.txt" >
NLog позволяет не только записать логи в файл, но и отправить сообщение на почту через сервер SMTP. Чтобы, например, отправлять администратору уведомления о произошедших критических ошибках достаточно добавить mail target и использовать его в logger с уровнем логирования Fatal.
<target name="email" xsi:type = "Mail"
smtpServer="mail.companyname.com"
smtpPort="25"
smtpAuthentication="Basic"
smtpUserName="bot@companyname.ru"
smtpPassword="password"
enableSsl="false"
from="bot@companyname.ru"
to="administrator@companyname.ru"
body="${error-layout}"
/>
<logger name="*" minlevel="Fatal" writeTo="email" />
В описание логера можно добавить фильтр, который будет работать, не зависимо, от того, в какой target передаются данные.
Например, вот таким фильтром можно отловить событие превышения попыток входа пользователя и инициировать отправку сообщения на email:
<logger name="*" minlevel="Warn" writeTo="email">
<filters>
<when condition="not contains('${message}','Доступ запрещен. Неверный пароль введен 5 раз.') and not contains('${message}', 'Access denied. You have entered an incorrect password 5 times.')" action="Ignore" />
</filters>
</logger>
Или сохранить статистику по экспорту и импорту документов в отдельную таблицу в базе данных:
<target name="documentDatabaseTable" xsi:type="Database"
...
/>
<logger name="*" writeTo="documentDatabaseTable">
<filters>
<when condition="not contains('${message}','DocumentExport') and not contains('${message}', 'DocumentImport')" action="Ignore" />
</filters>
</logger>
Если вы будете самостоятельно разбираться с NLog и настраивать использование какой-либо возможности, помимо ссылок на вики: targets, layouts, layout-renderers, wrappers вам будут полезны изменения по версиям, чтобы уточнить с какой версии поддерживается фича (сейчас Nomad использует NLog версии 4.0).
Если уже вся вики прочитана, но вас не покидает ощущение, что чего-то не хватает, самый простой способ добавить необходимую функциональность — использовать methodCall target. Логика сбора, обработки и хранения логов реализуется в .NET сборке, которая должна содержать общедоступный статический метод, в параметры которого передается сообщение и другие необходимые параметры, например, уровень логирования.
namespace CustomLogging
{
public class Logger
{
public static void AwesomeMethod(string message, string logLevel)
{
...
}
}
}
В файле конфигурации указывается название метода и класса, в котором он находится.
<target name="methodCall" xsi:type="MethodCall"
methodName="AwesomeMethod"
className="CustomLogging.Logger, CustomLogging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<parameter layout="${message}" name="String" type="System.Type" />
<parameter layout="${level}" name="String" type="System.Type" />
</target>
<logger name="*" minlevel="Debug" writeTo="methodCall" />
Чтобы сборка загрузилась и была доступна во время работы сервиса, она должна лежать в папке /bin сайта.
Хочется отметить, что изменение формата вывода в файлы server, server.trace и request не рекомендуется, так как сотрудники СПД работают именно с такими логами. А ещё такой формат файлов позволит использовать утилиту AppHealth, которая идет в поставке с NOMAD . Для ваших собственных настроек следует создавать свой target и добавлять новый logger.
Авторизуйтесь, чтобы написать комментарий