当然了,可以使用:log4net 库;
但目前该功能需求不需要用到这么强大的日志管理;直接写文件记录;所以就写了一个简单的;
这是半成品,还可以用,还有地方可以优化;
但再优化前,可读性比较好,我就上传了:
using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.InteropServices;
namespace Testing
{
public delegate bool ConsoleCtrlDelegate(int dwCtrlType);
/// <summary>
/// @author Jave.Lin
/// @date 2013-12-11
/// </summary>
public partial class Logger
{
[DllImport("kernel32.dll")]
private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate handlerRoutine, bool add);
private const int CtrlCEvent = 0;//CTRL_C_EVENT = 0;//一个Ctrl+C的信号被接收,该信号或来自键盘,或来自GenerateConsoleCtrlEvent 函数
private const int CtrlBreakEvent = 1;//CTRL_BREAK_EVENT = 1;//一个Ctrl+Break信号被接收,该信号或来自键盘,或来自GenerateConsoleCtrlEvent 函数
private const int CtrlCloseEvent = 2;//CTRL_CLOSE_EVENT = 2;//当用户系统关闭Console时,系统会发送此信号到此
private const int CtrlLogoffEvent = 5;//CTRL_LOGOFF_EVENT = 5;//当用户退出系统时系统会发送这个信号给所有的Console程序。该信号不能显示是哪个用户退出。
private const int CtrlShutdownEvent = 6;//CTRL_SHUTDOWN_EVENT = 6;//当系统将要关闭时会发送此信号到所有Console程序
public static readonly object Locker = new object();
private static StreamWriter WRITER;
// TODO : caches 可改用 StringBuilder 来优化
private static string ContinueWriteCaches;
private static readonly Stopwatch Continue_WriteSw;
private static int ContinueTime = 300; // 300毫秒以后,连续写操作,都统一到一块操作
private static int ContinueCountMax = 100; // 当连续写操作次数上限到指定的数值后,都写一次操作,之后的重新再计算
private static int ContinueCount = 0;
private static string LoggerFileName;
public static int AllWriteCount = 0;
static Logger()
{
var nowDateTime = DateTime.Now;
var dateTimeStr =
nowDateTime.Year + "_" +
nowDateTime.Month + "_" +
nowDateTime.Day + "_" +
nowDateTime.Hour + "_" +
nowDateTime.Minute + "_" +
nowDateTime.Second + "_" +
nowDateTime.Millisecond;
LoggerFileName = "Log/Logs_" + dateTimeStr + ".txt";
Continue_WriteSw = new Stopwatch();
if (SetConsoleCtrlHandler(new ConsoleCtrlDelegate(HandlerRoutine), true))
{
Info("Set SetConsoleCtrlHandler success.");
}
else
{
Error("Set SetConsoleCtrlHandler Error.");
}
}
private static bool HandlerRoutine(int ctrlType)
{
switch (ctrlType)
{
// src:
//case CtrlCEvent: System.Console.WriteLine("Ctrl+C keydown"); break;
//case CtrlBreakEvent: System.Console.WriteLine("Ctrl+Break keydown"); break;
//case CtrlCloseEvent: System.Console.WriteLine("window closed"); break;
//case CtrlLogoffEvent: System.Console.WriteLine("log off or shut down"); break;
//case CtrlShutdownEvent: System.Console.WriteLine("system shut down"); break;
//default: System.Console.WriteLine(ctrlType.ToString()); break;
// new:
//case CtrlCEvent: System.Console.WriteLine("Ctrl+C keydown"); break;
//case CtrlBreakEvent: System.Console.WriteLine("Ctrl+Break keydown"); break;
case CtrlCloseEvent:
_WriteBuffer();
break;
//case CtrlLogoffEvent: System.Console.WriteLine("log off or shut down"); break;
//case CtrlShutdownEvent: System.Console.WriteLine("system shut down"); break;
default: System.Console.WriteLine(ctrlType.ToString()); break;
}
return false;
}
private static void Write(string msg)
{
if (string.IsNullOrEmpty(msg))
{
return;
}
lock (Locker)
{
if (ContinueWriteCaches == null) ContinueWriteCaches = msg + "\r\n";
else ContinueWriteCaches += msg + "\r\n";
if (Continue_WriteSw.IsRunning)
{
if (Continue_WriteSw.ElapsedMilliseconds > ContinueTime)
{
_WriteBuffer();
return;
}
}
++ContinueCount;
if (ContinueCount > ContinueCountMax)
{
_WriteBuffer();
return;
}
if (!Continue_WriteSw.IsRunning)
{
Continue_WriteSw.Start();
}
}
}
private static void _WriteBuffer()
{
if (ContinueWriteCaches != null)
{
if (!File.Exists(LoggerFileName))
{
var dir = Directory.GetParent(LoggerFileName).FullName;
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
}
WRITER = new StreamWriter(LoggerFileName, true, Encoding.UTF8);
WRITER.WriteLine(ContinueWriteCaches);
WRITER.Flush();
WRITER.Close();
}
Continue_WriteSw.Stop();
Continue_WriteSw.Reset();
ContinueWriteCaches = null;
ContinueCount = 0;
Interlocked.Increment(ref AllWriteCount);
}
}
public partial class Logger
{
public static ConsoleColor S_InfoColor = ConsoleColor.White;
public static ConsoleColor S_DebugColor = ConsoleColor.Green;
public static ConsoleColor S_WarningColor = ConsoleColor.Yellow;
public static ConsoleColor S_ErrorColor = ConsoleColor.Red;
private static object _s_pLocker = new object();
// alwasy log
public static void Info(string msg, params object[] ps)
{
if (ps != null && ps.Length > 0 )
{
msg = string.Format(msg, ps);
}
_Write(S_InfoColor, "[Info]" + msg);
}
// remove log when debug complete.
public static void Debug(string msg, params object[] ps)
{
if (ps != null && ps.Length > 0)
{
msg = string.Format(msg, ps);
}
_Write(S_DebugColor, "[Debug]" + msg);
}
// remove log when bug fixed.
public static void Warning(string msg, params object[] ps)
{
if (ps != null && ps.Length > 0)
{
msg = string.Format(msg, ps);
}
_Write(S_WarningColor, "[Warning]" + msg);
}
// remove log when error fixed.
public static void Error(string msg, params object[] ps)
{
if (ps != null && ps.Length > 0)
{
msg = string.Format(msg, ps);
}
_Write(S_ErrorColor, "[Error]" + msg);
}
private static void _Write(ConsoleColor color, string msg)
{
lock (_s_pLocker)
{
msg = DateTime.Now.ToString() + " " + msg;
var srcColor = Console.ForegroundColor;
Console.ForegroundColor = color;
Console.WriteLine(msg);
Console.ForegroundColor = srcColor;
Write(msg);
}
}
}
}
测试调用:
for (int i = 0; i < 300; i++)
{
Logger.Debug("testsadfasdfasdf" + i);
}
Logger.Debug("Write Count : " + Logger.AllWriteCount); // 总调用IO写的次数为:2次。。。但写的内容次数就超过300