// log.h
#ifndef LOG_H
#define LOG_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
// 平台检测
#if defined(_WIN32) || defined(_WIN64)
#define OS_WINDOWS 1
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <windows.h>
#define open _open
#define write _write
#define close _close
#define fsync _commit
#define STDERR_FILENO 2
#else
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#endif
// 日志级别定义
typedef enum
{
LOG_DEBUG,
LOG_INFO,
LOG_WARNING,
LOG_ERROR
} LogLevel;
// 全局日志文件描述符
static int log_fd = -1;
static LogLevel log_level = LOG_INFO;
// 初始化日志系统
static int log_init(const char *filename, LogLevel level)
{
int flags = 0;
int mode = 0;
log_level = level;
if (filename == NULL)
{
log_fd = STDERR_FILENO; // 默认输出到标准错误
return 0;
}
// Windows 和 Linux 的文件打开标志处理
#ifdef OS_WINDOWS
flags = _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY;
mode = _S_IREAD | _S_IWRITE;
#else
flags = O_WRONLY | O_CREAT | O_APPEND;
mode = 0644;
#endif
// 打开日志文件
log_fd = open(filename, flags, mode);
if (log_fd < 0)
{
#ifdef OS_WINDOWS
char error[256];
strerror_s(error, sizeof(error), errno);
fprintf(stderr, "log_init failed: %s\n", error);
#else
perror("log_init failed");
#endif
return -1;
}
return 0;
}
// 关闭日志系统
static void log_close()
{
if (log_fd >= 0 && log_fd != STDERR_FILENO)
{
close(log_fd);
log_fd = -1;
}
}
// 核心日志函数
static void log_write(LogLevel level, const char *file, int line, const char *format, ...)
{
char header[256];
// 获取当前时间
time_t now = time(NULL);
struct tm tm_now;
// 日志级别字符串
const char *level_str = "UNKNOWN";
int header_len = 0;
int msg_len = 0;
char msg[1024];
char log_line[2048];
va_list args;
if (level < log_level || log_fd < 0)
return;
#ifdef OS_WINDOWS
localtime_s(&tm_now, &now);
#else
localtime_r(&now, &tm_now);
#endif
switch (level)
{
case LOG_DEBUG:
level_str = "DEBUG";
break;
case LOG_INFO:
level_str = "INFO";
break;
case LOG_WARNING:
level_str = "WARN";
break;
case LOG_ERROR:
level_str = "ERROR";
break;
}
// 构建日志头
header_len = snprintf(header, sizeof(header),
"[%04d-%02d-%02d %02d:%02d:%02d] [%s] [%s:%d] ",
tm_now.tm_year + 1900, tm_now.tm_mon + 1, tm_now.tm_mday,
tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec,
level_str, file, line);
// 处理可变参数
va_start(args, format);
msg_len = vsnprintf(msg, sizeof(msg), format, args);
va_end(args);
// 确保消息不会溢出缓冲区
if (msg_len < 0)
return;
if (msg_len >= (int)sizeof(msg))
{
msg[sizeof(msg) - 1] = '\0';
msg_len = (int)sizeof(msg) - 1;
}
// 组合完整日志
memcpy(log_line, header, header_len);
memcpy(log_line + header_len, msg, msg_len);
// 添加换行符
log_line[header_len + msg_len] = '\n';
// 写入日志
write(log_fd, log_line, header_len + msg_len + 1);
#ifndef OS_WINDOWS
// Windows 的 _commit 在 fsync 时已经调用
fsync(log_fd);
#endif
}
// 简化日志宏
#define LOG(level, ...) log_write(level, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_DEBUG(...) LOG(LOG_DEBUG, __VA_ARGS__)
#define LOG_INFO(...) LOG(LOG_INFO, __VA_ARGS__)
#define LOG_WARNING(...) LOG(LOG_WARNING, __VA_ARGS__)
#define LOG_ERROR(...) LOG(LOG_ERROR, __VA_ARGS__)
#endif // LOG_H
版权归属:
Administrator
许可协议:
本文使用《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》协议授权
评论区