Browse Source

feat: support logger_set_truncate_percent

ithewei 8 months ago
parent
commit
aa1bbc5d5e
7 changed files with 104 additions and 12 deletions
  1. 1 0
      Makefile
  2. 73 12
      base/hlog.c
  3. 3 0
      base/hlog.h
  4. 1 0
      docs/API.md
  5. 3 0
      docs/cn/hlog.md
  6. 1 0
      scripts/unittest.sh
  7. 22 0
      unittest/hlog_test.c

+ 1 - 0
Makefile

@@ -233,6 +233,7 @@ unittest: prepare
 	$(CC)  -g -Wall -O0 -std=c99   -I. -Ibase            -o bin/mkdir_p           unittest/mkdir_test.c         base/hbase.c
 	$(CC)  -g -Wall -O0 -std=c99   -I. -Ibase            -o bin/rmdir_p           unittest/rmdir_test.c         base/hbase.c
 	$(CC)  -g -Wall -O0 -std=c99   -I. -Ibase            -o bin/date              unittest/date_test.c          base/htime.c
+	$(CC)  -g -Wall -O0 -std=c99   -I. -Ibase            -o bin/hlog_test         unittest/hlog_test.c          base/hlog.c
 	$(CC)  -g -Wall -O0 -std=c99   -I. -Ibase            -o bin/hatomic_test      unittest/hatomic_test.c       -pthread
 	$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase            -o bin/hatomic_cpp_test  unittest/hatomic_test.cpp     -pthread
 	$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase            -o bin/hthread_test      unittest/hthread_test.cpp     -pthread

+ 73 - 12
base/hlog.c

