137 lines
4.7 KiB
C#
137 lines
4.7 KiB
C#
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);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|