Files
StandardSence/StandardScene.Signal/Logic/MagTrafficFileLogger.cs
T

137 lines
4.7 KiB
C#
Raw Normal View History

2026-08-24 14:55:35 +08:00
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Text;
namespace StandardScene.Signal.Logic
{
/// <summary>
/// 磁条交管放行留档,按车名分目录:log/mag-traffic/car{name}/release_yyyyMMdd.log
/// 进程启停等写到 log/mag-traffic/_sys/sys_yyyyMMdd.log
/// </summary>
public static class MagTrafficFileLogger
{
private static readonly ConcurrentDictionary<string, object> CarLocks = new ConcurrentDictionary<string, object>(StringComparer.OrdinalIgnoreCase);
private static readonly object SysLock = new object();
private static readonly char[] InvalidNameChars = Path.GetInvalidFileNameChars();
private static string _baseDirectory = "log";
private static bool _enabled = true;
public static void Configure(string baseDirectory, bool enabled)
{
_baseDirectory = string.IsNullOrWhiteSpace(baseDirectory) ? "log" : baseDirectory.Trim();
_enabled = enabled;
}
public static string GetLogDirectory()
{
return Path.Combine(ResolveBaseDirectory(), "mag-traffic");
}
/// <summary>目录名 car{name};名称为空时回退 car{id}。</summary>
public static string GetCarFolderKey(string carName, int carId)
{
var safe = SanitizeName(carName);
if (string.IsNullOrWhiteSpace(safe))
{
safe = carId > 0 ? carId.ToString() : "unknown";
}
return "car" + safe;
}
public static string GetCarLogDirectory(string carName, int carId = 0)
{
return Path.Combine(GetLogDirectory(), GetCarFolderKey(carName, carId));
}
public static string GetCurrentCarLogFilePath(string carName, int carId = 0)
{
return Path.Combine(GetCarLogDirectory(carName, carId), $"release_{DateTime.Now:yyyyMMdd}.log");
}
public static string GetCurrentSysLogFilePath()
{
return Path.Combine(GetLogDirectory(), "_sys", $"sys_{DateTime.Now:yyyyMMdd}.log");
}
/// <summary>按车名写入放行记录。</summary>
public static void Write(string carName, int carId, string message)
{
if (!_enabled || string.IsNullOrWhiteSpace(message))
{
return;
}
var folderKey = GetCarFolderKey(carName, carId);
var carLock = CarLocks.GetOrAdd(folderKey, _ => new object());
lock (carLock)
{
try
{
var directory = Path.Combine(GetLogDirectory(), folderKey);
Directory.CreateDirectory(directory);
var path = Path.Combine(directory, $"release_{DateTime.Now:yyyyMMdd}.log");
File.AppendAllText(
path,
$"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}{Environment.NewLine}",
new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
catch
{
}
}
}
/// <summary>进程启停、重载配置等非单车事件。</summary>
public static void WriteSystem(string message)
{
if (!_enabled || string.IsNullOrWhiteSpace(message))
{
return;
}
lock (SysLock)
{
try
{
var path = GetCurrentSysLogFilePath();
Directory.CreateDirectory(Path.GetDirectoryName(path) ?? GetLogDirectory());
File.AppendAllText(
path,
$"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}{Environment.NewLine}",
new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
catch
{
}
}
}
private static string SanitizeName(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return "";
}
var chars = name.Trim().Select(ch => InvalidNameChars.Contains(ch) || ch <= 31 ? '_' : ch).ToArray();
var safe = new string(chars).Trim('.', ' ');
while (safe.Contains("__"))
{
safe = safe.Replace("__", "_");
}
return safe.Length > 80 ? safe.Substring(0, 80) : safe;
}
private static string ResolveBaseDirectory()
{
return Path.IsPathRooted(_baseDirectory)
? _baseDirectory
: Path.Combine(AppContext.BaseDirectory, _baseDirectory);
}
}
}