Итак, только что начал использовать NLog. Я выполняю программную реализацию, где я пытаюсь настроить класс, который я могу импортировать в любой проект. Класс имеет два метода: CreateLogger() и GenerateLog(). Вот класс во всей своей полноте:Как заменить NLog Logger новым экземпляром Logger?
using System;
using NLog;
using NLog.Config;
using NLog.Targets;
namespace LogEngine
{
/// <summary>
/// Create an instance of NLog for use on a per class level.
/// </summary>
internal sealed class EventLog
{
#region Internal Methods
/// <summary>
/// Generates the NLog.Logger object that will control logging facilities in this program.
/// </summary>
/// <returns>
/// static reference to a <see cref="NLog.Logger" /> object.
/// </returns>
internal static Logger CreateLogger(string baseDir = @"${basedir}\")
{
// Setup log configuration object and new file and screen output targets.
var config = new LoggingConfiguration();
var screenTarget = new ConsoleTarget();
config.AddTarget("screen", screenTarget);
var fileTarget = new FileTarget();
config.AddTarget("file", fileTarget);
screenTarget.Layout = @"${newline}${message}";
var MinScreenOutput = new LoggingRule("*", LogLevel.Fatal, screenTarget);
config.LoggingRules.Add(MinScreenOutput);
// Set the properties for the file output target.
fileTarget.FileName = baseDir + @"${appdomain:format={1\}} logs\${shortdate}.log";
fileTarget.Layout = @"${longdate} ${pad:padcharacter=~:padding=29:inner= ${level:uppercase=true}}"
+ @" ${pad:padcharacter=~:padding=30:inner= Event ID\: ${event-properties:item=EventCode}}"
+ @"${newline}${message} ${when:when=level == 'Error':inner=${newline}Class/Method\:"
+ @"${pad:padding=9:inner=}${callsite:fileName=true:includeSourcePath=false:skipFrames=1}"
+ @"${newline}Exception\:${pad:padding=14:inner=}${exception}}${newline}";
// Define what sort of events to send to the file output target.
var MinOutputDebug = new LoggingRule("*", LogLevel.Debug, fileTarget);
config.LoggingRules.Add(MinOutputDebug);
// Set the configuration for the LogManager
LogManager.Configuration = config;
// Get the working instance of the logger.
return LogManager.GetLogger("LogEngine");
}
/// <summary>
/// Passes one log entry to the destination logger.
/// </summary>
/// <param name="log">
/// The <see cref="NLog.Logger" /> object to write the log entry to.
/// </param>
/// <param name="eventId">
/// Four character unique event ID as <see cref="System.String" />.
/// </param>
/// <param name="level">
/// The <see cref="NLog.LogLevel" /> value.
/// </param>
/// <param name="message">
/// The message to save to the log file as <see cref="System.String" />.
/// </param>
/// <param name="ex">
/// If this is an error log event, pass it as an <see cref="System.Exception" /> object.
/// </param>
internal static void GenerateLog(Logger log, string eventId, LogLevel level, string message, Exception ex = null)
{
// Values used for all events.
LogEventInfo logEvent = new LogEventInfo();
logEvent.Properties["EventCode"] = eventId;
logEvent.Level = level;
logEvent.Message = message;
// If we have an error log, make sure the exception is passed.
if (level.Equals(LogLevel.Error))
logEvent.Exception = ex;
// Actually write the log entry.
log.Log(logEvent);
if (level.Equals(LogLevel.Error) || level.Equals(LogLevel.Fatal))
System.Environment.Exit(Convert.ToInt32(eventId));
}
#endregion Internal Methods
}
}
В методе CreateLogger(), вы увидите, есть параметр по умолчанию. Итак, как это работает, когда я называю CreateLogger() в моей программе в начале моего класса, я не передавать никаких параметров и значение $ {имя_базовой_папки} используется для генерации начального протоколирования:
internal class Program
{
#region Private Fields
private static Logger log = EventLog.CreateLogger();
#endregion Private Fields
...
Однако, во время Мне нужно изменить местоположение регистрации из $ {basedir} в значение, которое я извлекаю из базы данных SQL. Вот как я это сделать:
if (!path.Equals(null))
{
sArgs.path = path.ToString().Trim();
//NLog.Config.SimpleConfigurator.ConfigureForFileLogging(sArgs.path + @"Logs\log1.txt", LogLevel.Debug);
//LogManager.Shutdown();
//LogManager.ReconfigExistingLoggers();
log = EventLog.CreateLogger(sArgs.path);
LogManager.ReconfigExistingLoggers();
}
«путь» является объект, возвращаемый вызовом SQLCommand.ExecuteScalar(). Это замена $ {basedir}, что мне нужно подключить мой Logger. Если путь не равен NULL, тогда я преобразовываю его в строку и сохраняю его в одноэлементный класс, созданный как «sArgs». Здесь есть какой-то прокомментированный код, чтобы показать, как я пытался решить эту проблему.
Хорошо, поэтому то, что я вижу, находится в последнем блоке кода (когда я установил «журнал» в новый экземпляр, сгенерированный CreateLogger (sArgs.path)). Я вижу, что мой путь ведения журнала в объекте журнала фактически обновление. Но, когда я получаю первую возможность регистрировать событие, он все еще использует старый экземпляр Logger (так что $ {basedir} все еще используется, а не sArgs.path).
Мой вопрос в том, что мне не хватает, что сохраняет изменения в «log», которые я могу явно видеть, когда мой код в отладчике меняет код, фактически становясь местом для объекта Logger? Или это то, что я делаю класс EventLog совершенно неправильным?
Благодарим за понимание, которое вы можете предоставить этой проблеме.
Спасибо @Riaan. Не знаю, почему я этого не видел, но это именно то, что происходит с моей следующей возможностью генерировать журнал после обновления пути в другом классе. Итак, означает ли это, что я должен скрывать класс EventLogger (как вы его назвали) в одноэлементный класс? Это означало бы, когда я введу метод, который я хочу выполнить, мне нужно будет связать его с экземпляром singleton (например, я делаю с sArgs для хранения аргументов моей программы). – breusshe
Я думаю, мне также нужно будет обновить свой макет, поэтому вызов $ {callsite: fileName = true: includeSourcePath = false: skipFrames = 1} будет обновлять skipFrames до равного 2, чтобы фактический метод, в котором происходит ошибка, сохраняется. – breusshe
На самом деле, теперь, когда я думаю об этом, возможно, один-одинетовый класс не подходит для этого. Что мне действительно нужно сделать, так это выяснить, как Class1 проверяет, нужно ли обновлять его конфигурацию. – breusshe