using System;
using System.Diagnostics;
using System.Text;
using System.IO;
using System.Threading;
namespace Common
{
public class LogEngine
{
private LogSetting m_Setting;
public LogEngine()
{
m_Setting = new LogSetting();
}
public LogEngine(string name)
: this()
{
m_Setting.Name = name;
}
private void WriteWords(object words)
{
// Lock file when the file has be writting at anthoer thread.
lock (_WriterLock)
{
StreamWriter stream = null;
try
{
string dir = GetCurrentDirectoryPath();
string filename = GetFileNameWithPartMark();
string fullpath = Path.Combine(dir, filename);
FileInfo fileInf;
if (Directory.Exists(dir) == false)
{
Directory.CreateDirectory(dir);
}
for (int part = 1; true; part++)
{
fileInf = new FileInfo(string.Format(fullpath, part));
if (fileInf.Exists)
{
if (fileInf.Length < Setting.MaxSizeByte)
{
stream = fileInf.AppendText();
break;
}
}
else
{
stream = fileInf.CreateText();
break;
}
}
stream.Write(words);
}
catch (Exception ex)
{
using (var sw = File.CreateText(
AppDomain.CurrentDomain.BaseDirectory +
"LogEngine." +
DateTime.Now.ToString("yyyyMMddHHmmssfff.") +
new Random().Next(9999) +
".log"))
{
sw.WriteLine("Exception when write words: {0}", words);
sw.WriteLine("Exception Message: {0}", ex.Message);
sw.WriteLine("Exception StackTrace: {0}", ex.StackTrace);
}
}
finally
{
if (stream != null)
{
stream.Dispose();
}
}
}
}
public void Write(string words)
{
if (this.m_Setting.BackgroundThread)
{
Thread t = new Thread(new ParameterizedThreadStart(WriteWords));
t.IsBackground = true;
t.Start(words);
}
else
{
WriteWords(words);
}
}
public string Write(string format, params object[] objs)
{
string words = string.Format(format, objs);
Write(words);
return words;
}
public string WriteLine(string format, params object[] objs)
{
StringBuilder sbWords = new StringBuilder();
sbWords.AppendFormat(format, objs).AppendLine();
string words = sbWords.ToString();
Write(words);
return words;
}
public string WriteLineWithDataTime(string format, params object[] objs)
{
StringBuilder sbWords = new StringBuilder();
sbWords.Append(DateTime.Now.ToString(Setting.DateTimeFormat));
sbWords.AppendFormat(format, objs);
sbWords.AppendLine();
string words = sbWords.ToString();
Write(words);
return words;
}
public LogSetting Setting { get { return m_Setting; } }
public string GetCurrentDirectoryPath()
{
string dir = Setting.Home;
if (Setting.FoldersTree != null)
{
foreach (var flag in Setting.FoldersTree)
{
switch (flag)
{
case FolderFlag.Name: dir = Path.Combine(dir, Setting.Name); break;
case FolderFlag.Date: dir = Path.Combine(dir, DateTime.Now.ToString(LogSetting.DATE_FORMAT)); break;
}
}
}
return dir;
}
private string GetFileNameWithPartMark()
{
return string.Format(_LOG_FILENAME_FMT, _LOG_FILENAME_SEPARATOR, Setting.Name, DateTime.Now.ToString(Setting.PartOfFileNameDHFormat), _PART_MARK).Trim(_LOG_FILENAME_SEPARATOR);
}
public void ExploreFolder()
{
Process.Start("explorer.exe", GetValidFolderPath(GetCurrentDirectoryPath()));
}
private string GetValidFolderPath(string path)
{
if (string.IsNullOrEmpty(path))
path = AppDomain.CurrentDomain.BaseDirectory;
if (Directory.Exists(path) == false)
path = GetValidFolderPath(Path.GetDirectoryName(path));
return path;
}
// Lock the file variable, must define static
private static readonly object _WriterLock = new object();
// {0} Name; {1} DateTime; {2} Part
const string _LOG_FILENAME_FMT = "{1}{0}{2}{0}P{3}.log";
const string _PART_MARK = "{0}";
const char _LOG_FILENAME_SEPARATOR = '_';
public static void CleanUpOutdated(string dirPath, uint days, string pattern = "*.log")
{
try
{
if (Directory.Exists(dirPath))
{
DirectoryInfo dInfo;
foreach (var dPath in Directory.GetDirectories(dirPath))
{
try
{
dInfo = new DirectoryInfo(dPath);
foreach (var fInfo in dInfo.GetFiles(pattern, SearchOption.AllDirectories))
{
try
{
if (DateTime.Now.Subtract(fInfo.LastWriteTime).Days > days)
fInfo.Delete();
}
catch { }
}
if (dInfo.GetFiles("*", SearchOption.AllDirectories).Length < 1)
{
dInfo.Delete();
}
}
catch { }
}
}
}
catch { }
}
public class LogSetting
{
string _name;
string _home;
FolderFlag[] _foldersTree;
internal long MaxSizeByte;
internal string PartOfFileNameDHFormat;
uint _maxSize;
bool _byHour;
public LogSetting()
{
_name = string.Empty;
_home = "Log";
MaxSize = 5;
//BackgroundThread = true;
ByHour = false;
DateTimeFormat = "HH:mm:ss.fff: ";
SetFoldersTree(FolderFlag.Date);
}
public string Name
{
get { return _name; }
set
{
if (value.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
throw new ArgumentException("Contains invalid characters", "value");
_name = value;
}
}
public string Home
{
get
{
return _home;
}
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentNullException("value");
if (value.IndexOfAny(Path.GetInvalidPathChars()) >= 0)
throw new ArgumentException("Contains invalid characters", "value");
_home = value;
}
}
public uint MaxSize
{
get
{
return _maxSize;
}
set
{
if (value > 0 && value <= 100)
{
_maxSize = value;
MaxSizeByte = _maxSize * 1048576; // 1MB = 1048576 byte
}
}
}
public bool ByHour
{
get { return _byHour; }
set
{
PartOfFileNameDHFormat = value ? "yyyyMMdd_HH" : DATE_FORMAT;
_byHour = value;
}
}
public string DateTimeFormat
{
get;
set;
}
public FolderFlag[] FoldersTree
{
get { return _foldersTree.Clone() as FolderFlag[]; }
}
public void SetFoldersTree(params FolderFlag[] folders)
{
_foldersTree = folders;
}
public bool BackgroundThread { get; set; }
internal const string DATE_FORMAT = "yyyyMMdd";
}
public enum FolderFlag
{
Name, Date
}
}
}