diff options
Diffstat (limited to 'Emby.Server.Implementations/Logging/SimpleLogManager.cs')
| -rw-r--r-- | Emby.Server.Implementations/Logging/SimpleLogManager.cs | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/Logging/SimpleLogManager.cs b/Emby.Server.Implementations/Logging/SimpleLogManager.cs new file mode 100644 index 000000000..6129f38c4 --- /dev/null +++ b/Emby.Server.Implementations/Logging/SimpleLogManager.cs @@ -0,0 +1,301 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; + +namespace Emby.Server.Implementations.Logging +{ + public class SimpleLogManager : ILogManager, IDisposable + { + public LogSeverity LogSeverity { get; set; } + public string ExceptionMessagePrefix { get; set; } + private FileLogger _fileLogger; + + private readonly string LogDirectory; + private readonly string LogFilePrefix; + public string DateTimeFormat = "yyyy-MM-dd HH:mm:ss.fff"; + + public SimpleLogManager(string logDirectory, string logFileNamePrefix) + { + LogDirectory = logDirectory; + LogFilePrefix = logFileNamePrefix; + } + + public ILogger GetLogger(string name) + { + return new NamedLogger(name, this); + } + + public void ReloadLogger(LogSeverity severity) + { + LogSeverity = severity; + + var logger = _fileLogger; + if (logger != null) + { + logger.Dispose(); + } + + var path = Path.Combine(LogDirectory, LogFilePrefix + "-" + decimal.Floor(DateTime.Now.Ticks / 10000000) + ".txt"); + + _fileLogger = new FileLogger(path); + + if (LoggerLoaded != null) + { + try + { + + LoggerLoaded(this, EventArgs.Empty); + + } + catch (Exception ex) + { + GetLogger("Logger").ErrorException("Error in LoggerLoaded event", ex); + } + } + } + + public event EventHandler LoggerLoaded; + + public void Flush() + { + var logger = _fileLogger; + if (logger != null) + { + logger.Flush(); + } + } + + private bool _console = true; + public void AddConsoleOutput() + { + _console = true; + } + + public void RemoveConsoleOutput() + { + _console = false; + } + + public void Log(string message) + { + if (_console) + { + Console.WriteLine(message); + } + + var logger = _fileLogger; + if (logger != null) + { + message = DateTime.Now.ToString(DateTimeFormat) + " " + message; + + logger.Log(message); + } + } + + public void Dispose() + { + var logger = _fileLogger; + if (logger != null) + { + logger.Dispose(); + } + + _fileLogger = null; + GC.SuppressFinalize(this); + } + } + + public class FileLogger : IDisposable + { + private readonly FileStream _fileStream; + + private bool _disposed; + private readonly CancellationTokenSource _cancellationTokenSource; + private readonly BlockingCollection<string> _queue = new BlockingCollection<string>(); + + public FileLogger(string path) + { + Directory.CreateDirectory(Path.GetDirectoryName(path)); + + _fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, 32768); + _cancellationTokenSource = new CancellationTokenSource(); + + Task.Factory.StartNew(LogInternal, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + } + + private void LogInternal() + { + while (!_cancellationTokenSource.IsCancellationRequested && !_disposed) + { + try + { + foreach (var message in _queue.GetConsumingEnumerable()) + { + var bytes = Encoding.UTF8.GetBytes(message + Environment.NewLine); + if (_disposed) + { + return; + } + + _fileStream.Write(bytes, 0, bytes.Length); + + _fileStream.Flush(true); + } + } + catch + { + + } + } + } + + public void Log(string message) + { + if (_disposed) + { + return; + } + + _queue.Add(message); + } + + public void Flush() + { + if (_disposed) + { + return; + } + + _fileStream.Flush(true); + } + + public void Dispose() + { + _cancellationTokenSource.Cancel(); + + Flush(); + + _disposed = true; + _fileStream.Dispose(); + GC.SuppressFinalize(this); + } + } + + public class NamedLogger : ILogger + { + public string Name { get; private set; } + private readonly SimpleLogManager _logManager; + + public NamedLogger(string name, SimpleLogManager logManager) + { + Name = name; + _logManager = logManager; + } + + public void Info(string message, params object[] paramList) + { + Log(LogSeverity.Info, message, paramList); + } + + public void Error(string message, params object[] paramList) + { + Log(LogSeverity.Error, message, paramList); + } + + public void Warn(string message, params object[] paramList) + { + Log(LogSeverity.Warn, message, paramList); + } + + public void Debug(string message, params object[] paramList) + { + if (_logManager.LogSeverity == LogSeverity.Info) + { + return; + } + Log(LogSeverity.Debug, message, paramList); + } + + public void Fatal(string message, params object[] paramList) + { + Log(LogSeverity.Fatal, message, paramList); + } + + public void FatalException(string message, Exception exception, params object[] paramList) + { + ErrorException(message, exception, paramList); + } + + public void ErrorException(string message, Exception exception, params object[] paramList) + { + LogException(LogSeverity.Error, message, exception, paramList); + } + + private void LogException(LogSeverity level, string message, Exception exception, params object[] paramList) + { + message = FormatMessage(message, paramList).Replace(Environment.NewLine, ". "); + + var messageText = LogHelper.GetLogMessage(exception); + + var prefix = _logManager.ExceptionMessagePrefix; + + if (!string.IsNullOrWhiteSpace(prefix)) + { + messageText.Insert(0, prefix); + } + + LogMultiline(message, level, messageText); + } + + private static string FormatMessage(string message, params object[] paramList) + { + if (paramList != null) + { + for (var i = 0; i < paramList.Length; i++) + { + var obj = paramList[i]; + + message = message.Replace("{" + i + "}", (obj == null ? "null" : obj.ToString())); + } + } + + return message; + } + + public void LogMultiline(string message, LogSeverity severity, StringBuilder additionalContent) + { + if (severity == LogSeverity.Debug && _logManager.LogSeverity == LogSeverity.Info) + { + return; + } + + additionalContent.Insert(0, message + Environment.NewLine); + + const char tabChar = '\t'; + + var text = additionalContent.ToString() + .Replace(Environment.NewLine, Environment.NewLine + tabChar) + .TrimEnd(tabChar); + + if (text.EndsWith(Environment.NewLine)) + { + text = text.Substring(0, text.LastIndexOf(Environment.NewLine, StringComparison.OrdinalIgnoreCase)); + } + + Log(severity, text); + } + + public void Log(LogSeverity severity, string message, params object[] paramList) + { + message = severity + " " + Name + ": " + FormatMessage(message, paramList); + + _logManager.Log(message); + } + } +} |
