Application event logging is a must. But most available logging modules around are quite bloated or heavy structured. Why not create your own simple file logger and gain full control over this part of your application? Have a look.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Common
{
public class Logger
{
#region fields
private static string LogFilePath;
private static string BakFilePath;
private static LogLevel LogLevel;
private const long MAX_FILE_SIZE = 11000000;
private const long SHRINKED_FILE_SIZE = 10000000;
#endregion
#region constructors
static Logger() {
Reset();
}
#endregion
#region Reset
public static void Reset() {
LogFilePath = AppSettings.GetLogFilePath();
BakFilePath = LogFilePath + @"\EventLog.txt";
LogLevel = AppSettings.GetLogLevel();
}
#endregion
#region LogInfo
public static void LogInfo(string msg) {
if (LogLevel > LogLevel.Information) {
return;
}
writeEntry("INF", msg);
}
#endregion
#region LogWarning
public static void LogWarning(string msg) {
if (LogLevel > LogLevel.Warning) {
return;
}
writeEntry("WRN", msg);
}
#endregion
#region LogError
public static void LogError(string msg) {
writeEntry("ERR", msg);
}
public static void LogError(Exception ex) {
LogError(null, ex);
}
public static void LogError(string msg, Exception ex) {
if (LogLevel > LogLevel.Error) {
return;
}
var sb = new StringBuilder();
if (msg != null) {
sb.AppendLine(msg.Trim());
}
if (ex != null) {
sb.Append(string.Format("{0}: {1}", ex.GetType(), ex.Message));
if (ex.InnerException != null) {
sb.Append(string.Format(" ---> {0}: {1}", ex.InnerException.GetType(), ex.InnerException.Message));
if (ex.InnerException.InnerException != null) {
sb.Append(string.Format(" ---> {0}: {1}", ex.InnerException.InnerException.GetType(), ex.InnerException.InnerException.Message));
}
}
sb.AppendLine();
sb.AppendLine(ex.StackTrace);
}
writeEntry("ERR", sb.ToString());
}
#endregion
#region write entry to file
private static void writeEntry(string key, string msg) {
try {
// Consider shrink file.
if (LogFilePath != null && BakFilePath != null) {
try {
var fiLogFile = new FileInfo(LogFilePath);
if (fiLogFile.Exists) {
if (fiLogFile.Length > MAX_FILE_SIZE) {
considerShrinkLogFile();
}
}
}
catch {
}
}
// Write entry.
if (LogFilePath != null) {
using (var fs = new FileStream(LogFilePath, FileMode.Append, FileAccess.Write, FileShare.None)) {
using (var wri = new StreamWriter(fs, Encoding.UTF8)) {
wri.WriteLine(string.Format("{0} {1} {2}",
DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"),
key,
msg
));
}
}
}
}
catch {
// Logging should never crash an application.
}
}
private static void considerShrinkLogFile() {
File.Copy(LogFilePath, BakFilePath, true);
var buffer = new byte[4096];
using (var fsRead = new FileStream(BakFilePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None)) {
fsRead.Position = Math.Max(0, fsRead.Length - SHRINKED_FILE_SIZE);
using (var fsWrite = new FileStream(LogFilePath, FileMode.Create, FileAccess.Write, FileShare.None)) {
int cntRead = fsRead.Read(buffer, 0, buffer.Length);
while (cntRead > 0) {
fsWrite.Write(buffer, 0, cntRead);
cntRead = fsRead.Read(buffer, 0, buffer.Length);
}
}
}
}
#endregion
}
#region helper types
public enum LogLevel
{
Information = 0, // Should have 0.
Warning = 1,
Error = 2
}
#endregion
}