The NLogAdapter example demonstrates how to add a custom LogAdapter to the DCF.
Classes
Class | Description | |
---|---|---|
NLogLogAdapter |
Adapter class to demonstrate using NLog as the back end log facility.
|
Examples
LogAdapter Sample Code
public sealed class NLogLogAdapter : ILogAdapter, IDisposable { private Logger _logger; private static readonly object[] NullParams = null; private const string NullMessage = "null message"; private const string NullFormat = "null format"; private static readonly string _nlogConfigName = "NLog4.config"; private static readonly string _nlogConfigNameKey = "nlogConfigName"; /// <summary> /// Constructor that configures NLog using the input path to the desired nlog configuration xml file. /// </summary> /// <remarks> /// The logger is constructed using the type of the calling class. /// </remarks> /// <param name="cfgFilePath">The path of the xml configuration file to use to configure NLog. If the file is null or /// missing, the already loaded nlog configuration will be used.</param> /// <param name="formatProvider">The format provider to use when logging messages to nlog, which if set to null will use /// CultureInfo.InvariantCulture.</param> public NLogLogAdapter(string cfgFilePath = null, IFormatProvider formatProvider = null) { if (!String.IsNullOrEmpty(cfgFilePath) && File.Exists(cfgFilePath)) { try { LoggingConfiguration nlogConfig = new XmlLoggingConfiguration(cfgFilePath); LogManager.Configuration = nlogConfig; } catch { Console.WriteLine("Error creating new nlog configuration. Using default..."); } } FormatProvider = formatProvider ?? CultureInfo.InvariantCulture; // get the type of the caller Type declaringType = new StackFrame(1).GetMethod().DeclaringType; _logger = LogManager.GetLogger(declaringType == null ? "UnknownType" : declaringType.FullName); } /// <summary> /// Get/Set the format provider to use when logging messages to nlog. /// </summary> /// <remarks> /// Unless otherwise specified, a default value of CultureInfo.InvariantCulture will be used. /// </remarks> public IFormatProvider FormatProvider { get; set; } /// <summary> /// Get the file name associated with a logging target name. Dig through any /// wrapper filters until we get to a file target and return the directory name. /// </summary> /// <param name="targetName">The target name.</param> /// <returns>The path to the NLog directory.</returns> public static string GetNLogLogDirectoryPath(string targetName) { Target target = NLog.LogManager.Configuration.FindTargetByName(targetName); if (target == null) throw new ArgumentException("target(" + targetName + ") not found"); while (target is WrapperTargetBase) { target = (target as WrapperTargetBase).WrappedTarget; } FileTarget fileTarget = target as FileTarget; if (fileTarget == null) throw new ArgumentException("could not find file target for target(" + targetName + ")"); // Following is a way to get the path of the NLog file LogEventInfo logEventInfo = new LogEventInfo { TimeStamp = DateTime.Now }; string fileName = fileTarget.FileName.Render(logEventInfo); string directoryName = Path.GetDirectoryName(fileName) ?? "."; return directoryName; } /// <summary> /// Reconfigures the output log directory for the file logger. /// </summary> /// <remarks> /// <para> /// This will only change the log directory if the input log dir is not null or empty and the name of the nlog configuration /// file used to configure the current logger matches the expected name for this nlog log adapter. /// </para> /// <para> /// This method is provided for testing purposes in order to programmatically alter the output directory for various types of /// file loggers (session logging, rotating logging, etc). It is recommended to alter the application configuration file where /// possible if a different output log directory is desired. /// </para> /// </remarks> /// <param name="logDir">The new log output directory for the file logger.</param> /// <param name="targetName">The name of the NLog FileTarget whose log directory will be reconfigured. If none /// is specified, the default target name of 'FileLogger' is used.</param> /// <param name="logDirConfigName">The name of the logDir configuration variable in the currently loaded NLog configuration. /// Default value is logDir.</param> /// <param name="logNameConfigName">The name of the logName configuration variable in the currently loaded NLog configuration. /// Default value is logName.</param> /// <param name="extension">The extension of the log file. Default value is .log.</param> public void ReconfigureLogDirectory(string logDir, string targetName = "FileLogger", string logDirConfigName = "logDir", string logNameConfigName = "logName", string extension = ".log") { if (_logger == null) throw new ObjectDisposedException("NLogLogAdapter"); if (!String.IsNullOrEmpty(logDir) && CheckNLogConfigName()) { try { LoggingConfiguration cfg = LogManager.Configuration; IDictionary<string, SimpleLayout> layouts = cfg.Variables; if (layouts.ContainsKey(logDirConfigName)) { FileTarget target = cfg.FindTargetByName(targetName) as FileTarget; if (target == null) return; string fileName = layouts[logNameConfigName].Text; target.FileName = Path.Combine(logDir, fileName + (extension ?? String.Empty)); if (target.ArchiveFileName != null && target.ArchiveFileName.ToString() != String.Empty) target.ArchiveFileName = Path.Combine(logDir, "Archive", fileName, "{#}" + extension); LogManager.ReconfigExistingLoggers(); } } catch (Exception e) { ErrorFormat(new LogEvent(GetType().FullName), e, "Error changing log directory:"); } } } #region Helpers private bool CheckNLogConfigName() { if (LogManager.Configuration == null || !LogManager.Configuration.Variables.ContainsKey(_nlogConfigNameKey)) return false; string nlogConfigName = LogManager.Configuration.Variables[_nlogConfigNameKey].Text; return nlogConfigName.Equals(_nlogConfigName); } private void WriteLogMessage(LogLevel level, LogEvent context, Exception e, object message) { WriteLogMessage(level, context, e, (message == null ? NullMessage : message.ToString()), NullParams); } private void WriteLogMessage(LogLevel level, LogEvent context, Exception e, string format, params object[] args) { if (format == null) format = NullFormat; LogEventInfo logEventInfo = new LogEventInfo(level, context.LoggerName, FormatProvider, format, args, e); logEventInfo.Properties["SessionId"] = context.IsDefaultSession ? (object)String.Empty : context.SessionId; logEventInfo.Properties["SessionName"] = context.SessionName; if (context.HasLogContext) { IDictionary<object, object> contextItems = context.GetLogContext(); foreach (string key in contextItems.Keys) { logEventInfo.Properties[key] = contextItems[key]; } } _logger.Log(logEventInfo); } #endregion #region ILogAdapter Members /// <summary> /// Log a fatal level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="message">The message object.</param> public void Fatal(LogEvent context, Exception e, object message) { WriteLogMessage(LogLevel.Fatal, context, e, message); } /// <summary> /// Log a fatal level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="format">The format string for the message.</param> /// <param name="args">The arguments to the formatted message.</param> public void FatalFormat(LogEvent context, Exception e, string format, params object[] args) { WriteLogMessage(LogLevel.Fatal, context, e, format, args); } /// <summary> /// Log an error level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="message">The message object.</param> public void Error(LogEvent context, Exception e, object message) { WriteLogMessage(LogLevel.Error, context, e, message); } /// <summary> /// Log an error level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="format">The format string for the message.</param> /// <param name="args">The arguments to the formatted message.</param> public void ErrorFormat(LogEvent context, Exception e, string format, params object[] args) { WriteLogMessage(LogLevel.Error, context, e, format, args); } /// <summary> /// Log a warn level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="message">The message object.</param> public void Warn(LogEvent context, Exception e, object message) { WriteLogMessage(LogLevel.Warn, context, e, message); } /// <summary> /// Log a warn level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="format">The format string for the message.</param> /// <param name="args">The arguments to the formatted message.</param> public void WarnFormat(LogEvent context, Exception e, string format, params object[] args) { WriteLogMessage(LogLevel.Warn, context, e, format, args); } /// <summary> /// Log an info level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="message">The message object.</param> public void Info(LogEvent context, Exception e, object message) { WriteLogMessage(LogLevel.Info, context, e, message); } /// <summary> /// Log an info level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="format">The format string for the message.</param> /// <param name="args">The arguments to the formatted message.</param> public void InfoFormat(LogEvent context, Exception e, string format, params object[] args) { WriteLogMessage(LogLevel.Info, context, e, format, args); } /// <summary> /// Log a debug level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="message">The message object.</param> public void Debug(LogEvent context, Exception e, object message) { WriteLogMessage(LogLevel.Debug, context, e, message); } /// <summary> /// Log a debug level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="format">The format string for the message.</param> /// <param name="args">The arguments to the formatted message.</param> public void DebugFormat(LogEvent context, Exception e, string format, params object[] args) { WriteLogMessage(LogLevel.Debug, context, e, format, args); } /// <summary> /// Log a verbose level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="message">The message object.</param> public void Verbose(LogEvent context, Exception e, object message) { WriteLogMessage(LogLevel.Trace, context, e, message); } /// <summary> /// Log a verbose level message to the logging backend. /// </summary> /// <param name="context">The LogEvent for this message.</param> /// <param name="e">An exception to be logged if non-null.</param> /// <param name="format">The format string for the message.</param> /// <param name="args">The arguments to the formatted message.</param> public void VerboseFormat(LogEvent context, Exception e, string format, params object[] args) { WriteLogMessage(LogLevel.Trace, context, e, format, args); } /// <summary> /// Flush any pending buffered log messages. The implementation of this method is defined by the LogAdapter. /// </summary> public void Flush() { if (_logger == null) throw new ObjectDisposedException("NLogLogAdapter"); LogManager.Flush(); } #endregion #region IDisposable Members /// <summary> /// Flush any pending buffered log messages and cleanup logger resources. /// </summary> /// <remarks> /// NLog hooks up to the AppDomain.CurrentDomain.ProcessExit and AppDomain.CurrentDomain.DomainUpload events, and /// as such, will automatically shutdown each logger. LogManager.Shutdown currently has a significant expense wrt /// how long it takes to dispose. /// </remarks> public void Dispose() { if (_logger == null) return; try { LogManager.Flush(); LogManager.Shutdown(); } catch (Exception) { // ignored } finally { _logger = null; } } #endregion }