Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancements #7

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 131 additions & 82 deletions src/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,112 +25,161 @@
#include <stdarg.h>
#include <string.h>
#include <time.h>

#include "log.h"

static struct {
void *udata;
log_LockFn lock;
FILE *fp;
int level;
int quiet;
#include <sys/time.h>

static struct
{
void *udata;
log_LockFn lock;
FILE *fp;
int console_level;
int file_level;
int quiet;
} L;

static void time_to_str(char *);

static int year;
static int month;
static int day;
static int hour;
static int minutes;
static int seconds;
static int usec;

static const char *level_names[] = {
"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
};
char time_string[25];

static struct timeval tv;
static struct tm *tm;

#ifdef LOG_USE_COLOR
static const char *level_colors[] = {
"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"
};
"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"};
#endif


static void lock(void) {
if (L.lock) {
L.lock(L.udata, 1);
}
const char *getLevelName(int level)
{
if (level >= MIN_LOG_LEVEL && level <= MAX_LOG_LEVEL)
return level_names[level];
else
return "INVALID LOG LEVEL";
}


static void unlock(void) {
if (L.lock) {
L.lock(L.udata, 0);
}
static void lock(void)
{
if (L.lock)
{
L.lock(L.udata, 1);
}
}


void log_set_udata(void *udata) {
L.udata = udata;
static void unlock(void)
{
if (L.lock)
{
L.lock(L.udata, 0);
}
}


void log_set_lock(log_LockFn fn) {
L.lock = fn;
void log_set_udata(void *udata)
{
L.udata = udata;
}


void log_set_fp(FILE *fp) {
L.fp = fp;
void log_set_lock(log_LockFn fn)
{
L.lock = fn;
}


void log_set_level(int level) {
L.level = level;
void log_set_fp(FILE *fp)
{
L.fp = fp;
}


void log_set_quiet(int enable) {
L.quiet = enable ? 1 : 0;
void log_set_console_level(int level)
{
L.console_level = level;
}

void log_set_file_level(int level)
{
L.file_level = level;
}

void log_log(int level, const char *file, int line, const char *fmt, ...) {
if (level < L.level) {
return;
}

/* Acquire lock */
lock();
void log_set_quiet(int enable)
{
L.quiet = enable ? 1 : 0;
}

/* Get current time */
time_t t = time(NULL);
struct tm *lt = localtime(&t);
void log_log(int level, const char *file, int line, const char *fmt, ...)
{
if (level < L.console_level && level < L.file_level)
{
return;
}

/* Acquire lock */
lock();
time_to_str(time_string);
/* Log to stderr */
if (!L.quiet && level >= L.console_level)
{
va_list args;

#ifdef LOG_USE_COLOR
fprintf(
stderr, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ",
time_string, level_colors[level], level_names[level], file, line);
#else
fprintf(stderr, "%s %-5s %s:%d: ", time_string, level_names[level], file, line);
#endif
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n");
fflush(stderr);
}

/* Log to file */
if (L.fp && level >= L.file_level)
{
va_list args;
fprintf(L.fp, "%s %-5s %s:%d: ", time_string, level_names[level], file, line);
va_start(args, fmt);
vfprintf(L.fp, fmt, args);
va_end(args);
fprintf(L.fp, "\n");
fflush(L.fp);
}

/* Release lock */
unlock();
}

/* Log to stderr */
if (!L.quiet) {
va_list args;
char buf[16];
buf[strftime(buf, sizeof(buf), "%H:%M:%S", lt)] = '\0';
#ifdef LOG_USE_COLOR
fprintf(
stderr, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ",
buf, level_colors[level], level_names[level], file, line);
#else
fprintf(stderr, "%s %-5s %s:%d: ", buf, level_names[level], file, line);
#endif
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n");
fflush(stderr);
}

/* Log to file */
if (L.fp) {
va_list args;
char buf[32];
buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", lt)] = '\0';
fprintf(L.fp, "%s %-5s %s:%d: ", buf, level_names[level], file, line);
va_start(args, fmt);
vfprintf(L.fp, fmt, args);
va_end(args);
fprintf(L.fp, "\n");
fflush(L.fp);
}

/* Release lock */
unlock();
/* Write time to buf in format YYYY-MM-DD HH:MM:SS.ms */
static void time_to_str(char *buf)
{
gettimeofday(&tv, NULL);
tm = localtime(&tv.tv_sec);
/* Add 1900 to get the right year value read the manual page for localtime() */
year = tm->tm_year + 1900;
/* Months are 0 indexed in struct tm */
month = tm->tm_mon + 1;
day = tm->tm_mday;
hour = tm->tm_hour;
minutes = tm->tm_min;
seconds = tm->tm_sec;
usec = tv.tv_usec;
// msec
// buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", lt)] = '\0';
int len = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%06d ",
year,
month,
day,
hour,
minutes,
seconds,
usec);
buf[len] = '\0';
}
11 changes: 10 additions & 1 deletion src/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
#include <stdio.h>
#include <stdarg.h>

#define MIN_LOG_LEVEL 0 // TRACE
#define MAX_LOG_LEVEL 5 // FATAL
static const char *level_names[] = {
"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
};

#define LOG_VERSION "0.1.0"

typedef void (*log_LockFn)(void *udata, int lock);
Expand All @@ -27,9 +33,12 @@ enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };
void log_set_udata(void *udata);
void log_set_lock(log_LockFn fn);
void log_set_fp(FILE *fp);
void log_set_level(int level);
void log_set_console_level(int level);
void log_set_file_level(int level);
void log_set_quiet(int enable);

void log_log(int level, const char *file, int line, const char *fmt, ...);

const char* getLevelName(int level);

#endif