hlog.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include "hlog.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdarg.h>
  5. #include <mutex>
  6. #include "htime.h" // for get_datetime
  7. #define SECONDS_PER_DAY 86400
  8. static char s_logfile[256] = DEFAULT_LOG_FILE;
  9. static int s_loglevel = DEFAULT_LOG_LEVEL;
  10. static bool s_logcolor = false;
  11. static int s_remain_days = DEFAULT_LOG_REMAIN_DAYS;
  12. static char s_logbuf[LOG_BUFSIZE];
  13. static std::mutex s_mutex;
  14. static void ts_logfile(time_t ts, char* buf, int len) {
  15. struct tm* tm = localtime(&ts);
  16. snprintf(buf, len, "%s-%04d-%02d-%02d.log",
  17. s_logfile,
  18. tm->tm_year+1900,
  19. tm->tm_mon+1,
  20. tm->tm_mday);
  21. }
  22. static FILE* shift_logfile() {
  23. static FILE* s_logfp = NULL;
  24. static char s_cur_logfile[256] = {0};
  25. static time_t s_last_logfile_ts = time(NULL);
  26. time_t ts_now = time(NULL);
  27. int interval_days = ts_now / SECONDS_PER_DAY - s_last_logfile_ts / SECONDS_PER_DAY;
  28. if (s_logfp == NULL || interval_days > 0) {
  29. // close old logfile
  30. if (s_logfp) {
  31. fclose(s_logfp);
  32. s_logfp = NULL;
  33. }
  34. else {
  35. interval_days = 30;
  36. }
  37. if (interval_days >= s_remain_days) {
  38. // remove [today-interval_days, today-s_remain_days] logfile
  39. char rm_logfile[256] = {0};
  40. for (int i = interval_days; i >= s_remain_days; --i) {
  41. time_t ts_rm = ts_now - i * SECONDS_PER_DAY;
  42. ts_logfile(ts_rm, rm_logfile, sizeof(rm_logfile));
  43. remove(rm_logfile);
  44. }
  45. }
  46. else {
  47. // remove today-s_remain_days logfile
  48. char rm_logfile[256] = {0};
  49. time_t ts_rm = ts_now - s_remain_days * SECONDS_PER_DAY;
  50. ts_logfile(ts_rm, rm_logfile, sizeof(rm_logfile));
  51. remove(rm_logfile);
  52. }
  53. }
  54. // open today logfile
  55. if (s_logfp == NULL) {
  56. ts_logfile(ts_now, s_cur_logfile, sizeof(s_cur_logfile));
  57. s_logfp = fopen(s_cur_logfile, "a"); // note: append-mode for multi-processes
  58. s_last_logfile_ts = ts_now;
  59. }
  60. // rewrite if too big
  61. if (s_logfp && ftell(s_logfp) > MAX_LOG_FILESIZE) {
  62. fclose(s_logfp);
  63. s_logfp = NULL;
  64. s_logfp = fopen(s_cur_logfile, "w");
  65. }
  66. return s_logfp;
  67. }
  68. int hlog_set_file(const char* logfile) {
  69. if (logfile == NULL || strlen(logfile) == 0) return -10;
  70. strncpy(s_logfile, logfile, sizeof(s_logfile));
  71. // remove suffix .log
  72. char* suffix = strrchr(s_logfile, '.');
  73. if (suffix && strcmp(suffix, ".log") == 0) {
  74. *suffix = '\0';
  75. }
  76. return 0;
  77. }
  78. void hlog_set_level(int level) {
  79. s_loglevel = level;
  80. }
  81. void hlog_set_remain_days(int days) {
  82. s_remain_days = days;
  83. }
  84. void hlog_enable_color(int on) {
  85. s_logcolor = on;
  86. }
  87. int hlog_printf(int level, const char* fmt, ...) {
  88. if (level < s_loglevel)
  89. return -10;
  90. const char* pcolor = "";
  91. const char* plevel = "";
  92. #define CASE_LOG(id, str, clr) \
  93. case id: plevel = str; pcolor = clr; break;
  94. switch (level) {
  95. FOREACH_LOG(CASE_LOG)
  96. }
  97. #undef CASE_LOG
  98. std::lock_guard<std::mutex> locker(s_mutex);
  99. FILE* fp = shift_logfile();
  100. if (fp == NULL) {
  101. return -20;
  102. }
  103. datetime_t now = get_datetime();
  104. int len = snprintf(s_logbuf, LOG_BUFSIZE, "[%04d-%02d-%02d %02d:%02d:%02d.%03d][%s]: ",
  105. now.year, now.month, now.day, now.hour, now.min, now.sec, now.ms, plevel);
  106. va_list ap;
  107. va_start(ap, fmt);
  108. len += vsnprintf(s_logbuf + len, LOG_BUFSIZE-len, fmt, ap);
  109. va_end(ap);
  110. if (s_logcolor) {
  111. fprintf(fp, "%s%s%s\n", pcolor, s_logbuf, CL_CLR);
  112. }
  113. else {
  114. fprintf(fp, "%s\n", s_logbuf);
  115. }
  116. fflush(fp); // note: fflush cache page => disk, slow
  117. return len;
  118. }