using System; using System.IO; using System.Linq; using NLog; using NLog.Config; using NLog.Targets; using NLog.Targets.Wrappers; using MediaBrowser.Model.Logging; namespace Emby.Common.Implementations.Logging { /// /// Class NlogManager /// public class NlogManager : ILogManager { /// /// Occurs when [logger loaded]. /// public event EventHandler LoggerLoaded; /// /// Gets or sets the log directory. /// /// The log directory. private string LogDirectory { get; set; } /// /// Gets or sets the log file prefix. /// /// The log file prefix. private string LogFilePrefix { get; set; } /// /// Gets the log file path. /// /// The log file path. public string LogFilePath { get; private set; } /// /// Gets or sets the exception message prefix. /// /// The exception message prefix. public string ExceptionMessagePrefix { get; set; } /// /// Initializes a new instance of the class. /// /// The log directory. /// The log file name prefix. public NlogManager(string logDirectory, string logFileNamePrefix) { LogDirectory = logDirectory; LogFilePrefix = logFileNamePrefix; LogManager.Configuration = new LoggingConfiguration (); } private LogSeverity _severity = LogSeverity.Debug; public LogSeverity LogSeverity { get { return _severity; } set { var changed = _severity != value; _severity = value; if (changed) { UpdateLogLevel(value); } } } private void UpdateLogLevel(LogSeverity newLevel) { var level = GetLogLevel(newLevel); var rules = LogManager.Configuration.LoggingRules; foreach (var rule in rules) { if (!rule.IsLoggingEnabledForLevel(level)) { rule.EnableLoggingForLevel(level); } foreach (var lev in rule.Levels.ToArray()) { if (lev < level) { rule.DisableLoggingForLevel(lev); } } } } /// /// Adds the file target. /// /// The path. /// The level. private void AddFileTarget(string path, LogSeverity level) { RemoveTarget("ApplicationLogFileWrapper"); var wrapper = new AsyncTargetWrapper (); wrapper.Name = "ApplicationLogFileWrapper"; var logFile = new FileTarget { FileName = path, Layout = "${longdate} ${level} ${logger}: ${message}" }; logFile.Name = "ApplicationLogFile"; wrapper.WrappedTarget = logFile; AddLogTarget(wrapper, level); } /// /// Adds the log target. /// /// The target. /// The level. public void AddLogTarget(Target target, LogSeverity level) { var config = LogManager.Configuration; config.AddTarget(target.Name, target); var rule = new LoggingRule("*", GetLogLevel(level), target); config.LoggingRules.Add(rule); LogManager.Configuration = config; } /// /// Removes the target. /// /// The name. public void RemoveTarget(string name) { var config = LogManager.Configuration; var target = config.FindTargetByName(name); if (target != null) { foreach (var rule in config.LoggingRules.ToList()) { var contains = rule.Targets.Contains(target); rule.Targets.Remove(target); if (contains) { config.LoggingRules.Remove(rule); } } config.RemoveTarget(name); LogManager.Configuration = config; } } /// /// Gets the logger. /// /// The name. /// ILogger. public MediaBrowser.Model.Logging.ILogger GetLogger(string name) { return new NLogger(name, this); } /// /// Gets the log level. /// /// The severity. /// LogLevel. /// Unrecognized LogSeverity private LogLevel GetLogLevel(LogSeverity severity) { switch (severity) { case LogSeverity.Debug: return LogLevel.Debug; case LogSeverity.Error: return LogLevel.Error; case LogSeverity.Fatal: return LogLevel.Fatal; case LogSeverity.Info: return LogLevel.Info; case LogSeverity.Warn: return LogLevel.Warn; default: throw new ArgumentException("Unrecognized LogSeverity"); } } /// /// Reloads the logger. /// /// The level. public void ReloadLogger(LogSeverity level) { LogFilePath = Path.Combine(LogDirectory, LogFilePrefix + "-" + decimal.Floor(DateTime.Now.Ticks / 10000000) + ".txt"); Directory.CreateDirectory(Path.GetDirectoryName(LogFilePath)); AddFileTarget(LogFilePath, level); LogSeverity = level; if (LoggerLoaded != null) { try { LoggerLoaded(this, EventArgs.Empty); } catch (Exception ex) { GetLogger("Logger").ErrorException("Error in LoggerLoaded event", ex); } } } /// /// Flushes this instance. /// public void Flush() { LogManager.Flush(); } public void AddConsoleOutput() { RemoveTarget("ConsoleTargetWrapper"); var wrapper = new AsyncTargetWrapper (); wrapper.Name = "ConsoleTargetWrapper"; var target = new ConsoleTarget() { Layout = "${level}, ${logger}, ${message}", Error = false }; target.Name = "ConsoleTarget"; wrapper.WrappedTarget = target; AddLogTarget(wrapper, LogSeverity); } public void RemoveConsoleOutput() { RemoveTarget("ConsoleTargetWrapper"); } } }