Created
November 4, 2012 22:47
-
-
Save jirkapenzes/4014154 to your computer and use it in GitHub Desktop.
Simple logger in one file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.IO; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Mail; | |
using System.Reflection; | |
using System.Text; | |
using SimpleLogger.Logging; | |
using SimpleLogger.Logging.Formatters; | |
using SimpleLogger.Logging.Handlers; | |
using SimpleLogger.Logging.Module; | |
namespace SimpleLogger | |
{ | |
public static class Logger | |
{ | |
private static readonly LogPublisher LogPublisher; | |
private static readonly ModuleManager ModuleManager; | |
private static readonly DebugLogger DebugLogger; | |
private static readonly CustomLevelManager LevelManager; | |
private static readonly object Sync = new object(); | |
private static Level _defaultLevel = Level.Info; | |
private static bool _isTurned = true; | |
private static bool _isTurnedDebug = true; | |
public enum Level | |
{ | |
None, | |
Info, | |
Warning, | |
Error, | |
Severe, | |
Fine, | |
Debug | |
} | |
static Logger() | |
{ | |
lock (Sync) | |
{ | |
LogPublisher = new LogPublisher(); | |
ModuleManager = new ModuleManager(); | |
DebugLogger = new DebugLogger(); | |
LevelManager = new CustomLevelManager(); | |
} | |
} | |
public static void DefaultInitialization() | |
{ | |
LoggerHandlerManager | |
.AddHandler(new ConsoleLoggerHandler()) | |
.AddHandler(new FileLoggerHandler()); | |
Log(Level.Info, "Default initialization"); | |
} | |
public static Level DefaultLevel | |
{ | |
get { return _defaultLevel; } | |
set { _defaultLevel = value; } | |
} | |
public static ILoggerHandlerManager LoggerHandlerManager | |
{ | |
get { return LogPublisher; } | |
} | |
public static void Log() | |
{ | |
Log("There is no message"); | |
} | |
public static void Log(string message) | |
{ | |
Log(_defaultLevel, message); | |
} | |
public static void Log(Level level, string message) | |
{ | |
var stackFrame = FindStackFrame(); | |
var methodBase = GetCallingMethodBase(stackFrame); | |
var callingMethod = methodBase.Name; | |
var callingClass = methodBase.ReflectedType.Name; | |
var lineNumber = stackFrame.GetFileLineNumber(); | |
Log(level, message, callingClass, callingMethod, lineNumber); | |
} | |
public static void Log(Exception exception) | |
{ | |
Log(Level.Error, exception.Message); | |
ModuleManager.ExceptionLog(exception); | |
} | |
public static void Log<TClass>(Exception exception) where TClass : class | |
{ | |
var message = string.Format("Log exception -> Message: {0}\nStackTrace: {1}", exception.Message, | |
exception.StackTrace); | |
Log<TClass>(Level.Error, message); | |
} | |
public static void Log<TClass>(string message) where TClass : class | |
{ | |
Log<TClass>(_defaultLevel, message); | |
} | |
public static void Log<TClass>(Level level, string message) where TClass : class | |
{ | |
var stackFrame = FindStackFrame(); | |
var methodBase = GetCallingMethodBase(stackFrame); | |
var callingMethod = methodBase.Name; | |
var callingClass = typeof(TClass).Name; | |
var lineNumber = stackFrame.GetFileLineNumber(); | |
Log(level, message, callingClass, callingMethod, lineNumber); | |
} | |
private static void Log(Level level, string message, string callingClass, string callingMethod, int lineNumber) | |
{ | |
if (!_isTurned || (!_isTurnedDebug && level == Level.Debug)) | |
return; | |
var currentDateTime = DateTime.Now; | |
ModuleManager.BeforeLog(); | |
var logMessage = new LogMessage(level.ToString(), message, currentDateTime, callingClass, callingMethod, lineNumber); | |
LogPublisher.Publish(logMessage); | |
ModuleManager.AfterLog(logMessage); | |
} | |
private static MethodBase GetCallingMethodBase(StackFrame stackFrame) | |
{ | |
return stackFrame == null | |
? MethodBase.GetCurrentMethod() : stackFrame.GetMethod(); | |
} | |
private static StackFrame FindStackFrame() | |
{ | |
var stackTrace = new StackTrace(); | |
for (var i = 0; i < stackTrace.GetFrames().Count(); i++) | |
{ | |
var methodBase = stackTrace.GetFrame(i).GetMethod(); | |
var name = MethodBase.GetCurrentMethod().Name; | |
if (!methodBase.Name.Equals("Log") && !methodBase.Name.Equals(name)) | |
return new StackFrame(i, true); | |
} | |
return null; | |
} | |
public static void AddCustomLevel(string level) | |
{ | |
LevelManager.AddLevel(level); | |
} | |
public static void On() | |
{ | |
_isTurned = true; | |
} | |
public static void Off() | |
{ | |
_isTurned = false; | |
} | |
public static void DebugOn() | |
{ | |
_isTurnedDebug = true; | |
} | |
public static void DebugOff() | |
{ | |
_isTurnedDebug = false; | |
} | |
public static IList<LoggerModule> Modules | |
{ | |
get { return ModuleManager.Modules; } | |
} | |
public static IEnumerable<LogMessage> Messages | |
{ | |
get { return LogPublisher.Messages; } | |
} | |
public static DebugLogger Debug | |
{ | |
get { return DebugLogger; } | |
} | |
} | |
} | |
namespace SimpleLogger.Logging | |
{ | |
internal class LogPublisher : ILoggerHandlerManager | |
{ | |
private readonly IList<ILoggerHandler> _loggerHandlers; | |
private readonly IList<LogMessage> _messages; | |
public LogPublisher() | |
{ | |
_loggerHandlers = new List<ILoggerHandler>(); | |
_messages = new List<LogMessage>(); | |
} | |
public void Publish(LogMessage logMessage) | |
{ | |
_messages.Add(logMessage); | |
foreach (var loggerHandler in _loggerHandlers) | |
loggerHandler.Publish(logMessage); | |
} | |
public ILoggerHandlerManager AddHandler(ILoggerHandler loggerHandler) | |
{ | |
if (loggerHandler != null) | |
_loggerHandlers.Add(loggerHandler); | |
return this; | |
} | |
public bool RemoveHandler(ILoggerHandler loggerHandler) | |
{ | |
return _loggerHandlers.Remove(loggerHandler); | |
} | |
public IEnumerable<LogMessage> Messages | |
{ | |
get { return _messages; } | |
} | |
} | |
} | |
namespace SimpleLogger.Logging | |
{ | |
public class LogMessage | |
{ | |
public DateTime DateTime { get; set; } | |
public string Level { get; set; } | |
public string Text { get; set; } | |
public string CallingClass { get; set; } | |
public string CallingMethod { get; set; } | |
public int LineNumber { get; set; } | |
public LogMessage() { } | |
public LogMessage(string level, string text, DateTime dateTime, string callingClass, string callingMethod, int lineNumber) | |
{ | |
Level = level; | |
Text = text; | |
DateTime = dateTime; | |
CallingClass = callingClass; | |
CallingMethod = callingMethod; | |
LineNumber = lineNumber; | |
} | |
public override string ToString() | |
{ | |
return new DefaultLoggerFormatter().ApplyFormat(this); | |
} | |
} | |
} | |
namespace SimpleLogger.Logging | |
{ | |
public interface ILoggerHandlerManager | |
{ | |
ILoggerHandlerManager AddHandler(ILoggerHandler loggerHandler); | |
bool RemoveHandler(ILoggerHandler loggerHandler); | |
} | |
} | |
namespace SimpleLogger.Logging | |
{ | |
public interface ILoggerHandler | |
{ | |
void Publish(LogMessage logMessage); | |
} | |
} | |
namespace SimpleLogger.Logging | |
{ | |
public class DebugLogger | |
{ | |
private const Logger.Level DebugLevel = Logger.Level.Debug; | |
public void Log() | |
{ | |
Log("There is no message"); | |
} | |
public void Log(string message) | |
{ | |
Logger.Log(DebugLevel, message); | |
} | |
public void Log(Exception exception) | |
{ | |
Logger.Log(DebugLevel, exception.Message); | |
} | |
public void Log<TClass>(Exception exception) where TClass : class | |
{ | |
var message = string.Format("Log exception -> Message: {0}\nStackTrace: {1}", exception.Message, exception.StackTrace); | |
Logger.Log<TClass>(DebugLevel, message); | |
} | |
public void Log<TClass>(string message) where TClass : class | |
{ | |
Logger.Log<TClass>(DebugLevel, message); | |
} | |
} | |
} | |
namespace SimpleLogger.Logging | |
{ | |
class CustomLevelManager | |
{ | |
private readonly HashSet<string> _levels; | |
public CustomLevelManager() | |
{ | |
_levels = new HashSet<string>(); | |
} | |
public void AddLevel(string level) | |
{ | |
if (_levels.Contains(level)) | |
throw new ArithmeticException("Level is already defined. "); | |
_levels.Add(level); | |
} | |
public bool IsDefinedLevel(string level) | |
{ | |
return _levels.Contains(level); | |
} | |
} | |
} | |
namespace SimpleLogger.Logging.Module | |
{ | |
public class ModuleManager | |
{ | |
private readonly IList<LoggerModule> _modules; | |
public ModuleManager() | |
{ | |
_modules = new List<LoggerModule>(); | |
} | |
public void BeforeLog() | |
{ | |
foreach (var loggerModule in _modules) | |
loggerModule.BeforeLog(); | |
} | |
public void AfterLog(LogMessage logMessage) | |
{ | |
foreach (var loggerModule in _modules) | |
loggerModule.AfterLog(logMessage); | |
} | |
public void ExceptionLog(Exception exception) | |
{ | |
foreach (var loggerModule in _modules) | |
loggerModule.ExceptionLog(exception); | |
} | |
public IList<LoggerModule> Modules | |
{ | |
get { return _modules; } | |
} | |
} | |
} | |
namespace SimpleLogger.Logging.Module | |
{ | |
public abstract class LoggerModule | |
{ | |
public virtual void BeforeLog() { } | |
public virtual void AfterLog(LogMessage logMessage) { } | |
public virtual void ExceptionLog(Exception exception) { } | |
} | |
} | |
namespace SimpleLogger.Logging.Module | |
{ | |
public class EmailSenderLoggerModule : LoggerModule | |
{ | |
private readonly SmtpServerConfiguration _smtpServerConfiguration; | |
public string Sender { get; set; } | |
public IList<string> Recipients { get; private set; } | |
public bool EnableSsl { get; set; } | |
private readonly string _subject; | |
private readonly ILoggerFormatter _loggerFormatter; | |
public EmailSenderLoggerModule(SmtpServerConfiguration smtpServerConfiguration) | |
: this(smtpServerConfiguration, GenerateSubjectName()) { } | |
public EmailSenderLoggerModule(SmtpServerConfiguration smtpServerConfiguration, string subject) | |
: this(smtpServerConfiguration, subject, new DefaultLoggerFormatter()) { } | |
public EmailSenderLoggerModule(SmtpServerConfiguration smtpServerConfiguration, ILoggerFormatter loggerFormatter) | |
: this(smtpServerConfiguration, GenerateSubjectName(), loggerFormatter) { } | |
public EmailSenderLoggerModule(SmtpServerConfiguration smtpServerConfiguration, string subject, ILoggerFormatter loggerFormatter) | |
{ | |
_smtpServerConfiguration = smtpServerConfiguration; | |
_subject = subject; | |
_loggerFormatter = loggerFormatter; | |
Recipients = new List<string>(); | |
} | |
public override void ExceptionLog(Exception exception) | |
{ | |
if (string.IsNullOrEmpty(Sender) || Recipients.Count == 0) | |
throw new NullReferenceException("Not specified email sender and recipient. "); | |
var body = MakeEmailBodyFromLogHistory(); | |
var client = new SmtpClient(_smtpServerConfiguration.Host, _smtpServerConfiguration.Port) | |
{ | |
EnableSsl = EnableSsl, | |
UseDefaultCredentials = false, | |
Credentials = new NetworkCredential(_smtpServerConfiguration.UserName, _smtpServerConfiguration.Password) | |
}; | |
foreach (var recipient in Recipients) | |
{ | |
using (var mailMessage = new MailMessage(Sender, recipient, _subject, body)) | |
{ | |
client.Send(mailMessage); | |
} | |
} | |
} | |
private static string GenerateSubjectName() | |
{ | |
var currentDate = DateTime.Now; | |
return string.Format("SimpleLogger {0} {1}", currentDate.ToShortDateString(), currentDate.ToShortTimeString()); | |
} | |
private string MakeEmailBodyFromLogHistory() | |
{ | |
var stringBuilder = new StringBuilder(); | |
stringBuilder.AppendLine("Simple logger - email module"); | |
foreach (var logMessage in Logger.Messages) | |
stringBuilder.AppendLine(_loggerFormatter.ApplyFormat(logMessage)); | |
return stringBuilder.ToString(); | |
} | |
} | |
public class SmtpServerConfiguration | |
{ | |
public string UserName { get; private set; } | |
public string Password { get; private set; } | |
public string Host { get; private set; } | |
public int Port { get; private set; } | |
public SmtpServerConfiguration(string userName, string password, string host, int port) | |
{ | |
UserName = userName; | |
Password = password; | |
Host = host; | |
Port = port; | |
} | |
} | |
} | |
namespace SimpleLogger.Logging.Handlers | |
{ | |
public class FileLoggerHandler : ILoggerHandler | |
{ | |
private readonly string _fileName; | |
private readonly string _directory; | |
private readonly ILoggerFormatter _loggerFormatter; | |
public FileLoggerHandler() : this(CreateFileName()) { } | |
public FileLoggerHandler(string fileName) : this(fileName, string.Empty) { } | |
public FileLoggerHandler(string fileName, string directory) : this(new DefaultLoggerFormatter(), fileName, directory) { } | |
public FileLoggerHandler(ILoggerFormatter loggerFormatter) : this(loggerFormatter, CreateFileName()) { } | |
public FileLoggerHandler(ILoggerFormatter loggerFormatter, string fileName) : this(loggerFormatter, fileName, string.Empty) { } | |
public FileLoggerHandler(ILoggerFormatter loggerFormatter, string fileName, string directory) | |
{ | |
_loggerFormatter = loggerFormatter; | |
_fileName = fileName; | |
_directory = directory; | |
} | |
public void Publish(LogMessage logMessage) | |
{ | |
if (!string.IsNullOrEmpty(_directory)) | |
{ | |
var directoryInfo = new DirectoryInfo(_directory); | |
if (!directoryInfo.Exists) | |
directoryInfo.Create(); | |
} | |
using (var writer = new StreamWriter(File.Open(Path.Combine(_directory, _fileName), FileMode.Append))) | |
writer.WriteLine(_loggerFormatter.ApplyFormat(logMessage)); | |
} | |
private static string CreateFileName() | |
{ | |
var currentDate = DateTime.Now; | |
var guid = Guid.NewGuid(); | |
return string.Format("Log_{0:0000}{1:00}{2:00}-{3:00}{4:00}_{5}.log", | |
currentDate.Year, currentDate.Month, currentDate.Day, currentDate.Hour, currentDate.Minute, guid); | |
} | |
} | |
} | |
namespace SimpleLogger.Logging.Handlers | |
{ | |
public class DebugConsoleLoggerHandler : ILoggerHandler | |
{ | |
private readonly ILoggerFormatter _loggerFormatter; | |
public DebugConsoleLoggerHandler() : this(new DefaultLoggerFormatter()) { } | |
public DebugConsoleLoggerHandler(ILoggerFormatter loggerFormatter) | |
{ | |
_loggerFormatter = loggerFormatter; | |
} | |
public void Publish(LogMessage logMessage) | |
{ | |
System.Diagnostics.Debug.WriteLine(_loggerFormatter.ApplyFormat(logMessage)); | |
} | |
} | |
} | |
namespace SimpleLogger.Logging.Handlers | |
{ | |
public class ConsoleLoggerHandler : ILoggerHandler | |
{ | |
private readonly ILoggerFormatter _loggerFormatter; | |
public ConsoleLoggerHandler() : this(new DefaultLoggerFormatter()) { } | |
public ConsoleLoggerHandler(ILoggerFormatter loggerFormatter) | |
{ | |
_loggerFormatter = loggerFormatter; | |
} | |
public void Publish(LogMessage logMessage) | |
{ | |
Console.WriteLine(_loggerFormatter.ApplyFormat(logMessage)); | |
} | |
} | |
} | |
namespace SimpleLogger.Logging.Formatters | |
{ | |
public interface ILoggerFormatter | |
{ | |
string ApplyFormat(LogMessage logMessage); | |
} | |
} | |
namespace SimpleLogger.Logging.Formatters | |
{ | |
internal class DefaultLoggerFormatter : ILoggerFormatter | |
{ | |
public string ApplyFormat(LogMessage logMessage) | |
{ | |
return string.Format("{0:dd.MM.yyyy HH:mm}: {1} [line: {2} {3} -> {4}()]: {5}", | |
logMessage.DateTime, logMessage.Level, logMessage.LineNumber, logMessage.CallingClass, | |
logMessage.CallingMethod, logMessage.Text); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment