The c simple log class queue which can replace log4j logs implements class code sharing
- 2020-05-27 06:59:53
- OfStack
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
namespace LogisTrac
{
/// <summary>
/// The log class
/// The queue Can be in / month / weeks / day / The size of the segmentation
/// Call method:
/// Log.Instance.LogDirectory=@"C:\"; The default is to run the program directory
/// Log.Instance.FileNamePrefix="cxd"; The default is log_
/// Log.Instance.CurrentMsgType = MsgLevel.Debug; The default is Error
/// Log.Instance.logFileSplit = LogFileSplit.Daily; Log split type LogFileSplit.Sizely The size of the
/// Log.Instance.MaxFileSize = 5; Default size is 2M , only LogFileSplit.Sizely The configuration is valid
/// Log.Instance.LogWrite("aa");
/// Log.Instance.LogWrite("aa", MsgLevel.Debug);
/// </summary>
public class Log : IDisposable
{
private static Log _instance = null;
private static readonly object _synObject = new object();
/// <summary>
/// The singleton
/// </summary>
public static Log Instance
{
get
{
if (null == _instance)
{
lock (_synObject)
{
if (null == _instance)
{
_instance = new Log();
}
}
}
return _instance;
}
}
/// <summary>
/// The cache queue for the log object
/// </summary>
private static Queue<Msg> _msgs;
/// <summary>
/// The control flag for the log writing thread ture In the writing |false Didn't write
/// </summary>
private bool _state;
private string _logDirectory = AppDomain.CurrentDomain.BaseDirectory;
/// <summary>
/// Log files are stored in directories
/// </summary>
public string LogDirectory
{
get { return _logDirectory; }
set { _logDirectory = value; }
}
private LogFileSplit _logFileSplit = LogFileSplit.Sizely;
/// <summary>
/// Log split type
/// </summary>
public LogFileSplit logFileSplit
{
get { return _logFileSplit; }
set { _logFileSplit = value; }
}
private MsgLevel _currentLogLevel = MsgLevel.Error;
/// <summary>
/// Current logging level
/// </summary>
public MsgLevel CurrentMsgType
{
get { return _currentLogLevel; }
set { _currentLogLevel = value; }
}
/// <summary>
/// Currently responsible for logging the name of the log file
/// </summary>
private string _currentFileName="1.log";
private string _fileNamePrefix = "log_";
/// <summary>
/// The prefix name of the log, by default log_
/// </summary>
public string FileNamePrefix
{
get { return _fileNamePrefix; }
set { _fileNamePrefix = value; }
}
/// <summary>
/// A time marker for the log file lifecycle
/// </summary>
private DateTime _CurrentFileTimeSign = new DateTime();
private int _maxFileSize = 2;
/// <summary>
/// The default size for a single log file ( Unit: $ )
/// </summary>
public int MaxFileSize
{
get { return _maxFileSize; }
set { _maxFileSize = value; }
}
/// <summary>
/// File suffix
/// </summary>
private int _fileSymbol = 0;
/// <summary>
/// Current file size ( Units: B)
/// </summary>
private long _fileSize = 0;
/// <summary>
/// Log files are written into the stream object
/// </summary>
private StreamWriter _writer;
/// <summary>
/// Create a new instance of the log object , Creates a type based on the specified log file path and the specified log file
/// </summary>
private Log()
{
if (_msgs == null)
{
GetCurrentFilename();
_state = true;
_msgs = new Queue<Msg>();
Thread thread = new Thread(work);
thread.Start();
}
}
// The method by which the log file is written to the thread execution
private void work()
{
while (true)
{
// Determines if there is a log to write in the queue
if (_msgs.Count > 0)
{
Msg msg = null;
lock (_msgs)
{
msg = _msgs.Dequeue();
if (msg != null)
{
FileWrite(msg);
}
}
}
else
{
// Determines whether a message has been sent to terminate the log and close it
if (_state)
{
Thread.Sleep(1);
}
else
{
FileClose();
}
}
}
}
/// <summary>
/// Gets the log file name based on the log type , And at the same time create a time marker for the file to expire
/// The decision to create a new file is made by determining the expiration date of the file.
/// </summary>
/// <returns></returns>
private
void GetCurrentFilename()
{
DateTime now = DateTime.Now;
string format = "";
switch (_logFileSplit)
{
case LogFileSplit.Daily:
_CurrentFileTimeSign = new DateTime(now.Year, now.Month, now.Day);
_CurrentFileTimeSign = _CurrentFileTimeSign.AddDays(1);
format = now.ToString("yyyyMMdd'.log'");
break;
case LogFileSplit.Weekly:
_CurrentFileTimeSign = new DateTime(now.Year, now.Month, now.Day);
_CurrentFileTimeSign = _CurrentFileTimeSign.AddDays(7);
format = now.ToString("yyyyMMdd'.log'");
break;
case LogFileSplit.Monthly:
_CurrentFileTimeSign = new DateTime(now.Year, now.Month, 1);
_CurrentFileTimeSign = _CurrentFileTimeSign.AddMonths(1);
format = now.ToString("yyyyMM'.log'");
break;
case LogFileSplit.Annually:
_CurrentFileTimeSign = new DateTime(now.Year, 1, 1);
_CurrentFileTimeSign = _CurrentFileTimeSign.AddYears(1);
format = now.ToString("yyyy'.log'");
break;
default:
_fileSymbol++;
format = _fileSymbol.ToString() + ".log";
break;
}
if (File.Exists(Path.Combine(LogDirectory, _currentFileName)))
{
_fileSize = new FileInfo(Path.Combine(LogDirectory, _currentFileName)).Length;
}
else
{
_fileSize = 0;
}
_currentFileName=_fileNamePrefix + format.Trim();
}
// Method to write log text to a file
private void FileWrite(Msg msg)
{
try
{
if (_writer == null)
{
FileOpen();
}
if (_writer != null)
{
// Determine the file expiration mark , If the current file expires, close the current file to create a new log file
if ((_logFileSplit != LogFileSplit.Sizely && DateTime.Now >= _CurrentFileTimeSign)||
(_logFileSplit == LogFileSplit.Sizely && ((double)_fileSize / 1048576) > _maxFileSize))
{
GetCurrentFilename();
FileClose();
FileOpen();
}
_writer.Write(msg.datetime);
_writer.Write('\t');
_writer.Write(msg.type);
_writer.Write('\t');
_writer.WriteLine(msg.text);
_fileSize+=System.Text.Encoding.UTF8.GetBytes(msg.ToString()).Length;
_writer.Flush();
}
}
catch (Exception e)
{
Console.Out.Write(e);
}
}
// Open file ready to write
private void FileOpen()
{
_writer = new StreamWriter(LogDirectory + _currentFileName, true, Encoding.UTF8);
}
// Close the open log file
private void FileClose()
{
if (_writer != null)
{
_writer.Flush();
_writer.Close();
_writer.Dispose();
_writer = null;
}
}
/// <summary>
/// Write to new log , According to the specified log object Msg
/// </summary>
/// <param name="msg"> Log content object </param>
private void LogWrite(Msg msg)
{
if (msg.type < CurrentMsgType)
return;
if (_msgs != null)
{
lock (_msgs)
{
_msgs.Enqueue(msg);
}
}
}
/// <summary>
/// Write to new log , According to the specified log content and information type , Write a new log using the current time for the log time
/// </summary>
/// <param name="text"> Log contents </param>
/// <param name="type"> Information types </param>
public void LogWrite(string text, MsgLevel type)
{
LogWrite(new Msg(text, type));
}
/// <summary>
/// Write to new log , According to the specified log content
/// </summary>
/// <param name="text"> Log contents </param>
public void LogWrite(string text)
{
LogWrite(text, MsgLevel.Debug);
}
/// <summary>
/// Write to new log , Writes a new log based on the specified log time, log content, and information type
/// </summary>
/// <param name="dt"> Log time </param>
/// <param name="text"> Log contents </param>
/// <param name="type"> Information types </param>
public void LogWrite(DateTime dt, string text, MsgLevel type)
{
LogWrite(new Msg(dt, text, type));
}
/// <summary>
/// Write to new log , Writes the new log based on the specified exception class and information type
/// </summary>
/// <param name="e"> The exception object </param>
/// <param name="type"> Information types </param>
public void LogWrite(Exception e)
{
LogWrite(new Msg(e.Message, MsgLevel.Error));
}
/// <summary>
/// Destroy log object
/// </summary>
public void Dispose()
{
_state = false;
}
}
/// <summary>
/// 1 Two logged objects
/// </summary>
public class Msg
{
/// <summary>
/// Create a new logging instance ; The contents of the log record are empty , The message type is MsgType.Unknown, The log time is the current time
/// </summary>
public Msg()
: this("", MsgLevel.Debug)
{
}
/// <summary>
/// Create a new logging instance ; The log event is the current time
/// </summary>
/// <param name="t"> The textual content of the log </param>
/// <param name="p"> The type of message logged </param>
public Msg(string t, MsgLevel p)
: this(DateTime.Now, t, p)
{
}
/// <summary>
/// Create a new logging instance ;
/// </summary>
/// <param name="dt"> Time logged </param>
/// <param name="t"> The textual content of the log </param>
/// <param name="p"> The type of message logged </param>
public Msg(DateTime dt, string t, MsgLevel p)
{
datetime = dt;
type = p;
text = t;
}
/// <summary>
/// Time logged
/// </summary>
public DateTime datetime { get; set; }
/// <summary>
/// The contents of the log
/// </summary>
public string text { get; set; }
/// <summary>
/// The log level
/// </summary>
public MsgLevel type { get; set; }
public new string ToString()
{
return datetime.ToString(CultureInfo.InvariantCulture) + "\t" + text + "\n";
}
}
/// <summary>
/// Enumeration of log file splitting
/// </summary>
/// <remarks> Log type enumeration indicates how log files are created , If you have more logs, consider creating them daily 1 Log files
/// If the logs are small, consider creating them weekly, monthly, or annually 1 Log files </remarks>
public enum LogFileSplit
{
/// <summary>
/// This enumeration indicates daily creation 1 Two new log files
/// </summary>
Daily,
/// <summary>
/// This enumeration indicates weekly creation 1 Two new log files
/// </summary>
Weekly,
/// <summary>
/// This enumeration indicates monthly creation 1 Two new log files
/// </summary>
Monthly,
/// <summary>
/// This enumeration indicates annual creation 1 Two new log files
/// </summary>
Annually,
/// <summary>
/// The log file size exceeds the specified creation 1 Two new log files, MaxFileSize Specify the size
/// </summary>
Sizely
}
/// <summary>
/// Log level type Debug=0 Infor Warn Error
/// </summary>
public enum MsgLevel
{
/// <summary>
/// Debugging information
/// </summary>
Debug = 0,
/// <summary>
/// Logging that indicates a common information type
/// </summary>
Infor,
/// <summary>
/// Logging that indicates the type of warning message
/// </summary>
Warn,
/// <summary>
/// Logging that indicates the type of error message
/// </summary>
Error
}
}