using MediaBrowser.Model.Logging ;
using NLog ;
using NLog.Config ;
using NLog.Targets ;
using NLog.Targets.Wrappers ;
using System ;
using System.IO ;
using System.Linq ;
namespace MediaBrowser.Common.Implementations.Logging
{
/// <summary>
/// Class NlogManager
/// </summary>
public class NlogManager : ILogManager
{
/// <summary>
/// Occurs when [logger loaded].
/// </summary>
public event EventHandler LoggerLoaded ;
/// <summary>
/// Gets or sets the log directory.
/// </summary>
/// <value>The log directory.</value>
private string LogDirectory { get ; set ; }
/// <summary>
/// Gets or sets the log file prefix.
/// </summary>
/// <value>The log file prefix.</value>
private string LogFilePrefix { get ; set ; }
/// <summary>
/// Gets the log file path.
/// </summary>
/// <value>The log file path.</value>
public string LogFilePath { get ; private set ; }
/// <summary>
/// Gets or sets the exception message prefix.
/// </summary>
/// <value>The exception message prefix.</value>
public string ExceptionMessagePrefix { get ; set ; }
/// <summary>
/// Initializes a new instance of the <see cref="NlogManager" /> class.
/// </summary>
/// <param name="logDirectory">The log directory.</param>
/// <param name="logFileNamePrefix">The log file name prefix.</param>
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 ) ;
}
}
}
}
/// <summary>
/// Adds the file target.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="level">The level.</param>
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 ) ;
}
/// <summary>
/// Adds the log target.
/// </summary>
/// <param name="target">The target.</param>
/// <param name="level">The level.</param>
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 ;
}
/// <summary>
/// Removes the target.
/// </summary>
/// <param name="name">The name.</param>
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 ;
}
}
/// <summary>
/// Gets the logger.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>ILogger.</returns>
public Model . Logging . ILogger GetLogger ( string name )
{
return new NLogger ( name , this ) ;
}
/// <summary>
/// Gets the log level.
/// </summary>
/// <param name="severity">The severity.</param>
/// <returns>LogLevel.</returns>
/// <exception cref="System.ArgumentException">Unrecognized LogSeverity</exception>
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" ) ;
}
}
/// <summary>
/// Reloads the logger.
/// </summary>
/// <param name="level">The level.</param>
public void ReloadLogger ( LogSeverity level )
{
LogFilePath = Path . Combine ( LogDirectory , LogFilePrefix + "-" + decimal . Round ( 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 ) ;
}
}
}
/// <summary>
/// Flushes this instance.
/// </summary>
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" ) ;
}
}
}