c#에서 간단하게 사용할 수 있는 로깅 라이브러리는 여러가지가 있다.
그중에서 Clearcove.logging을 간단하게 소개한다.
Thread 3개로 각각 info log, error log를 비동기로 기록하는 예제
- 로깅 파일 설정
static void Main(string[] args)
{
// 로깅 파일 설정
var targetLogFile = new FileInfo("./AppLog.log");
Logger.LogToConsole = true; // Print log entries to console (optional).
Logger.Start(targetLogFile); // Loggers will complains if you skip initialization
try
{
Run(args);
}
finally
{
Logger.ShutDown(); // Removing this line may result in lost log entries.
}
Console.WriteLine("Done.");
} // end static void Main
- Run()
private static void Run(string[] _)
{
var log = new Logger(typeof(Program)); // Create logger with class name.
var tasks = new List<Task>();
// 정보성 로그 쓰레드
for (int i = 1; i <= 3; i++)
{
var threadId = i;
log.Info("[INFO] Starting thread: " + threadId);
tasks.Add(Task.Factory.StartNew(() => LogMessages(threadId)));
}
// 에러 로그 쓰레드
for (int i = 1; i <= 3; i++)
{
var threadId = i;
log.Info("[ERR] Starting thread: " + threadId);
tasks.Add(Task.Factory.StartNew(() => ErrLogMessages(threadId)));
}
Task.WaitAll(tasks.ToArray());
} // end private static void Run(string[] _)
* LogMessages/ErrLogMessages
private static void LogMessages(int threadId)
{
var random = new Random();
var log = new Logger("Thread_" + threadId); // Create logger from string.
for (int i = 1; i < 100; i++)
{
log.Info("This is log msg ... " + i);
Thread.Sleep(random.Next(10, 100)); // sleep to simulate a more realistic execution.
}
} // end private static void LogMessages(int threadId)
private static void ErrLogMessages(int threadId)
{
var random = new Random();
var log = new Logger("Thread_" + threadId); // Create logger from string.
for (int i = 1; i < 100; i++)
{
log.Error("This is error log msg ... " + i);
Thread.Sleep(random.Next(10, 100)); // sleep to simulate a more realistic execution.
}
} // end private static void ErrLogMessages(int threadId)
- Clearcove.Logging
using System;
using System.IO;
using System.Text;
using System.Threading;
namespace Clearcove.Logging
{
public sealed class Logger
{
#region Log File Writing
public static bool Listening { get; private set; }
public static FileInfo TargetLogFile { get; private set; }
public static DirectoryInfo TargetDirectory { get { return TargetLogFile?.Directory; } }
public static bool LogToConsole = false;
public static int BatchInterval = 1000;
public static bool IgnoreDebug = false;
private static readonly Timer Timer = new Timer(Tick);
private static readonly StringBuilder LogQueue = new StringBuilder();
public static void Start(FileInfo targetLogFile)
{
if (Listening)
return;
Listening = true;
TargetLogFile = targetLogFile;
VerifyTargetDirectory();
Timer.Change(BatchInterval, Timeout.Infinite); // A one-off tick event that is reset every time.
}
private static void VerifyTargetDirectory()
{
if (TargetDirectory == null)
throw new DirectoryNotFoundException("Target logging directory not found.");
TargetDirectory.Refresh();
if (!TargetDirectory.Exists)
TargetDirectory.Create();
}
private static void Tick(object state)
{
try
{
var logMessage = "";
lock (LogQueue)
{
logMessage = LogQueue.ToString();
LogQueue.Length = 0;
}
if (string.IsNullOrEmpty(logMessage))
return;
if (LogToConsole)
Console.Write(logMessage);
VerifyTargetDirectory(); // File may be deleted after initialization.
File.AppendAllText(TargetLogFile.FullName, logMessage);
}
finally
{
if(Listening)
Timer.Change(BatchInterval, Timeout.Infinite); // Reset timer for next tick.
}
}
public static void ShutDown()
{
if (!Listening)
return;
Listening = false;
Timer.Dispose();
Tick(null); // Flush.
}
#endregion
public readonly string Name;
public EventHandler<LogMessageInfo> LogMessageAdded;
private bool _startedErrorShown = false;
public const string DEBUG = "DEBUG";
public const string INFO = "INFO";
public const string WARN = "WARN";
public const string ERROR = "ERROR";
public Logger(Type t) : this(t.Name)
{
}
public Logger(string name)
{
Name = name;
}
public void Debug(string message)
{
if (IgnoreDebug)
return;
Log(DEBUG, message);
}
public void Info(string message)
{
Log(INFO, message);
}
public void Warn(string message, Exception ex = null)
{
Log(WARN, message, ex);
}
public void Error(string message, Exception ex = null)
{
Log(ERROR, message, ex);
}
public void Log(string level, string message, Exception ex = null)
{
if (!CheckListening())
return;
if (ex != null)
message += string.Format("\r\n{0}\r\n{1}", ex.Message, ex.StackTrace);
var info = new LogMessageInfo(level, Name, message);
var msg = info.ToString();
lock (LogQueue)
{
LogQueue.AppendLine(msg);
}
var evnt = LogMessageAdded;
if(evnt != null)
evnt.Invoke(this, info); // Block caller.
}
private bool CheckListening()
{
if (Listening)
return true;
if (!_startedErrorShown)
{
Console.WriteLine("Logging has not been started.");
_startedErrorShown = true; // No need to excessively repeat this message.
}
return false;
}
}
public sealed class LogMessageInfo : EventArgs
{
public readonly DateTime Timestamp;
public readonly string ThreadId;
public readonly string Level;
public readonly string Logger;
public readonly string Message;
public bool IsError { get { return Logging.Logger.ERROR.Equals(Level, StringComparison.Ordinal); } }
public bool IsWarning { get { return Logging.Logger.WARN.Equals(Level, StringComparison.Ordinal); } }
public bool IsInformation { get { return Logging.Logger.INFO.Equals(Level, StringComparison.Ordinal); } }
public bool IsDebug { get { return Logging.Logger.DEBUG.Equals(Level, StringComparison.Ordinal); } }
public LogMessageInfo(string level, string logger, string message)
{
Timestamp = DateTime.Now;
//Timestamp = DateTime.UtcNow;
var thread = Thread.CurrentThread;
ThreadId = string.IsNullOrEmpty(thread.Name) ? thread.ManagedThreadId.ToString() : thread.Name;
Level = level;
Logger = logger;
Message = message;
}
public override string ToString()
{
return string.Format("{0:yyyy/MM/dd HH:mm:ss.fff} {1} {2} {3} {4}",
Timestamp, ThreadId, Logger, Level, Message);
}
}
}
728x90
'소프트웨어 개발(SW Dev) > C#' 카테고리의 다른 글
Visual Studio 코드 편집기 Tab 들여쓰기 설정 (0) | 2021.10.07 |
---|---|
C# Interactive 단축키 (0) | 2021.10.05 |
c# 언어 표준 (0) | 2021.04.07 |
Code Review checklist and guidelines for C# Developers (0) | 2021.03.22 |
Visual Studio Code로 C# 프로그램 개발 (0) | 2021.03.19 |
댓글