NLog динамически меняет имя файла, используя NLog.config
Как динамически изменить FileName, используя переменную из C#? Моя идея состоит в том, чтобы создать файл журнала, как Log_<UserId_From_DB>_${date:format=yyyy-MM-dd}.log
, Есть идеи?
3 ответа
Другой вариант - использовать глобальный контекст диагностики - $ (GDC):
Установите значение в C#
GlobalDiagnosticsContext.Set("UserId_From_DB","42");
В конфиге (nlog.config):
<target type="file" filename="Log_${gdc:item=UserId_From_DB}_${date:format=yyyy-MM-dd}.log" ..>
Пожалуйста, избегайте изменения переменных NLog во время выполнения (см. Предыдущий ответ ниже). Они должны рассматриваться как только для чтения, потому что они не потокобезопасны. Переменные NLog также будут затронуты, если LoggingConfiguration будет перезагружен.
Предыдущий ответ с переменными NLog:
Установите значение в C#
LogManager.Configuration.Variables["UserId_From_DB"] = "42";
В конфиге (nlog.config):
<target type="file" filename="Log_${var:UserId_From_DB}_${date:format=yyyy-MM-dd}.log" ..>
Если значение будет установлено снова, имя файла будет автоматически изменено.
Пока опубликованный ответ работает, он страдает от проблем параллелизма. Эта переменная является глобальной переменной, и вы можете столкнуться с конфликтами.
Доступно лучшее решение. Есть способ передать свойства события в NLog.
Ссылка на соответствующую документацию NLog.
Предположим, вы хотите записать сообщение об ошибке:
Logger myLog = LogManager.GetLogger(name);
LogLevel level = LogLevel.Error;
string message = "This is an error message!";
Вы превращаете эту информацию в LogEventInfo
объект:
LogEventInfo logEvent = new LogEventInfo(level , myLog.Name, message);
Затем вы можете добавить свойства к этому событию (строковые индексы могут свободно выбирать):
logEvent.Properties["MySpecialValue"] = "SPECIAL";
И тогда вы пишете в журнал:
myLog.Log(logEvent);
Интересно, что в вашей конфигурации NLog вы можете использовать это настраиваемое свойство в любом поле, которое в документации Nlog называется значением "Layout".
Ты используешь ${event-properties:item=MySpecialValue}
в макете для доступа к свойству. Например:
<target xsi:type="File"
name="file"
fileName="${basedir}/logs/${event-properties:item=MySpecialValue}/my_${event-properties:item=MySpecialValue}_file.log"
layout="${event-properties:item=MySpecialValue} ${message}" />
Следуя опубликованному примеру, вы получите папку с именем SPECIAL
внутри которого находится файл журнала с именем my_SPECIAL_file.log
в котором вы найдете сообщение SPECIAL This is an error message!
, Просто чтобы доказать, что вы можете использовать это пользовательское значение разными способами и формами.
Я обычно использую это, чтобы вести запись, зависящую от сущности (где имя файла журнала равно значению идентификатора сущности), что по сути то же самое, что вы хотите сделать здесь.
В качестве краткого совета я склоняюсь к тому, чтобы обернуть NLog Logger в свой собственный класс:
public class UserLogger
{
private readonly Logger _log;
private readonly User _user;
public UserLogger(User u)
{
_user = u;
_log = LogManager.GetCurrentClassLogger();
}
public void Error(string message)
{
LogEventInfo logEvent =
new LogEventInfo(LogLevel.Error, _log.Name, message);
logEvent.Properties["UserId"] = _user.Id;
_log.Log(logEvent);
}
}
Это всего лишь простой пример для начала. Крутая особенность, которую я здесь использую, заключается в том, что я определил имя файла журнала (в цели Nlog.Config), используя UserId
значение и, следовательно, может гарантировать, что каждый пользователь будет зарегистрирован в свой собственный уникальный файл журнала.
Таким образом, вы можете принудительно установить, что идентификатор пользователя известен, когда вы хотите войти в цель "user log". В качестве дополнительного бонуса, он также аккуратно отделяет зависимости NLog от вашего вызывающего кода.
Предполагая, что у вас есть файл журнала с именем mylogfile.log в вашем файле nlog.config
FileTarget target = LogManager.Configuration.FindTargetByName("mylogfile.log") as FileTarget;
String customlog = "Log_" + GetUserId(UserId_From_DB) + "_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
target.FileName = customlog;