@@ -1,5 +1,6 @@
 #include "hlog.h"
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -44,6 +45,7 @@ struct logger_s {
     // for file logger
     char                filepath[256];
     unsigned long long  max_filesize;
+    float               truncate_percent;
     int                 remain_days;
     int                 enable_fsync;
     FILE*               fp_;
@@ -67,6 +69,7 @@ static void logger_init(logger_t* logger) {
 
     logger->fp_ = NULL;
     logger->max_filesize = DEFAULT_LOG_MAX_FILESIZE;
+    logger->truncate_percent = DEFAULT_LOG_TRUNCATE_PERCENT;
     logger->remain_days = DEFAULT_LOG_REMAIN_DAYS;
     logger->enable_fsync = 1;
     logger_set_file(logger, DEFAULT_LOG_FILE);
@@ -146,6 +149,11 @@ void logger_set_remain_days(logger_t* logger, int days) {
     logger->remain_days = days;
 }
 
+void logger_set_truncate_percent(logger_t* logger, float percent) {
+    assert(percent <= 1.0f);
+    logger->truncate_percent = percent;
+}
+
 void logger_set_max_bufsize(logger_t* logger, unsigned int bufsize) {
     logger->bufsize = bufsize;
     logger->buf = (char*)realloc(logger->buf, bufsize);
@@ -214,6 +222,68 @@ static void logfile_name(const char* filepath, time_t ts, char* buf, int len) {
             tm->tm_mday);
 }
 
+static void logfile_truncate(logger_t* logger) {
+    // close
+    if (logger->fp_) {
+        fclose(logger->fp_);
+        logger->fp_ = NULL;
+    }
+    char tmp_logfile[sizeof(logger->cur_logfile) + 4] = {0};
+    FILE* tmpfile = NULL;
+    if (logger->truncate_percent < 1.0f) {
+        snprintf(tmp_logfile, sizeof(tmp_logfile), "%s.tmp", logger->cur_logfile);
+        tmpfile = fopen(tmp_logfile, "w");
+    }
+    if (tmpfile) {
+        // truncate percent
+        logger->fp_ = fopen(logger->cur_logfile, "r");
+        if (logger->fp_) {
+            fseek(logger->fp_, 0, SEEK_END);
+            long filesize = ftell(logger->fp_);
+            long truncate_size = (long)((double)filesize * logger->truncate_percent);
+            fseek(logger->fp_, -(filesize - truncate_size), SEEK_CUR);
+            long cur_pos = ftell(logger->fp_);
+            char buf[4096] = {0};
+            const char* pbuf = buf;
+            size_t nread = 0, nwrite = 0;
+            char find_newline = 0;
+            while ((nread = fread(buf, 1, sizeof(buf), logger->fp_)) > 0) {
+                pbuf = buf;
+                if (find_newline == 0) {
+                    while (nread > 0) {
+                        if (*pbuf == '\n') {
+                            find_newline = 1;
+                            ++pbuf;
+                            --nread;
+                            break;
+                        }
+                        ++pbuf;
+                        --nread;
+                    }
+                }
+                if (nread > 0) {
+                    nwrite += fwrite(pbuf, 1, nread, tmpfile);
+                }
+            }
+            fclose(tmpfile);
+            fclose(logger->fp_);
+            logger->fp_ = NULL;
+            remove(logger->cur_logfile);
+            rename(tmp_logfile, logger->cur_logfile);
+        }
+    } else {
+        // truncate all
+        // remove(logger->cur_logfile);
+        logger->fp_ = fopen(logger->cur_logfile, "w");
+        if (logger->fp_) {
+            fclose(logger->fp_);
+            logger->fp_ = NULL;
+        }
+    }
+    // reopen
+    logger->fp_ = fopen(logger->cur_logfile, "a");
+}
+
 static FILE* logfile_shift(logger_t* logger) {
     time_t ts_now = time(NULL);
     int interval_days = logger->last_logfile_ts == 0 ? 0 : (ts_now+s_gmtoff) / SECONDS_PER_DAY - (logger->last_logfile_ts+s_gmtoff) / SECONDS_PER_DAY;
@@ -258,17 +328,8 @@ static FILE* logfile_shift(logger_t* logger) {
         fseek(logger->fp_, 0, SEEK_END);
         long filesize = ftell(logger->fp_);
         if (filesize > logger->max_filesize) {
-            fclose(logger->fp_);
-            logger->fp_ = NULL;
-            // ftruncate
-            logger->fp_ = fopen(logger->cur_logfile, "w");
-            // reopen with O_APPEND for multi-processes
-            if (logger->fp_) {
-                fclose(logger->fp_);
-                logger->fp_ = fopen(logger->cur_logfile, "a");
-            }
-        }
-        else {
+            logfile_truncate(logger);
+        } else {
             logger->can_write_cnt = (logger->max_filesize - filesize) / logger->bufsize;
         }
     }
@@ -419,7 +480,7 @@ int logger_print(logger_t* logger, int level, const char* fmt, ...) {
         len += snprintf(buf + len, bufsize - len, "%s", CLR_CLR);
     }
 
-    if(len<bufsize) {
+    if(len < bufsize) {
         buf[len++] = '\n';
     }
 

+ 3 - 0
base/hlog.h

@@ -67,6 +67,7 @@ typedef enum {
 #define DEFAULT_LOG_REMAIN_DAYS     1
 #define DEFAULT_LOG_MAX_BUFSIZE     (1<<14)  // 16k
 #define DEFAULT_LOG_MAX_FILESIZE    (1<<24)  // 16M
+#define DEFAULT_LOG_TRUNCATE_PERCENT 0.99f   // truncate when exceeded max filesize
 
 // logger: default file_logger
 // network_logger() see event/nlog.h
@@ -113,6 +114,7 @@ HV_EXPORT void logger_set_max_filesize(logger_t* logger, unsigned long long file
 // 16, 16M, 16MB
 HV_EXPORT void logger_set_max_filesize_by_str(logger_t* logger, const char* filesize);
 HV_EXPORT void logger_set_remain_days(logger_t* logger, int days);
+HV_EXPORT void logger_set_truncate_percent(logger_t* logger, float percent);
 HV_EXPORT void logger_enable_fsync(logger_t* logger, int on);
 HV_EXPORT void logger_fsync(logger_t* logger);
 HV_EXPORT const char* logger_get_cur_file(logger_t* logger);
@@ -133,6 +135,7 @@ HV_EXPORT void      hv_destroy_default_logger(void);
 #define hlog_set_max_filesize(filesize) logger_set_max_filesize(hlog, filesize)
 #define hlog_set_max_filesize_by_str(filesize) logger_set_max_filesize_by_str(hlog, filesize)
 #define hlog_set_remain_days(days)      logger_set_remain_days(hlog, days)
+#define hlog_set_truncate_percent(val)  logger_set_truncate_percent(hlog, val)
 #define hlog_enable_fsync()             logger_enable_fsync(hlog, 1)
 #define hlog_disable_fsync()            logger_enable_fsync(hlog, 0)
 #define hlog_fsync()                    logger_fsync(hlog)

+ 1 - 0
docs/API.md

@@ -254,6 +254,7 @@
 - logger_set_max_bufsize
 - logger_set_max_filesize
 - logger_set_remain_days
+- logger_set_truncate_percent
 - logger_get_cur_file
 - hlogd, hlogi, hlogw, hloge, hlogf
 - LOGD, LOGI, LOGW, LOGE, LOGF

+ 3 - 0
docs/cn/hlog.md

@@ -64,6 +64,9 @@ void logger_set_max_filesize(logger_t* logger, unsigned long long filesize);
 // 16, 16M, 16MB
 void logger_set_max_filesize_by_str(logger_t* logger, const char* filesize);
 
+// 设置日志文件翻转截断百分比
+void logger_set_truncate_percent(logger_t* logger, float percent);
+
 // 设置日志文件保留天数
 void logger_set_remain_days(logger_t* logger, int days);
 

+ 1 - 0
scripts/unittest.sh

@@ -11,6 +11,7 @@ bin/ifconfig
 bin/mkdir_p 123/456
 bin/ls
 bin/rmdir_p 123/456
+bin/hlog_test
 
 bin/base64
 bin/md5

+ 22 - 0
unittest/hlog_test.c

@@ -0,0 +1,22 @@
+#include "hlog.h"
+
+int main(int argc, char* argv[]) {
+    char logfile[] = "hlog_test.log";
+    hlog_set_file(logfile);
+    hlog_set_level(LOG_LEVEL_INFO);
+
+    // test log max filesize
+    hlog_set_max_filesize_by_str("1M");
+    for (int i = 100000; i <= 999999; ++i) {
+        hlogi("[%d] xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", i);
+    }
+
+    // test log level
+    hlogd("%s", "not show debug");
+    hlogi("%s", "show info");
+    hlogw("%s", "show warn");
+    hloge("%s", "show error");
+    hlogf("%s", "show fatal");
+
+    return 0;
+}