mirror of
https://github.com/MaSzyna-EU07/StarterNG.git
synced 2026-11-01 20:34:57 +01:00
A failed write leaves the old file in place. Settings that could not be read are not saved over. UI exceptions reach the log. Started from a shortcut set up elsewhere, the starter moves to its own folder when only that one holds a game.
157 lines
3.7 KiB
C#
157 lines
3.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using StarterNG.Application.Abstractions;
|
|
|
|
namespace StarterNG.Infrastructure.Adapters;
|
|
|
|
public sealed class FileDiagnosticsLog : IDiagnosticsLog
|
|
{
|
|
private readonly IFileSystem _files;
|
|
private readonly IClock _clock;
|
|
private readonly string _logPath;
|
|
|
|
private readonly object _gate = new();
|
|
private readonly List<string> _lines = new();
|
|
|
|
private StreamWriter? _writer;
|
|
private bool _writerFailed;
|
|
private bool _previousKept;
|
|
|
|
public FileDiagnosticsLog(IFileSystem files, IClock clock, IGamePaths paths)
|
|
{
|
|
_files = files;
|
|
_clock = clock;
|
|
_logPath = paths.DiagnosticsLog;
|
|
}
|
|
|
|
public string LogPath => _logPath;
|
|
|
|
public string Text
|
|
{
|
|
get { lock (_gate) return string.Join(Environment.NewLine, _lines); }
|
|
}
|
|
|
|
public void Log(string message)
|
|
{
|
|
string line = $"{_clock.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)} {message}";
|
|
lock (_gate)
|
|
{
|
|
_lines.Add(line);
|
|
Append(line);
|
|
}
|
|
}
|
|
|
|
public void Log(string context, Exception exception) =>
|
|
Log($"{context}: {exception.GetType().Name}: {exception.Message}");
|
|
|
|
public void Log(IEnumerable<string> messages)
|
|
{
|
|
foreach (string message in messages)
|
|
Log(message);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
lock (_gate)
|
|
{
|
|
_lines.Clear();
|
|
CloseWriter();
|
|
try
|
|
{
|
|
if (_files.FileExists(_logPath))
|
|
_files.DeleteFile(_logPath);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Flush()
|
|
{
|
|
lock (_gate)
|
|
{
|
|
if (_lines.Count == 0)
|
|
return;
|
|
|
|
try
|
|
{
|
|
_writer?.Flush();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_writerFailed = true;
|
|
_lines.Add($"log flush failed: {ex.GetType().Name}: {ex.Message}");
|
|
}
|
|
|
|
if (!_writerFailed && _writer is not null)
|
|
return;
|
|
|
|
try
|
|
{
|
|
_files.CreateDirectory(Path.GetDirectoryName(_logPath)!);
|
|
if (KeepPreviousSession())
|
|
_files.WriteAllLines(_logPath, _lines);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
// What the last session left, a crash's traces above all, is what this log is
|
|
// read for: one copy of it goes aside before the first entry of this one. False
|
|
// when it could not, and the log is then added to instead of started over.
|
|
private bool KeepPreviousSession()
|
|
{
|
|
if (_previousKept)
|
|
return true;
|
|
|
|
try
|
|
{
|
|
if (_files.FileExists(_logPath))
|
|
_files.CopyFile(_logPath, _logPath + ".1", overwrite: true);
|
|
return _previousKept = true;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private void Append(string line)
|
|
{
|
|
if (_writerFailed)
|
|
return;
|
|
|
|
try
|
|
{
|
|
if (_writer is null)
|
|
{
|
|
_files.CreateDirectory(Path.GetDirectoryName(_logPath)!);
|
|
_writer = new StreamWriter(_logPath, append: !KeepPreviousSession()) { AutoFlush = true };
|
|
}
|
|
_writer.WriteLine(line);
|
|
}
|
|
catch
|
|
{
|
|
_writerFailed = true;
|
|
CloseWriter();
|
|
}
|
|
}
|
|
|
|
private void CloseWriter()
|
|
{
|
|
try
|
|
{
|
|
_writer?.Dispose();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
_writer = null;
|
|
}
|
|
}
|