logger.dll 使用教程
1. 创建DLL工具实例
加载DLL文件
package logs
import (
"encoding/json"
"fmt"
"os"
"runtime"
"syscall"
"unsafe"
)
// LoggerDLL 封装 logger.dll 操作
type LoggerDLL struct {
dll *syscall.LazyDLL
createLogger *syscall.LazyProc
createContext *syscall.LazyProc
logInfo *syscall.LazyProc
logError *syscall.LazyProc
logWarning *syscall.LazyProc
logSuccess *syscall.LazyProc
freeString *syscall.LazyProc
closeAllLoggers *syscall.LazyProc
}
// LoggerConfig logger配置结构
type LoggerConfig struct {
LogDir string `json:"log_dir"`
SplitType int `json:"split_type"`
RotateType int `json:"rotate_type"`
MaxSize int64 `json:"max_size"`
MaxCount int `json:"max_count"`
Level int `json:"level"`
EnableCaller bool `json:"enable_caller"`
DefaultTaskType string `json:"default_task_type"`
}
var loggerDLLInstance *LoggerDLL
var loggerHandle string
var loggerContextHandle string
// ensureLoggerDLL 确保logger DLL已加载
func ensureLoggerDLL() (*LoggerDLL, error) {
if loggerDLLInstance != nil {
return loggerDLLInstance, nil
}
// 检查是否在Windows平台
if runtime.GOOS != "windows" {
return nil, fmt.Errorf("logger DLL only supported on Windows platform")
}
// logger.dll 位于 dll/logger.dll
//dllPath := filepath.Join("modules", "logs", "logger.dll")
dllPath := "D:\\www\\wwwroot\\planA\\modules\\logs\\logger.dll"
// 检查文件是否存在
if _, err := os.Stat(dllPath); os.IsNotExist(err) {
// 尝试从当前目录查找
if _, err := os.Stat("logger.dll"); err == nil {
dllPath = "logger.dll"
} else {
return nil, fmt.Errorf("logger DLL not found at %s", dllPath)
}
}
dll := syscall.NewLazyDLL(dllPath)
loggerDLLInstance = &LoggerDLL{
dll: dll,
createLogger: dll.NewProc("CreateLogger"),
createContext: dll.NewProc("CreateContextWithTaskType"),
logInfo: dll.NewProc("LogInfo"),
logError: dll.NewProc("LogError"),
logWarning: dll.NewProc("LogWarning"),
logSuccess: dll.NewProc("LogSuccess"),
freeString: dll.NewProc("FreeString"),
closeAllLoggers: dll.NewProc("CloseAllLoggers"),
}
return loggerDLLInstance, nil
}
// cStr 将 C 字符串指针转换为 Go 字符串
func cStr(ptr uintptr) string {
if ptr == 0 {
return ""
}
var b []byte
for {
c := *(*byte)(unsafe.Pointer(ptr))
if c == 0 {
break
}
b = append(b, c)
ptr++
}
return string(b)
}
// InitializeLogger 初始化logger
func InitializeLogger(logDir string) error {
m, err := ensureLoggerDLL()
if err != nil {
return err
}
// 确保日志目录存在
if err := os.MkdirAll(logDir, 0755); err != nil {
return fmt.Errorf("创建日志目录失败: %v", err)
}
// 创建logger配置
config := LoggerConfig{
LogDir: logDir,
SplitType: 1, // SplitByDay
RotateType: 0, // RotateBySize
MaxSize: 100 * 1024 * 1024, // 100MB
MaxCount: 10,
Level: 1, // LevelInfo - 只显示INFO及以上级别的日志
EnableCaller: true,
DefaultTaskType: "main",
}
configJSON, err := json.Marshal(config)
if err != nil {
return fmt.Errorf("序列化配置失败: %v", err)
}
// 调用CreateLogger
configPtr, _ := syscall.BytePtrFromString(string(configJSON))
ret, _, _ := m.createLogger.Call(uintptr(unsafe.Pointer(configPtr)))
if ret == 0 {
return fmt.Errorf("创建logger失败")
}
// 获取logger句柄
handle := cStr(ret)
loggerHandle = handle
// 释放返回的字符串
m.freeString.Call(ret)
// 创建默认上下文
return createLoggerContext("main")
}
// createLoggerContext 创建带任务类型的logger上下文
func createLoggerContext(taskType string) error {
m, err := ensureLoggerDLL()
if err != nil {
return err
}
if loggerHandle == "" {
return fmt.Errorf("logger未初始化")
}
handlePtr, _ := syscall.BytePtrFromString(loggerHandle)
taskTypePtr, _ := syscall.BytePtrFromString(taskType)
ret, _, _ := m.createContext.Call(
uintptr(unsafe.Pointer(handlePtr)),
uintptr(unsafe.Pointer(taskTypePtr)),
)
if ret == 0 {
return fmt.Errorf("创建logger上下文失败")
}
// 获取上下文句柄
loggerContextHandle = cStr(ret)
// 释放返回的字符串
m.freeString.Call(ret)
return nil
}
// SetLogTaskType 设置当前日志任务类型
func SetLogTaskType(taskType string) error {
return createLoggerContext(taskType)
}
// LogInfo 记录信息日志
func LogInfo(message string) error {
m, err := ensureLoggerDLL()
if err != nil {
return err
}
if loggerContextHandle == "" {
return fmt.Errorf("logger上下文未初始化")
}
ctxPtr, _ := syscall.BytePtrFromString(loggerContextHandle)
msgPtr, _ := syscall.BytePtrFromString(message)
m.logInfo.Call(
uintptr(unsafe.Pointer(ctxPtr)),
uintptr(unsafe.Pointer(msgPtr)),
)
return nil
}
// LogError 记录错误日志
func LogError(message string) error {
m, err := ensureLoggerDLL()
if err != nil {
return err
}
if loggerContextHandle == "" {
return fmt.Errorf("logger上下文未初始化")
}
ctxPtr, _ := syscall.BytePtrFromString(loggerContextHandle)
msgPtr, _ := syscall.BytePtrFromString(message)
m.logError.Call(
uintptr(unsafe.Pointer(ctxPtr)),
uintptr(unsafe.Pointer(msgPtr)),
)
return nil
}
// LogWarning 记录警告日志
func LogWarning(message string) error {
m, err := ensureLoggerDLL()
if err != nil {
return err
}
if loggerContextHandle == "" {
return fmt.Errorf("logger上下文未初始化")
}
ctxPtr, _ := syscall.BytePtrFromString(loggerContextHandle)
msgPtr, _ := syscall.BytePtrFromString(message)
m.logWarning.Call(
uintptr(unsafe.Pointer(ctxPtr)),
uintptr(unsafe.Pointer(msgPtr)),
)
return nil
}
// LogSuccess 记录成功日志
func LogSuccess(message string) error {
m, err := ensureLoggerDLL()
if err != nil {
return err
}
if loggerContextHandle == "" {
return fmt.Errorf("logger上下文未初始化")
}
ctxPtr, _ := syscall.BytePtrFromString(loggerContextHandle)
msgPtr, _ := syscall.BytePtrFromString(message)
m.logSuccess.Call(
uintptr(unsafe.Pointer(ctxPtr)),
uintptr(unsafe.Pointer(msgPtr)),
)
return nil
}
// CloseLogger 关闭logger
func CloseLogger() error {
m, err := ensureLoggerDLL()
if err != nil {
return err
}
ret, _, _ := m.closeAllLoggers.Call()
if ret == 0 {
return fmt.Errorf("关闭logger失败")
}
m.freeString.Call(ret)
loggerHandle = ""
loggerContextHandle = ""
loggerDLLInstance = nil
return nil
}
// GetLoggerHandle 获取当前logger句柄(用于外部调用)
func GetLoggerHandle() string {
return loggerContextHandle
}
// IsLoggerInitialized 检查logger是否已初始化
func IsLoggerInitialized() bool {
return loggerHandle != "" && loggerContextHandle != ""
}
// SetConsoleOutput 设置控制台输出开关
func SetConsoleOutput(enabled bool) {
if enabled {
os.Setenv("LOG_CONSOLE", "true")
} else {
os.Setenv("LOG_CONSOLE", "false")
}
}
// LogWithLevel 带级别的日志记录,可以精确控制显示
func LogWithLevel(level, message string, showConsole bool) {
if !IsLoggerInitialized() {
return
}
switch level {
case "ERROR":
LogError(message)
case "WARNING":
LogWarning(message)
case "SUCCESS":
LogSuccess(message)
case "INFO":
LogInfo(message)
default:
LogInfo(message)
}
}
// LogOnlyFile 仅写入文件,不输出到控制台
func LogOnlyFile(level, message string) {
// 临时禁用控制台输出
os.Setenv("LOG_CONSOLE", "false")
LogWithLevel(level, message, false)
}
// LogConsoleAndFile 同时输出到控制台和文件
func LogConsoleAndFile(level, message string) {
// 临时启用控制台输出
os.Setenv("LOG_CONSOLE", "true")
LogWithLevel(level, message, true)
}
接口详情
创建日志器--CreateLogger
请求信息
dll.CreateLogger(configJSON)
请求参数
| 参数名 |
类型 |
必填 |
说明 |
| configJSON |
string |
是 |
配置信息JSON字符串 |
配置JSON结构
{
"log_dir": "/path/to/logs",
"split_type": 0,
"rotate_type": 0,
"max_size": 104857600,
"max_count": 30,
"level": 1,
"enable_caller": true,
"default_task_type": "main"
}
参数说明:
log_dir: 日志目录路径
split_type: 分片方式(0=按月,1=按天,2=按小时,3=按分钟,4=按秒)
rotate_type: 轮转方式(0=按大小,1=按数量)
max_size: 最大文件大小(字节),仅在rotate_type=0时有效
max_count: 最大文件数量,仅在rotate_type=1时有效
level: 日志级别(0=SUCCESS,1=INFO,2=WARNING,3=ERROR)
enable_caller: 是否启用调用者信息
default_task_type: 默认任务类型
响应示例
"错误: 创建日志目录失败: permission denied"
创建带任务类型的上下文--CreateContextWithTaskType
请求信息
dll.CreateContextWithTaskType(loggerHandle, taskType)
请求参数
| 参数名 |
类型 |
必填 |
说明 |
| loggerHandle |
string |
是 |
日志器句柄 |
| taskType |
string |
是 |
任务类型 |
响应示例
"ctx_1645497600000000000"
错误响应示例
"错误: 无效的logger句柄"
记录信息日志--LogInfo
请求信息
dll.LogInfo(ctxHandle, message)
请求参数
| 参数名 |
类型 |
必填 |
说明 |
| ctxHandle |
string |
是 |
上下文句柄 |
| message |
string |
是 |
日志消息 |
响应示例
无返回值,日志将写入到对应的日志文件中。
记录错误日志--LogError
请求信息
dll.LogError(ctxHandle, message)
请求参数
| 参数名 |
类型 |
必填 |
说明 |
| ctxHandle |
string |
是 |
上下文句柄 |
| message |
string |
是 |
日志消息 |
响应示例
无返回值,日志将写入到对应的日志文件中。
记录警告日志--LogWarning
请求信息
dll.LogWarning(ctxHandle, message)
请求参数
| 参数名 |
类型 |
必填 |
说明 |
| ctxHandle |
string |
是 |
上下文句柄 |
| message |
string |
是 |
日志消息 |
响应示例
无返回值,日志将写入到对应的日志文件中。
记录成功日志--LogSuccess
请求信息
dll.LogSuccess(ctxHandle, message)
请求参数
| 参数名 |
类型 |
必填 |
说明 |
| ctxHandle |
string |
是 |
上下文句柄 |
| message |
string |
是 |
日志消息 |
响应示例
无返回值,日志将写入到对应的日志文件中。
获取日志条目--GetLogs
请求信息
dll.GetLogs(loggerHandle, configJSON)
请求参数
| 参数名 |
类型 |
必填 |
说明 |
| loggerHandle |
string |
是 |
日志器句柄 |
| configJSON |
string |
是 |
查询配置JSON |
查询配置JSON结构
{
"level": 1,
"task_type": "main",
"start_time": "2024-01-01 00:00:00",
"end_time": "2024-01-31 23:59:59",
"max_entries": 1000
}
参数说明:
level: 日志级别(-1表示所有级别)
task_type: 任务类型(空字符串表示所有任务类型)
start_time: 开始时间(格式: 2006-01-02 15:04:05)
end_time: 结束时间(格式: 2006-01-02 15:04:05)
max_entries: 最大返回条目数(0表示使用默认值1000)
响应示例
{
"count": 125,
"entries": [
{
"timestamp": "2024-01-15 10:30:45.123",
"level": "INFO",
"task_type": "main",
"caller": "logger.go:256",
"message": "系统启动完成"
},
{
"timestamp": "2024-01-15 10:31:15.456",
"level": "ERROR",
"task_type": "backup",
"caller": "backup.go:89",
"message": "备份文件失败: 磁盘空间不足"
}
]
}
错误响应示例
{"error": "无效的logger句柄"}
获取日志文件列表--GetLogFiles
请求信息
dll.GetLogFiles(loggerHandle)
请求参数
| 参数名 |
类型 |
必填 |
说明 |
| loggerHandle |
string |
是 |
日志器句柄 |
响应示例
{
"count": 8,
"files": [
{
"level": "INFO",
"task_type": "main",
"file_name": "INFO-main-2024-01.logs",
"file_size": 1048576,
"mod_time": "2024-01-15 10:30:45"
},
{
"level": "ERROR",
"task_type": "backup",
"file_name": "ERROR-backup-2024-01.logs",
"file_size": 51200,
"mod_time": "2024-01-15 10:31:15"
}
]
}
错误响应示例
{"error": "无效的logger句柄"}
获取版本信息--GetVersion
请求信息
dll.GetVersion()
请求参数
无参数
响应示例
"v1"
关闭所有日志器--CloseAllLoggers
请求信息
dll.CloseAllLoggers()
请求参数
无参数
响应示例
"成功关闭所有logger"
错误响应示例
"关闭了5个logger,其中1个出错,最后错误: close file error"
释放C字符串内存--FreeString
请求信息
dll.FreeString(str)
请求参数
| 参数名 |
类型 |
必填 |
说明 |
| str |
string |
是 |
需要释放的字符串 |