LCOV - code coverage report
Current view: top level - felix-client/src - clog.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 48 80 60.0 %
Date: 2025-08-12 04:15:35 Functions: 7 13 53.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2020 rxi
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  * of this software and associated documentation files (the "Software"), to
       6             :  * deal in the Software without restriction, including without limitation the
       7             :  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
       8             :  * sell copies of the Software, and to permit persons to whom the Software is
       9             :  * furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      19             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
      20             :  * IN THE SOFTWARE.
      21             :  */
      22             : 
      23             : #include "clog.h"
      24             : #include <math.h>
      25             : #include <sys/time.h>
      26             : 
      27             : #define MAX_CALLBACKS 32
      28             : 
      29             : typedef struct {
      30             :   clog_LogFn fn;
      31             :   void *udata;
      32             :   int level;
      33             : } CCallback;
      34             : 
      35             : static struct {
      36             :   void *udata;
      37             :   clog_LockFn lock;
      38             :   int level;
      39             :   bool quiet;
      40             :   CCallback callbacks[MAX_CALLBACKS];
      41             : } CL;
      42             : 
      43             : 
      44             : static const char *clevel_strings[] = {
      45             :   "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"
      46             : };
      47             : 
      48             : 
      49             : #ifdef CLOG_USE_COLOR
      50             : static const char *clevel_colors[] = {
      51             :   "\x1b[35m", "\x1b[31m", "\x1b[33m", "\x1b[32m", "\x1b[36m", "\x1b[94m"
      52             : };
      53             : #endif
      54             : 
      55             : 
      56       12302 : static void cstdout_callback(clog_Event *ev) {
      57       12302 :   char buf[20];
      58       12302 :   struct timeval t;
      59       12302 :   int msec;
      60       12302 :   buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0';
      61       12302 :   gettimeofday(&t, NULL);
      62       12302 :   msec = lrint(t.tv_usec/1000.0);
      63       12302 :   char buffer[24];
      64       12302 :   snprintf(buffer, sizeof(buffer), "%s.%03d", buf, msec);
      65             : #ifdef CLOG_USE_COLOR
      66             :   fprintf(
      67             :     ev->udata, "%s %s%-5s\x1b[0m \x1b[90m%s %s:%d:\x1b[0m ",
      68             :     buffer, clevel_colors[ev->level], clevel_strings[ev->level], "client",
      69             :     ev->file, ev->line);
      70             : #else
      71       12302 :   fprintf(
      72       12302 :     ev->udata, "%s %-5s %s %s:%d: ",
      73       12302 :     buffer, clevel_strings[ev->level], "client", ev->file, ev->line);
      74             : #endif
      75       12302 :   vfprintf(ev->udata, ev->fmt, ev->ap);
      76       12302 :   fprintf(ev->udata, "\n");
      77       12302 :   fflush(ev->udata);
      78       12302 : }
      79             : 
      80             : 
      81           0 : static void cfile_callback(clog_Event *ev) {
      82           0 :   char buf[64];
      83           0 :   buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0';
      84           0 :   fprintf(
      85           0 :     ev->udata, "%s %-5s %s:%d: ",
      86           0 :     buf, clevel_strings[ev->level], ev->file, ev->line);
      87           0 :   vfprintf(ev->udata, ev->fmt, ev->ap);
      88           0 :   fprintf(ev->udata, "\n");
      89           0 :   fflush(ev->udata);
      90           0 : }
      91             : 
      92             : 
      93      114047 : static void clog_lock(void)   {
      94      114047 :   if (CL.lock) { CL.lock(true, CL.udata); }
      95      114047 : }
      96             : 
      97             : 
      98      114047 : static void clog_unlock(void) {
      99      114047 :   if (CL.lock) { CL.lock(false, CL.udata); }
     100      114047 : }
     101             : 
     102             : 
     103         419 : const char* clog_level_string(int level) {
     104         419 :   return clevel_strings[level];
     105             : }
     106             : 
     107             : 
     108           0 : void clog_set_lock(clog_LockFn fn, void *udata) {
     109           0 :   CL.lock = fn;
     110           0 :   CL.udata = udata;
     111           0 : }
     112             : 
     113             : 
     114         419 : void clog_set_level(int level) {
     115         419 :   CL.level = CLOG_INFO;
     116         419 :   clog_info("Setting log_level to %s", clog_level_string(level));
     117         419 :   CL.level = level;
     118         419 : }
     119             : 
     120           0 : int clog_level() {
     121           0 :   return CL.level;
     122             : }
     123             : 
     124           0 : void clog_set_quiet(bool enable) {
     125           0 :   CL.quiet = enable;
     126           0 : }
     127             : 
     128             : 
     129           0 : int clog_add_callback(clog_LogFn fn, void *udata, int level) {
     130           0 :   for (int i = 0; i < MAX_CALLBACKS; i++) {
     131           0 :     if (!CL.callbacks[i].fn) {
     132           0 :       CL.callbacks[i] = (CCallback) { fn, udata, level };
     133           0 :       return 0;
     134             :     }
     135             :   }
     136             :   return -1;
     137             : }
     138             : 
     139             : 
     140           0 : int clog_add_fp(FILE *fp, int level) {
     141           0 :   return clog_add_callback(cfile_callback, fp, level);
     142             : }
     143             : 
     144             : 
     145       12302 : static void cinit_event(clog_Event *ev, void *udata) {
     146       12302 :   if (!ev->time) {
     147       12302 :     time_t t = time(NULL);
     148       12302 :     ev->time = localtime(&t);
     149             :   }
     150       12302 :   ev->udata = udata;
     151       12302 : }
     152             : 
     153             : 
     154      114046 : void clog_log(int level, const char *file, int line, const char *fmt, ...) {
     155      114046 :   clog_Event ev = {
     156             :     .fmt   = fmt,
     157             :     .file  = file,
     158             :     .line  = line,
     159             :     .level = level,
     160             :   };
     161             : 
     162      114046 :   clog_lock();
     163             : 
     164      114047 :   if (!CL.quiet && level <= CL.level) {
     165       12302 :     if ( level <= CLOG_WARN){
     166         166 :       cinit_event(&ev, stderr);
     167             :     } else {
     168       12136 :       cinit_event(&ev, stdout);
     169             :     }
     170       12302 :     va_start(ev.ap, fmt);
     171       12302 :     cstdout_callback(&ev);
     172       12302 :     va_end(ev.ap);
     173             :   }
     174             : 
     175      114047 :   for (int i = 0; i < MAX_CALLBACKS && CL.callbacks[i].fn; i++) {
     176           0 :     CCallback *cb = &CL.callbacks[i];
     177           0 :     if (level <= cb->level) {
     178           0 :       cinit_event(&ev, cb->udata);
     179           0 :       va_start(ev.ap, fmt);
     180           0 :       cb->fn(&ev);
     181           0 :       va_end(ev.ap);
     182             :     }
     183             :   }
     184             : 
     185      114047 :   clog_unlock();
     186      114047 : }

Generated by: LCOV version 1.0