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 EntryWritten; public event EventHandler 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)); } } }