first version
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2025 SimcuTeam. All rights reserved.
|
||||
* 移植自 C# 项目 SimApi(E:\simcu\simapi-net),遵循 MIT 许可证。
|
||||
*/
|
||||
|
||||
package simapi.logger
|
||||
|
||||
import std.collection.concurrent.*
|
||||
import std.env.*
|
||||
import std.time.*
|
||||
import soulsoft_extensions_logging.*
|
||||
|
||||
/**
|
||||
* SimApi 日志记录器:输出格式对齐 C# 原版 SimApiLogger。
|
||||
* 格式:`[ 分类 ][ 时间 ][ 级别 ]\n消息\n[异常]`
|
||||
* 按日志级别着色输出。
|
||||
*/
|
||||
public class SimApiLogger <: ILogger {
|
||||
private let _name: String
|
||||
|
||||
public init(name: String) {
|
||||
_name = name
|
||||
}
|
||||
|
||||
public func log<TState>(logLevel: LogLevel, eventId: EventId, state: TState, exception: ?Exception,
|
||||
formatter: (TState, ?Exception) -> String): Unit where TState <: ToString {
|
||||
if (!isEnabled(logLevel)) {
|
||||
return
|
||||
}
|
||||
|
||||
let now = DateTime.now()
|
||||
let timeStr = formatTime(now)
|
||||
let levelStr = levelName(logLevel)
|
||||
|
||||
var sb = StringBuilder()
|
||||
sb.append("${color(levelColor(logLevel))}[ ${_name} ][ ${timeStr} ][ ${levelStr} ]\n")
|
||||
sb.append("${state}\n")
|
||||
if (let Some(ex) <- exception) {
|
||||
sb.append("${ex}\n")
|
||||
}
|
||||
sb.append(resetColor())
|
||||
// 对齐 C# Console.WriteLine:message 末尾 \n 之后再补一个 \n,形成空行分隔
|
||||
sb.append("\n")
|
||||
|
||||
let writer = getStdOut()
|
||||
writer.write(sb.toString())
|
||||
writer.flush()
|
||||
}
|
||||
|
||||
public func isEnabled(logLevel: LogLevel): Bool {
|
||||
logLevel != LogLevel.Off
|
||||
}
|
||||
|
||||
/**
|
||||
* 级别名称,对齐 C# 的 LogLevel.ToString()。
|
||||
*/
|
||||
private static func levelName(logLevel: LogLevel): String {
|
||||
match (logLevel) {
|
||||
case LogLevel.Trace => "Trace"
|
||||
case LogLevel.Debug => "Debug"
|
||||
case LogLevel.Info => "Information"
|
||||
case LogLevel.Warn => "Warning"
|
||||
case LogLevel.Error => "Error"
|
||||
case LogLevel.Fatal => "Critical"
|
||||
case _ => "None"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 级别对应 ANSI 前景色(对齐 C# ConsoleColor):
|
||||
* Debug→DarkMagenta, Info→DarkCyan, Warn→Yellow, Error→Red, Fatal→DarkRed, 其他→White
|
||||
*/
|
||||
private static func levelColor(logLevel: LogLevel): String {
|
||||
match (logLevel) {
|
||||
case LogLevel.Debug => "35" // DarkMagenta
|
||||
case LogLevel.Info => "36" // DarkCyan
|
||||
case LogLevel.Warn => "33" // Yellow
|
||||
case LogLevel.Error => "31" // Red
|
||||
case LogLevel.Fatal => "31;1" // DarkRed(粗体近似)
|
||||
case _ => "37" // White
|
||||
}
|
||||
}
|
||||
|
||||
private static func color(code: String): String {
|
||||
"\u{1b}[${code}m"
|
||||
}
|
||||
|
||||
private static func resetColor(): String {
|
||||
"\u{1b}[0m"
|
||||
}
|
||||
|
||||
private static func formatTime(dt: DateTime): String {
|
||||
let year = dt.year
|
||||
let month = pad2(dt.monthValue)
|
||||
let day = pad2(dt.dayOfMonth)
|
||||
let hour = pad2(dt.hour)
|
||||
let minute = pad2(dt.minute)
|
||||
let second = pad2(dt.second)
|
||||
let millis = pad3(dt.nanosecond / 1000000)
|
||||
"${year}-${month}-${day} ${hour}:${minute}:${second}:${millis}"
|
||||
}
|
||||
|
||||
private static func pad2(v: Int64): String {
|
||||
if (v < 10) {
|
||||
return "0${v}"
|
||||
}
|
||||
"${v}"
|
||||
}
|
||||
|
||||
private static func pad3(v: Int64): String {
|
||||
if (v < 10) {
|
||||
return "00${v}"
|
||||
}
|
||||
if (v < 100) {
|
||||
return "0${v}"
|
||||
}
|
||||
"${v}"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SimApi 日志提供程序:按分类缓存日志记录器。
|
||||
*/
|
||||
public class SimApiLoggerProvider <: ILoggerProvider {
|
||||
private let _loggers = ConcurrentHashMap<String, SimApiLogger>()
|
||||
|
||||
public init() {}
|
||||
|
||||
public func createLogger(categoryName: String): ILogger {
|
||||
if (let Some(logger) <- _loggers.get(categoryName)) {
|
||||
return logger
|
||||
}
|
||||
return _loggers.entryView(categoryName) {
|
||||
view => if (view.value.isNone()) {
|
||||
view.value = SimApiLogger(categoryName)
|
||||
}
|
||||
}.getOrThrow()
|
||||
}
|
||||
|
||||
public func close(): Unit {}
|
||||
|
||||
public func isClosed(): Bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user