daShangDao_kfzgw-info/logger/loggerDll.go
2026-02-27 11:46:40 +08:00

841 lines
22 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import "C"
import (
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"syscall"
"time"
"unsafe"
"golang.org/x/sys/windows"
)
// LoggerWrapper 封装DLL调用
type LoggerWrapper struct {
dllHandle windows.Handle
createLogger uintptr
createContext uintptr
logInfo uintptr
logError uintptr
logWarning uintptr
logSuccess uintptr
freeString uintptr
closeAllLoggers uintptr
// cui
getLogs uintptr
getLogFiles uintptr
}
// 全局变量来跟踪创建的logger数量
var (
createdLoggers []string
loggerCount int
)
func NewLoggerWrapper(dllPath string) (*LoggerWrapper, error) {
if _, err := os.Stat(dllPath); os.IsNotExist(err) {
return nil, fmt.Errorf("DLL文件不存在: %s", dllPath)
}
dllHandle, err := windows.LoadLibrary(dllPath)
if err != nil {
return nil, fmt.Errorf("加载DLL失败: %v", err)
}
wrapper := &LoggerWrapper{
dllHandle: dllHandle,
}
if err := wrapper.loadFunctions(); err != nil {
windows.FreeLibrary(dllHandle)
return nil, err
}
return wrapper, nil
}
func (lw *LoggerWrapper) loadFunctions() error {
var err error
lw.createLogger, err = windows.GetProcAddress(lw.dllHandle, "CreateLogger")
if err != nil {
return err
}
lw.createContext, err = windows.GetProcAddress(lw.dllHandle, "CreateContextWithTaskType")
if err != nil {
return err
}
lw.logInfo, err = windows.GetProcAddress(lw.dllHandle, "LogInfo")
if err != nil {
return err
}
lw.logError, err = windows.GetProcAddress(lw.dllHandle, "LogError")
if err != nil {
return err
}
lw.logWarning, err = windows.GetProcAddress(lw.dllHandle, "LogWarning")
if err != nil {
return err
}
lw.logSuccess, err = windows.GetProcAddress(lw.dllHandle, "LogSuccess")
if err != nil {
return err
}
lw.freeString, err = windows.GetProcAddress(lw.dllHandle, "FreeString")
if err != nil {
return err
}
lw.closeAllLoggers, err = windows.GetProcAddress(lw.dllHandle, "CloseAllLoggers")
if err != nil {
return err
}
// cui
lw.getLogs, err = windows.GetProcAddress(lw.dllHandle, "GetLogs")
if err != nil {
return err
}
// cui
lw.getLogFiles, err = windows.GetProcAddress(lw.dllHandle, "GetLogFiles")
if err != nil {
return err
}
return nil
}
func (lw *LoggerWrapper) CreateLogger(configJSON string) (string, error) {
configCStr, err := syscall.BytePtrFromString(configJSON)
if err != nil {
return "", err
}
resultPtr, _, err := syscall.SyscallN(lw.createLogger, uintptr(unsafe.Pointer(configCStr)))
if err != syscall.Errno(0) {
return "", fmt.Errorf("CreateLogger调用失败: %v", err)
}
if resultPtr == 0 {
return "", fmt.Errorf("CreateLogger返回空指针")
}
result := readNullTerminatedString(resultPtr)
lw.FreeStringByPtr(resultPtr)
// 记录创建的logger
createdLoggers = append(createdLoggers, result)
loggerCount++
return result, nil
}
func (lw *LoggerWrapper) CreateContextWithTaskType(loggerHandle, taskType string) (string, error) {
loggerHandleCStr, err := syscall.BytePtrFromString(loggerHandle)
if err != nil {
return "", err
}
taskTypeCStr, err := syscall.BytePtrFromString(taskType)
if err != nil {
return "", err
}
resultPtr, _, err := syscall.SyscallN(
lw.createContext,
uintptr(unsafe.Pointer(loggerHandleCStr)),
uintptr(unsafe.Pointer(taskTypeCStr)),
)
if err != syscall.Errno(0) {
return "", fmt.Errorf("CreateContextWithTaskType调用失败: %v", err)
}
if resultPtr == 0 {
return "", fmt.Errorf("CreateContextWithTaskType返回空指针")
}
result := readNullTerminatedString(resultPtr)
lw.FreeStringByPtr(resultPtr)
return result, nil
}
func (lw *LoggerWrapper) LogInfo(ctxHandle, message string) error {
return lw.logMessage(ctxHandle, message, lw.logInfo)
}
func (lw *LoggerWrapper) LogError(ctxHandle, message string) error {
return lw.logMessage(ctxHandle, message, lw.logError)
}
func (lw *LoggerWrapper) LogWarning(ctxHandle, message string) error {
return lw.logMessage(ctxHandle, message, lw.logWarning)
}
func (lw *LoggerWrapper) LogSuccess(ctxHandle, message string) error {
return lw.logMessage(ctxHandle, message, lw.logSuccess)
}
func (lw *LoggerWrapper) logMessage(ctxHandle, message string, logFunc uintptr) error {
ctxHandleCStr, err := syscall.BytePtrFromString(ctxHandle)
if err != nil {
return err
}
messageCStr, err := syscall.BytePtrFromString(message)
if err != nil {
return err
}
_, _, err = syscall.SyscallN(
logFunc,
uintptr(unsafe.Pointer(ctxHandleCStr)),
uintptr(unsafe.Pointer(messageCStr)),
)
if err != syscall.Errno(0) {
return fmt.Errorf("日志记录失败: %v", err)
}
return nil
}
// cui
func (lw *LoggerWrapper) GetLogs(loggerHandle, configJSON string) (string, error) {
loggerHandleCStr, err := syscall.BytePtrFromString(loggerHandle)
if err != nil {
return "", err
}
configCStr, err := syscall.BytePtrFromString(configJSON)
if err != nil {
return "", err
}
resultPtr, _, err := syscall.SyscallN(
lw.getLogs,
uintptr(unsafe.Pointer(loggerHandleCStr)),
uintptr(unsafe.Pointer(configCStr)),
)
if err != syscall.Errno(0) {
return "", fmt.Errorf("GetLogs调用失败: %v", err)
}
if resultPtr == 0 {
return "", fmt.Errorf("GetLogs返回空指针")
}
result := ptrToString(resultPtr)
lw.FreeStringByPtr(resultPtr)
return result, nil
}
// cui
func (lw *LoggerWrapper) GetLogFiles(loggerHandle string) (string, error) {
loggerHandleCStr, err := syscall.BytePtrFromString(loggerHandle)
if err != nil {
return "", err
}
resultPtr, _, err := syscall.SyscallN(
lw.getLogFiles,
uintptr(unsafe.Pointer(loggerHandleCStr)),
)
if err != syscall.Errno(0) {
return "", fmt.Errorf("GetLogFiles调用失败: %v", err)
}
if resultPtr == 0 {
return "", fmt.Errorf("GetLogFiles返回空指针")
}
result := ptrToString(resultPtr)
lw.FreeStringByPtr(resultPtr)
return result, nil
}
func ptrToString(ptr uintptr) string {
if ptr == 0 {
return ""
}
// 先找到字符串长度
var length int
for {
b := *(*byte)(unsafe.Pointer(ptr + uintptr(length)))
if b == 0 {
break
}
length++
if length > 64*1024 { // 64KB限制
break
}
}
if length == 0 {
return ""
}
// 创建适当大小的切片
data := make([]byte, length)
for i := 0; i < length; i++ {
data[i] = *(*byte)(unsafe.Pointer(ptr + uintptr(i)))
}
return string(data)
}
func (lw *LoggerWrapper) FreeStringByPtr(ptr uintptr) {
if ptr != 0 {
syscall.SyscallN(lw.freeString, ptr)
}
}
func (lw *LoggerWrapper) CloseAllLoggers() (string, error) {
resultPtr, _, err := syscall.SyscallN(lw.closeAllLoggers)
if err != syscall.Errno(0) {
return "", fmt.Errorf("CloseAllLoggers调用失败: %v", err)
}
if resultPtr == 0 {
return "", fmt.Errorf("CloseAllLoggers返回空指针")
}
result := readNullTerminatedString(resultPtr)
lw.FreeStringByPtr(resultPtr)
return result, nil
}
func readNullTerminatedString(ptr uintptr) string {
if ptr == 0 {
return ""
}
var bytes []byte
for i := 0; i < 256; i++ {
b := *(*byte)(unsafe.Pointer(ptr + uintptr(i)))
if b == 0 {
break
}
bytes = append(bytes, b)
}
return string(bytes)
}
func (lw *LoggerWrapper) Close() error {
return windows.FreeLibrary(lw.dllHandle)
}
func checkError(result string) error {
if len(result) >= 6 && result[:6] == "错误:" {
return fmt.Errorf(result)
}
return nil
}
// 监控内存
func monitorResources() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("📊 内存使用: Alloc=%.2fMB, TotalAlloc=%.2fMB, Sys=%.2fMB, NumGC=%d, Goroutines=%d\n",
float64(m.Alloc)/1024/1024,
float64(m.TotalAlloc)/1024/1024,
float64(m.Sys)/1024/1024,
m.NumGC,
runtime.NumGoroutine())
}
// 测试日志读取功能 cui
func testLogReadingFunctions(wrapper *LoggerWrapper) {
fmt.Println("\n📖 ========== 开始日志读取功能测试 ==========")
// 创建测试logger
config := `{
"log_dir": "./test_logs_reading",
"level": 1,
"split_type": 1,
"max_size": 1048576,
"max_count": 5,
"enable_caller": true,
"default_task_type": "reading_test"
}`
loggerHandle, err := wrapper.CreateLogger(config)
if err != nil {
log.Printf("创建测试logger失败: %v", err)
return
}
fmt.Printf("✅ 创建测试logger: %s\n", loggerHandle)
// 创建不同任务类型的上下文
taskTypes := []string{"task_a", "task_b", "task_c"}
ctxHandles := make(map[string]string)
for _, taskType := range taskTypes {
ctxHandle, err := wrapper.CreateContextWithTaskType(loggerHandle, taskType)
if err != nil {
log.Printf("创建上下文失败: %v", err)
continue
}
ctxHandles[taskType] = ctxHandle
fmt.Printf("✅ 创建上下文: %s -> %s\n", taskType, ctxHandle)
}
// 记录测试日志
fmt.Println("\n📝 记录测试日志数据...")
messages := []struct {
level string
message string
task string
}{
{"INFO", "这是INFO级别的测试消息", "task_a"},
{"ERROR", "这是ERROR级别的错误消息", "task_b"},
{"WARNING", "这是WARNING级别的警告消息", "task_c"},
{"SUCCESS", "这是SUCCESS级别的成功消息", "task_a"},
{"INFO", "另一条INFO消息", "task_b"},
}
for i, msg := range messages {
var err error
switch msg.level {
case "INFO":
err = wrapper.LogInfo(ctxHandles[msg.task], fmt.Sprintf("%s - 序号: %d", msg.message, i))
case "ERROR":
err = wrapper.LogError(ctxHandles[msg.task], fmt.Sprintf("%s - 序号: %d", msg.message, i))
case "WARNING":
err = wrapper.LogWarning(ctxHandles[msg.task], fmt.Sprintf("%s - 序号: %d", msg.message, i))
case "SUCCESS":
err = wrapper.LogSuccess(ctxHandles[msg.task], fmt.Sprintf("%s - 序号: %d", msg.message, i))
}
if err != nil {
log.Printf("记录日志失败: %v", err)
} else {
fmt.Printf("✅ 记录%s日志: %s\n", msg.level, msg.message)
}
}
// 等待一下确保日志写入完成
time.Sleep(100 * time.Millisecond)
// 测试1: 获取日志文件列表
fmt.Println("\n📁 测试1: 获取日志文件列表")
filesResult, err := wrapper.GetLogFiles(loggerHandle)
if err != nil {
log.Printf("获取日志文件列表失败: %v", err)
} else {
fmt.Printf("✅ 获取日志文件列表成功:\n%s\n", formatJSON(filesResult))
}
// 测试2: 获取所有日志
fmt.Println("\n📄 测试2: 获取所有日志")
allLogsConfig := `{
"level": -1,
"max_entries": 50
}`
allLogsResult, err := wrapper.GetLogs(loggerHandle, allLogsConfig)
if err != nil {
log.Printf("获取所有日志失败: %v", err)
} else {
fmt.Printf("✅ 获取所有日志成功:\n%s\n", formatJSON(allLogsResult))
}
// 测试3: 按级别过滤日志
fmt.Println("\n🔍 测试3: 按级别过滤日志(INFO)")
infoLogsConfig := `{
"level": 1,
"max_entries": 10
}`
infoLogsResult, err := wrapper.GetLogs(loggerHandle, infoLogsConfig)
if err != nil {
log.Printf("获取INFO日志失败: %v", err)
} else {
fmt.Printf("✅ 获取INFO日志成功:\n%s\n", formatJSON(infoLogsResult))
}
// 测试4: 按任务类型过滤日志
fmt.Println("\n🔍 测试4: 按任务类型过滤日志(task_a)")
taskALogsConfig := `{
"level": -1,
"task_type": "task_a",
"max_entries": 10
}`
taskALogsResult, err := wrapper.GetLogs(loggerHandle, taskALogsConfig)
if err != nil {
log.Printf("获取task_a日志失败: %v", err)
} else {
fmt.Printf("✅ 获取task_a日志成功:\n%s\n", formatJSON(taskALogsResult))
}
// 测试5: 限制返回条目数
fmt.Println("\n🔍 测试5: 限制返回条目数(2条)")
limitedLogsConfig := `{
"level": -1,
"max_entries": 2
}`
limitedLogsResult, err := wrapper.GetLogs(loggerHandle, limitedLogsConfig)
if err != nil {
log.Printf("获取限制条目日志失败: %v", err)
} else {
fmt.Printf("✅ 获取限制条目日志成功:\n%s\n", formatJSON(limitedLogsResult))
}
// 测试6: 组合条件查询
fmt.Println("\n🔍 测试6: 组合条件查询(ERROR级别 + task_b)")
combinedConfig := `{
"level": 3,
"task_type": "task_b",
"max_entries": 10
}`
combinedResult, err := wrapper.GetLogs(loggerHandle, combinedConfig)
if err != nil {
log.Printf("组合条件查询失败: %v", err)
} else {
fmt.Printf("✅ 组合条件查询成功:\n%s\n", formatJSON(combinedResult))
}
// 测试7: 组合条件查询
fmt.Println("\n🔍 测试7: 组合条件查询(task_b)")
combinedTimeConfig := `{
"level": -1,
"task_type": "task_b",
"start_time": "2025-11-25 15:03:31",
"end_time": "2025-11-25 15:04:31",
"max_entries": 10
}`
combinedTimeResult, err := wrapper.GetLogs(loggerHandle, combinedTimeConfig)
if err != nil {
log.Printf("组合条件查询失败: %v", err)
} else {
fmt.Printf("✅ 组合条件查询成功:\n%s\n", formatJSON(combinedTimeResult))
}
// 解析并分析结果
fmt.Println("\n📊 日志读取功能测试分析:")
analyzeLogReadingResults(allLogsResult)
fmt.Println("✅ 日志读取功能测试完成")
}
// 分析日志读取结果 cui
func analyzeLogReadingResults(logsResult string) {
var result map[string]interface{}
if err := json.Unmarshal([]byte(logsResult), &result); err != nil {
log.Printf("解析日志结果失败: %v", err)
return
}
if errorMsg, exists := result["error"]; exists {
fmt.Printf("❌ 错误: %v\n", errorMsg)
return
}
count, _ := result["count"].(float64)
entries, _ := result["entries"].([]interface{})
fmt.Printf(" 总日志条目数: %.0f\n", count)
// 统计各级别日志数量
levelCount := make(map[string]int)
taskCount := make(map[string]int)
for _, entry := range entries {
if entryMap, ok := entry.(map[string]interface{}); ok {
level, _ := entryMap["level"].(string)
taskType, _ := entryMap["task_type"].(string)
levelCount[level]++
taskCount[taskType]++
}
}
fmt.Println(" 日志级别分布:")
for level, count := range levelCount {
fmt.Printf(" - %s: %d条\n", level, count)
}
fmt.Println(" 任务类型分布:")
for taskType, count := range taskCount {
fmt.Printf(" - %s: %d条\n", taskType, count)
}
}
// 格式化JSON输出 cui
func formatJSON(jsonStr string) string {
var result map[string]interface{}
if err := json.Unmarshal([]byte(jsonStr), &result); err != nil {
return jsonStr // 返回原始字符串如果解析失败
}
formatted, err := json.MarshalIndent(result, " ", " ")
if err != nil {
return jsonStr
}
return string(formatted)
}
// 测试资源回收的核心函数
func testResourceCleanup(wrapper *LoggerWrapper) {
fmt.Println("🧪 开始资源回收验证测试")
// 测试配置
config := `{
"log_dir": "./resource_cleanup_test",
"level": 1,
"split_type": 1,
"max_size": 1048576,
"max_count": 3,
"enable_caller": false,
"default_task_type": "cleanup_test"
}`
// 阶段1: 创建多个logger并记录初始状态
fmt.Println("\n📝 阶段1: 创建测试logger")
activeLoggers := make([]string, 0)
idleLoggers := make([]string, 0)
// 创建6个logger3个活跃3个闲置
for i := 0; i < 6; i++ {
loggerHandle, err := wrapper.CreateLogger(config)
if err != nil {
log.Printf("创建logger %d 失败: %v", i, err)
continue
}
if i < 3 {
activeLoggers = append(activeLoggers, loggerHandle)
fmt.Printf("✅ 创建活跃logger %d: %s\n", i, loggerHandle)
} else {
idleLoggers = append(idleLoggers, loggerHandle)
fmt.Printf("✅ 创建闲置logger %d: %s\n", i, loggerHandle)
}
}
fmt.Printf("\n📊 创建统计: 活跃logger=%d, 闲置logger=%d, 总计=%d\n",
len(activeLoggers), len(idleLoggers), len(activeLoggers)+len(idleLoggers))
// 阶段2: 使用活跃logger让闲置logger保持不使用状态
fmt.Println("\n📝 阶段2: 使用活跃logger")
for i, loggerHandle := range activeLoggers {
ctxHandle, err := wrapper.CreateContextWithTaskType(loggerHandle, fmt.Sprintf("active_task_%d", i))
if err != nil {
log.Printf("创建上下文失败: %v", err)
continue
}
// 记录多条日志确保活跃状态
for j := 0; j < 5; j++ {
message := fmt.Sprintf("活跃logger %d - 消息 %d - 时间: %s", i, j, time.Now().Format("15:04:05"))
err = wrapper.LogInfo(ctxHandle, message)
if err != nil {
log.Printf("记录日志失败: %v", err)
}
}
fmt.Printf("✅ 活跃logger %d 已使用: %s\n", i, loggerHandle)
}
// 记录当前资源状态
fmt.Println("\n📊 资源使用前状态:")
monitorResources()
// 阶段3: 模拟时间流逝并验证资源回收
fmt.Println("\n⏰ 阶段3: 模拟时间流逝等待资源回收")
fmt.Println(" 自动清理机制: 每30分钟运行一次清理2小时未使用的资源")
fmt.Println(" 由于测试时间限制,我们将观察资源使用模式...")
// 多次采样资源使用情况来观察趋势
fmt.Println("\n📈 资源使用趋势观察:")
initialMemory := getMemoryUsage()
for i := 0; i < 3; i++ {
fmt.Printf("\n 采样 %d:\n", i+1)
monitorResources()
// 继续使用活跃logger以保持其活跃状态
for _, loggerHandle := range activeLoggers {
ctxHandle, err := wrapper.CreateContextWithTaskType(loggerHandle, "keep_alive")
if err == nil {
wrapper.LogInfo(ctxHandle, fmt.Sprintf("保持活跃 - 采样 %d", i+1))
}
}
time.Sleep(2 * time.Second)
}
finalMemory := getMemoryUsage()
memoryChange := finalMemory - initialMemory
fmt.Printf("\n📊 内存变化: %.2fMB\n", memoryChange)
// 阶段4: 验证闲置logger的状态
fmt.Println("\n🔍 阶段4: 验证闲置logger状态")
stillWorkingCount := 0
for i, loggerHandle := range idleLoggers {
ctxHandle, err := wrapper.CreateContextWithTaskType(loggerHandle, "test_after_idle")
if err != nil {
fmt.Printf("❌ 闲置logger %d 可能已被回收: %s -> %v\n", i, loggerHandle, err)
} else {
// 尝试记录日志
err = wrapper.LogInfo(ctxHandle, "测试闲置logger是否仍然工作")
if err != nil {
fmt.Printf("❌ 闲置logger %d 记录日志失败: %s -> %v\n", i, loggerHandle, err)
} else {
fmt.Printf("✅ 闲置logger %d 仍然工作: %s\n", i, loggerHandle)
stillWorkingCount++
}
}
}
// 阶段5: 验证活跃logger的状态
fmt.Println("\n🔍 阶段5: 验证活跃logger状态")
activeWorkingCount := 0
for i, loggerHandle := range activeLoggers {
ctxHandle, err := wrapper.CreateContextWithTaskType(loggerHandle, "test_active")
if err != nil {
fmt.Printf("❌ 活跃logger %d 异常: %s -> %v\n", i, loggerHandle, err)
} else {
err = wrapper.LogInfo(ctxHandle, "测试活跃logger是否正常工作")
if err != nil {
fmt.Printf("❌ 活跃logger %d 记录日志失败: %s -> %v\n", i, loggerHandle, err)
} else {
fmt.Printf("✅ 活跃logger %d 正常工作: %s\n", i, loggerHandle)
activeWorkingCount++
}
}
}
// 阶段6: 分析测试结果
fmt.Println("\n📋 阶段6: 资源回收测试结果分析")
fmt.Printf(" 初始创建: %d 个logger\n", len(activeLoggers)+len(idleLoggers))
fmt.Printf(" 活跃logger正常: %d/%d\n", activeWorkingCount, len(activeLoggers))
fmt.Printf(" 闲置logger仍然工作: %d/%d\n", stillWorkingCount, len(idleLoggers))
fmt.Printf(" 内存变化: %.2fMB\n", memoryChange)
// 资源回收效果评估
if stillWorkingCount < len(idleLoggers) {
fmt.Println("🎯 资源回收效果: ✅ 检测到可能的资源回收")
fmt.Println(" 说明: 部分闲置logger无法使用可能已被自动清理机制回收")
} else {
fmt.Println("🎯 资源回收效果: ⚠️ 未检测到明显的资源回收")
fmt.Println(" 说明: 所有logger仍然可用可能因为:")
fmt.Println(" - 测试时间不足以触发自动清理")
fmt.Println(" - 自动清理机制配置时间较长")
fmt.Println(" - 所有logger仍被认定为活跃状态")
}
// 阶段7: 显式清理
fmt.Println("\n🧹 阶段7: 显式清理所有资源")
result, err := wrapper.CloseAllLoggers()
if err != nil {
log.Printf("关闭所有logger失败: %v", err)
} else {
fmt.Printf("✅ %s\n", result)
}
// 最终资源状态
fmt.Println("\n📊 最终资源状态:")
monitorResources()
fmt.Println("🧪 资源回收验证测试完成")
}
func getMemoryUsage() float64 {
var m runtime.MemStats
runtime.ReadMemStats(&m)
return float64(m.Alloc) / 1024 / 1024
}
// 文件系统资源检查
func checkFileSystemResources() {
fmt.Println("\n📁 文件系统资源检查:")
// 检查日志目录
dirs := []string{"./resource_cleanup_test", "./test_logs"}
for _, dir := range dirs {
if _, err := os.Stat(dir); !os.IsNotExist(err) {
files, _ := filepath.Glob(filepath.Join(dir, "*", "*.log"))
fmt.Printf(" 目录 %s: %d 个日志文件\n", dir, len(files))
// 显示文件详情
for _, file := range files {
info, err := os.Stat(file)
if err == nil {
fmt.Printf(" - %s (大小: %.2fKB, 修改时间: %s)\n",
filepath.Base(file),
float64(info.Size())/1024,
info.ModTime().Format("15:04:05"))
}
}
} else {
fmt.Printf(" 目录 %s: 不存在\n", dir)
}
}
}
func main() {
config := `{
"log_dir": "./test_logs_reading",
"level": 1,
"split_type": 1,
"max_size": 1048576,
"max_count": 5,
"enable_caller": true,
"default_task_type": "reading_test"
}`
var configs Config
err2 := json.Unmarshal([]byte(config), &configs)
if err2 != nil {
fmt.Println(err2)
}
logger, err := NewLogger(configs)
if err != nil {
fmt.Println(err)
}
fmt.Println(logger)
fmt.Println("🚀 开始资源回收验证测试")
// 确定DLL路径
dllPath := "logger.dll"
if _, err := os.Stat(dllPath); os.IsNotExist(err) {
log.Fatalf("DLL文件不存在: %s", dllPath)
}
// 创建包装器
wrapper, err := NewLoggerWrapper(dllPath)
if err != nil {
log.Fatalf("创建日志包装器失败: %v", err)
}
defer wrapper.Close()
fmt.Println("✅ DLL加载成功")
// 初始资源状态
fmt.Println("\n📈 初始资源状态:")
monitorResources()
// 运行日志读取功能测试
testLogReadingFunctions(wrapper)
// 运行资源回收测试
testResourceCleanup(wrapper)
// 检查文件系统资源
checkFileSystemResources()
fmt.Println("\n🎉 资源回收验证完成!")
fmt.Println("\n💡 测试说明:")
fmt.Println(" - 本测试创建了活跃和闲置的logger来模拟真实使用场景")
fmt.Println(" - 通过观察闲置logger的可用性来验证自动回收机制")
fmt.Println(" - 内存使用趋势可以帮助识别资源泄漏")
fmt.Println(" - 实际自动清理需要较长时间(2小时未使用)")
}