111 lines
3.4 KiB
C#
111 lines
3.4 KiB
C#
|
|
using System;
|
||
|
|
using System.IO;
|
||
|
|
using System.Text;
|
||
|
|
using DCIT.Core.Models;
|
||
|
|
|
||
|
|
namespace DCIT.Core.Services
|
||
|
|
{
|
||
|
|
public class LogService
|
||
|
|
{
|
||
|
|
private readonly object _syncRoot = new object();
|
||
|
|
private readonly string _logFilePath;
|
||
|
|
private bool _runtimeFailureActive;
|
||
|
|
|
||
|
|
public LogService(string startupDirectory)
|
||
|
|
{
|
||
|
|
_logFilePath = Path.Combine(startupDirectory, string.Format("session-{0:yyyyMMdd}.log", DateTime.Today));
|
||
|
|
EnsureWritable();
|
||
|
|
}
|
||
|
|
|
||
|
|
public event EventHandler<LogEntry> EntryWritten;
|
||
|
|
|
||
|
|
public event EventHandler<LogWriteFailureEventArgs> WriteFailed;
|
||
|
|
|
||
|
|
public string LogFilePath
|
||
|
|
{
|
||
|
|
get { return _logFilePath; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool HasRuntimeFailure { get; private set; }
|
||
|
|
|
||
|
|
public Exception LastRuntimeFailure { get; private set; }
|
||
|
|
|
||
|
|
public void Info(string eventCode, string message, string detail = null)
|
||
|
|
{
|
||
|
|
Write(LogLevel.Info, eventCode, message, detail);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Warning(string eventCode, string message, string detail = null)
|
||
|
|
{
|
||
|
|
Write(LogLevel.Warning, eventCode, message, detail);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Error(string eventCode, string message, string detail = null)
|
||
|
|
{
|
||
|
|
Write(LogLevel.Error, eventCode, message, detail);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Write(LogLevel level, string eventCode, string message, string detail = null)
|
||
|
|
{
|
||
|
|
var entry = new LogEntry
|
||
|
|
{
|
||
|
|
Level = level,
|
||
|
|
EventCode = eventCode,
|
||
|
|
Message = message,
|
||
|
|
Detail = detail,
|
||
|
|
};
|
||
|
|
|
||
|
|
var line = string.Format(
|
||
|
|
"{0:yyyy-MM-dd HH:mm:ss.fff}\t{1}\t{2}\t{3}",
|
||
|
|
entry.Timestamp,
|
||
|
|
level.ToString().ToUpperInvariant(),
|
||
|
|
entry.EventCode ?? string.Empty,
|
||
|
|
entry.Message ?? string.Empty);
|
||
|
|
|
||
|
|
if (!string.IsNullOrWhiteSpace(entry.Detail))
|
||
|
|
{
|
||
|
|
line += "\t" + entry.Detail.Replace("\r", " ").Replace("\n", " ");
|
||
|
|
}
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
lock (_syncRoot)
|
||
|
|
{
|
||
|
|
File.AppendAllText(_logFilePath, line + Environment.NewLine, new UTF8Encoding(false));
|
||
|
|
_runtimeFailureActive = false;
|
||
|
|
HasRuntimeFailure = false;
|
||
|
|
LastRuntimeFailure = null;
|
||
|
|
}
|
||
|
|
|
||
|
|
EntryWritten?.Invoke(this, entry);
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
var shouldRaiseEvent = false;
|
||
|
|
lock (_syncRoot)
|
||
|
|
{
|
||
|
|
HasRuntimeFailure = true;
|
||
|
|
LastRuntimeFailure = ex;
|
||
|
|
if (!_runtimeFailureActive)
|
||
|
|
{
|
||
|
|
_runtimeFailureActive = true;
|
||
|
|
shouldRaiseEvent = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (shouldRaiseEvent)
|
||
|
|
{
|
||
|
|
WriteFailed?.Invoke(this, new LogWriteFailureEventArgs(entry, _logFilePath, ex));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EnsureWritable()
|
||
|
|
{
|
||
|
|
var directory = Path.GetDirectoryName(_logFilePath);
|
||
|
|
Directory.CreateDirectory(directory);
|
||
|
|
File.AppendAllText(_logFilePath, string.Empty, new UTF8Encoding(false));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|