daShangDao_planA/modules/logs/logger.md

13 KiB
Raw Permalink Blame History

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=SUCCESS1=INFO2=WARNING3=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 需要释放的字符串