/*
* Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
*/
package magic.log
import magic.core.message.ChatMessage
import magic.core.message.Dialog
import magic.config.Config
import magic.utils.exists
import std.fs.{File, OpenOption, Directory, Path}
import std.console.Console
import std.collection.HashMap
import std.io.OutputStream
import std.log.LogLevel as EnumLogLevel
import log.LogLevel
@When[cjc_version < "0.56.4"]
import std.log.SimpleLogger
@When[cjc_version >= "0.56.4"]
import logger.SimpleLogger
@When[cjc_version < "0.56.4"]
private func buildSimpleLogger(output: OutputStream): SimpleLogger {
let logger = SimpleLogger("logger", EnumLogLevel.INFO, output)
logger.level = convertLogLevel(Config.logLevel)
return logger
}
@When[cjc_version < "0.56.4"]
private func convertLogLevel(logLevel: LogLevel): EnumLogLevel {
if (logLevel == LogLevel.OFF) {
return EnumLogLevel.OFF
} else if (logLevel == LogLevel.FATAL || logLevel == LogLevel.ERROR) {
return EnumLogLevel.ERROR
} else if (logLevel == LogLevel.WARN) {
return EnumLogLevel.WARN
} else if (logLevel == LogLevel.INFO) {
return EnumLogLevel.INFO
} else if (logLevel == LogLevel.DEBUG) {
return EnumLogLevel.DEBUG
} else if (logLevel == LogLevel.TRACE) {
return EnumLogLevel.TRACE
} else if (logLevel == LogLevel.ALL) {
return EnumLogLevel.ALL
}
throw UnsupportedException()
}
@When[cjc_version >= "0.56.4"]
private func buildSimpleLogger(output: OutputStream): SimpleLogger {
let logger = SimpleLogger(output)
logger.level = Config.logLevel
return logger
}
@When[ohos != "true"]
public struct LogUtils {
private static var _LOGGER: Option<SimpleLogger> = None
private static prop LOGGER: SimpleLogger {
get() {
match (_LOGGER) {
case Some(logger) =>
return logger
case None =>
let logger = if (Config.logFile == "stdout") {
buildSimpleLogger(Console.stdOut)
} else if (Config.logFile == "stderr") {
buildSimpleLogger(Console.stdErr)
} else {
let file = File(Config.logFile, OpenOption.CreateOrTruncate(false))
buildSimpleLogger(file)
}
_LOGGER = logger
return logger
}
}
}
private static let NAMED_LOGGERS = HashMap<String, SimpleLogger>()
private static func getNamedLogger(name: String): SimpleLogger {
if (NAMED_LOGGERS.contains(name)) {
return NAMED_LOGGERS[name]
}
if (!exists(Config.agentLogDir)) {
Directory.create(Config.agentLogDir, recursive: true)
}
let path = Path(Config.agentLogDir).join("${name}.log")
let file = File(path, OpenOption.CreateOrTruncate(false))
let logger = buildSimpleLogger(file)
NAMED_LOGGERS[name] = logger
return logger
}
public static func debug(msg: String): Unit {
LOGGER.debug(msg)
}
public static func debug(name: String, msg: String): Unit {
debug("${name}: ${msg}")
}
public static func info(msg: String): Unit {
LOGGER.info(msg)
}
public static func info(name: String, msg: String): Unit {
info("${name}: ${msg}")
if (Config.enableAgentLog) {
let logger = getNamedLogger(name)
logger.info("${name}: ${msg}")
}
}
public static func info(msg: ChatMessage): Unit {
info("Chat Message[ ${msg.role} ]: ${msg.content}")
}
public static func info(name: String, msg: ChatMessage): Unit {
info(name, "Chat Message[ ${msg.role} ]: ${msg.content}")
}
public static func info(history: Dialog): Unit {
for (msg in history) {
info(msg)
}
}
public static func info(name: String, history: Dialog): Unit {
for (msg in history) {
info(name, msg)
}
}
public static func info(messages: Array<ChatMessage>): Unit {
for (msg in messages) {
info(msg)
}
}
public static func info(name: String, messages: Array<ChatMessage>): Unit {
for (msg in messages) {
info(name, msg)
}
}
public static func error(msg: String): Unit {
LOGGER.error(msg)
}
public static func error(name: String, msg: String): Unit {
error("${name}: ${msg}")
if (Config.enableAgentLog) {
let logger = getNamedLogger(name)
logger.error("${name}: ${msg}")
}
}
}