logging changed to spdlog

This commit is contained in:
d1str4ught
2025-09-22 04:14:59 +02:00
parent 37b15a7a98
commit 4f75aa1acd
201 changed files with 33830 additions and 637 deletions

View File

@@ -1,452 +1,109 @@
#include "stdafx.h"
#include "log.h"
#ifndef OS_WINDOWS
#define SYSLOG_FILENAME "syslog"
#define SYSERR_FILENAME "syserr"
#define PTS_FILENAME "PTS"
#include <cstdarg>
#include <fstream>
#include <filesystem>
#include <chrono>
#include <iomanip>
#include <ctime>
#include <spdlog/spdlog.h>
#include <spdlog/async.h>
#include <spdlog/sinks/basic_file_sink.h>
#include "syslog_rotate_sink.h"
constexpr size_t LOGGER_QUEUE_SIZE = (1 << 14);
constexpr size_t LOGGER_NUM_THREADS = 1;
static std::shared_ptr<spdlog::logger> g_syslog;
static std::shared_ptr<spdlog::logger> g_syserr;
static bool g_bLogInitialized = false;
void log_init()
{
if (g_bLogInitialized)
return;
spdlog::init_thread_pool(LOGGER_QUEUE_SIZE, LOGGER_NUM_THREADS);
auto syslog_sink = std::make_shared<syslog_rotate_sink>();
syslog_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v");
g_syslog = std::make_shared<spdlog::async_logger>(
"syslog",
syslog_sink,
spdlog::thread_pool(),
spdlog::async_overflow_policy::block);
spdlog::register_logger(g_syslog);
auto syserr_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("syserr.log", true);
syserr_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%!()] %v");
g_syserr = std::make_shared<spdlog::async_logger>(
"syserr",
syserr_sink,
spdlog::thread_pool(),
spdlog::async_overflow_policy::block);
spdlog::register_logger(g_syserr);
#ifdef _DEBUG
g_syslog->set_level(spdlog::level::debug);
#else
#define SYSLOG_FILENAME "syslog.txt"
#define SYSERR_FILENAME "syserr.txt"
#define PTS_FILENAME "PTS.txt"
g_syslog->set_level(spdlog::level::info);
#endif
typedef struct log_file_s * LPLOGFILE;
typedef struct log_file_s LOGFILE;
spdlog::flush_every(std::chrono::seconds(1));
struct log_file_s
{
char* filename;
FILE* fp;
std::atexit([]() { log_destroy(); });
int last_hour;
int last_day;
};
LPLOGFILE log_file_sys = NULL;
LPLOGFILE log_file_err = NULL;
LPLOGFILE log_file_pt = NULL;
static char log_dir[32] = { 0, };
unsigned int log_keep_days = 3;
// Internal functions
LPLOGFILE log_file_init(const char* filename, const char *openmode);
void log_file_destroy(LPLOGFILE logfile);
void log_file_rotate(LPLOGFILE logfile);
void log_file_check(LPLOGFILE logfile);
void log_file_set_dir(const char *dir);
static unsigned int log_level_bits = 0;
void log_set_level(unsigned int bit)
{
log_level_bits |= bit;
g_bLogInitialized = true;
}
void log_unset_level(unsigned int bit)
void log_destroy()
{
log_level_bits &= ~bit;
if (!g_bLogInitialized)
return;
spdlog::shutdown();
g_bLogInitialized = false;
}
void log_set_expiration_days(unsigned int days)
void _sys_err(std::string_view str, const std::source_location& src_loc)
{
log_keep_days = days;
spdlog::source_loc loc;
loc.funcname = src_loc.function_name();
loc.line = src_loc.line();
loc.filename = src_loc.file_name();
g_syserr->log(loc, spdlog::level::err, str);
}
int log_get_expiration_days(void)
void _sys_log(int level, std::string_view str)
{
return log_keep_days;
}
int log_init(void)
{
log_file_set_dir("./log");
do
spdlog::level::level_enum lvl = spdlog::level::info;
switch (level)
{
log_file_sys = log_file_init(SYSLOG_FILENAME, "a+");
if( NULL == log_file_sys ) break;
log_file_err = log_file_init(SYSERR_FILENAME, "a+");
if( NULL == log_file_err ) break;
log_file_pt = log_file_init(PTS_FILENAME, "w");
if( NULL == log_file_pt ) break;
return true;
case 1: lvl = spdlog::level::debug; break;
case 2: lvl = spdlog::level::trace; break;
case 3: lvl = spdlog::level::trace; break;
default: lvl = spdlog::level::info; break;
}
while( false );
return false;
g_syslog->log(lvl, str);
}
void log_destroy(void)
{
log_file_destroy(log_file_sys);
log_file_destroy(log_file_err);
log_file_destroy(log_file_pt);
log_file_sys = NULL;
log_file_err = NULL;
log_file_pt = NULL;
}
void log_rotate(void)
{
log_file_check(log_file_sys);
log_file_check(log_file_err);
log_file_check(log_file_pt);
log_file_rotate(log_file_sys);
}
#ifndef OS_WINDOWS
void _sys_err(const char *func, int line, const char *format, ...)
std::string_view _format(std::string_view fmt, ...)
{
constexpr int BUFFER_SIZE = 4096;
thread_local char buffer[BUFFER_SIZE + 1];
va_list args;
time_t ct = time(0);
char *time_s = asctime(localtime(&ct));
char buf[1024 + 2]; // \n을 붙이기 위해..
int len;
if (!log_file_err)
return;
time_s[strlen(time_s) - 1] = '\0';
len = snprintf(buf, 1024, "SYSERR: %-15.15s :: %s: ", time_s + 4, func);
buf[1025] = '\0';
if (len < 1024)
{
va_start(args, format);
vsnprintf(buf + len, 1024 - len, format, args);
va_end(args);
}
strcat(buf, "\n");
// log_file_err 에 출력
fputs(buf, log_file_err->fp);
fflush(log_file_err->fp);
// log_file_sys 에도 출력
fputs(buf, log_file_sys->fp);
fflush(log_file_sys->fp);
}
#else
void _sys_err(const char *func, int line, const char *format, ...)
{
va_list args;
time_t ct = time(0);
char *time_s = asctime(localtime(&ct));
char buf[1024 + 2]; // \n을 붙이기 위해..
int len;
if (!log_file_err)
return;
time_s[strlen(time_s) - 1] = '\0';
len = snprintf(buf, 1024, "SYSERR: %-15.15s :: %s: ", time_s + 4, func);
buf[1025] = '\0';
if (len < 1024)
{
va_start(args, format);
vsnprintf(buf + len, 1024 - len, format, args);
va_end(args);
}
strcat(buf, "\n");
// log_file_err 에 출력
fputs(buf, log_file_err->fp);
fflush(log_file_err->fp);
// log_file_sys 에도 출력
fputs(buf, log_file_sys->fp);
fflush(log_file_sys->fp);
fputs(buf, stdout);
fflush(stdout);
}
#endif
static char sys_log_header_string[33] = { 0, };
void sys_log_header(const char *header)
{
strncpy(sys_log_header_string, header, 32);
}
void sys_log(unsigned int bit, const char *format, ...)
{
va_list args;
if (bit != 0 && !(log_level_bits & bit))
return;
if (log_file_sys)
{
time_t ct = time(0);
char *time_s = asctime(localtime(&ct));
fprintf(log_file_sys->fp, sys_log_header_string);
time_s[strlen(time_s) - 1] = '\0';
fprintf(log_file_sys->fp, "%-15.15s :: ", time_s + 4);
va_start(args, format);
vfprintf(log_file_sys->fp, format, args);
va_end(args);
fputc('\n', log_file_sys->fp);
fflush(log_file_sys->fp);
}
#ifndef OS_WINDOWS
// log_level이 1 이상일 경우에는 테스트일 경우가 많으니 stdout에도 출력한다.
if (log_level_bits > 1)
{
#endif
fprintf(stdout, sys_log_header_string);
va_start(args, format);
vfprintf(stdout, format, args);
va_end(args);
fputc('\n', stdout);
fflush(stdout);
#ifndef OS_WINDOWS
}
#endif
}
void pt_log(const char *format, ...)
{
va_list args;
if (!log_file_pt)
return;
va_start(args, format);
vfprintf(log_file_pt->fp, format, args);
va_start(args, fmt);
int len = vsnprintf(buffer, BUFFER_SIZE, fmt.data(), args);
va_end(args);
fputc('\n', log_file_pt->fp);
fflush(log_file_pt->fp);
}
LPLOGFILE log_file_init(const char * filename, const char * openmode)
{
LPLOGFILE logfile;
FILE * fp;
struct tm curr_tm;
time_t time_s;
time_s = time(0);
curr_tm = *localtime(&time_s);
fp = fopen(filename, openmode);
if (!fp)
return NULL;
logfile = (LPLOGFILE) malloc(sizeof(LOGFILE));
logfile->filename = strdup(filename);
logfile->fp = fp;
logfile->last_hour = curr_tm.tm_hour;
logfile->last_day = curr_tm.tm_mday;
return (logfile);
}
void log_file_destroy(LPLOGFILE logfile)
{
if (logfile == NULL) {
return;
}
if (logfile->filename)
{
free(logfile->filename);
logfile->filename = NULL;
}
if (logfile->fp)
{
fclose(logfile->fp);
logfile->fp = NULL;
}
free(logfile);
}
void log_file_check(LPLOGFILE logfile)
{
struct stat sb;
// 파일이 없으므로 다시 연다.
if (stat(logfile->filename, &sb) != 0 && errno == ENOENT)
{
fclose(logfile->fp);
logfile->fp = fopen(logfile->filename, "a+");
}
}
void log_file_delete_old(const char *filename)
{
struct stat sb;
int num1, num2;
char buf[32];
char system_cmd[64];
struct tm new_tm;
if (stat(filename, &sb) == -1)
{
perror("log_file_delete_old: stat");
return;
}
if (!S_ISDIR(sb.st_mode))
return;
new_tm = *tm_calc(NULL, -log_keep_days);
sprintf(buf, "%04d%02d%02d", new_tm.tm_year + 1900, new_tm.tm_mon + 1, new_tm.tm_mday);
num1 = atoi(buf);
#ifndef OS_WINDOWS
{
struct dirent ** namelist;
int n;
n = scandir(filename, &namelist, 0, alphasort);
if (n < 0)
perror("scandir");
else
{
char name[MAXNAMLEN+1];
while (n-- > 0)
{
strncpy(name, namelist[n]->d_name, 255);
name[255] = '\0';
free(namelist[n]);
if (*name == '.')
continue;
if (!isdigit(*name))
continue;
num2 = atoi(name);
if (num2 <= num1)
{
sprintf(system_cmd, "rm -rf %s/%s", filename, name);
system(system_cmd);
sys_log(0, "%s: SYSTEM_CMD: %s", __FUNCTION__, system_cmd);
fprintf(stderr, "%s: SYSTEM_CMD: %s %s:%d %s:%d\n", __FUNCTION__, system_cmd, buf, num1, name, num2);
}
}
}
free(namelist);
}
#else
{
WIN32_FIND_DATA fdata;
HANDLE hFind;
if ((hFind = FindFirstFile(filename, &fdata)) != INVALID_HANDLE_VALUE)
{
do
{
if (!isdigit(*fdata.cFileName))
continue;
num2 = atoi(fdata.cFileName);
if (num2 <= num1)
{
sprintf(system_cmd, "del %s\\%s", filename, fdata.cFileName);
system(system_cmd);
sys_log(0, "SYSTEM_CMD: %s", system_cmd);
}
}
while (FindNextFile(hFind, &fdata));
}
}
#endif
}
void log_file_rotate(LPLOGFILE logfile)
{
struct tm curr_tm;
time_t time_s;
char dir[128];
char system_cmd[128];
time_s = time(0);
curr_tm = *localtime(&time_s);
if (curr_tm.tm_mday != logfile->last_day)
{
struct tm new_tm;
new_tm = *tm_calc(&curr_tm, -3);
#ifndef OS_WINDOWS
sprintf(system_cmd, "rm -rf %s/%04d%02d%02d", log_dir, new_tm.tm_year + 1900, new_tm.tm_mon + 1, new_tm.tm_mday);
#else
sprintf(system_cmd, "del %s\\%04d%02d%02d", log_dir, new_tm.tm_year + 1900, new_tm.tm_mon + 1, new_tm.tm_mday);
#endif
system(system_cmd);
sys_log(0, "SYSTEM_CMD: %s", system_cmd);
logfile->last_day = curr_tm.tm_mday;
}
if (curr_tm.tm_hour != logfile->last_hour)
{
struct stat stat_buf;
snprintf(dir, 128, "%s/%04d%02d%02d", log_dir, curr_tm.tm_year + 1900, curr_tm.tm_mon + 1, curr_tm.tm_mday);
if (stat(dir, &stat_buf) != 0 || S_ISDIR(stat_buf.st_mode))
{
#ifdef OS_WINDOWS
CreateDirectory(dir, NULL);
#else
mkdir(dir, S_IRWXU);
#endif
}
sys_log(0, "SYSTEM: LOG ROTATE (%04d-%02d-%02d %d)",
curr_tm.tm_year + 1900, curr_tm.tm_mon + 1, curr_tm.tm_mday, logfile->last_hour);
// 로그 파일을 닫고
fclose(logfile->fp);
// 옮긴다.
#ifndef OS_WINDOWS
snprintf(system_cmd, 128, "mv %s %s/%s.%02d", logfile->filename, dir, logfile->filename, logfile->last_hour);
#else
snprintf(system_cmd, 128, "move %s %s\\%s.%02d", logfile->filename, dir, logfile->filename, logfile->last_hour);
#endif
system(system_cmd);
// 마지막 저장시간 저장
logfile->last_hour = curr_tm.tm_hour;
// 로그 파일을 다시 연다.
logfile->fp = fopen(logfile->filename, "a+");
}
}
void log_file_set_dir(const char *dir)
{
strcpy(log_dir, dir);
log_file_delete_old(log_dir);
return { buffer, (std::string_view::size_type) std::clamp(len, 0, BUFFER_SIZE) };
}