feat: add simple logging library

This commit is contained in:
2024-08-03 09:21:21 +02:00
parent 6c3ad9ffa5
commit 9d1408c174
8 changed files with 167 additions and 24 deletions

View File

@ -4,24 +4,37 @@
#include <getopt.h>
#include "cli.h"
struct cli_options new_options() {
struct cli_options result;
cli_options new_options() {
cli_options result;
result.file.has_value = false;
result.file.value = NULL;
result.verbosity = 1;
result.help = false;
result.version = false;
char *no_color = getenv("NO_COLOR");
bool color = true;
if(no_color != NULL && no_color[0] != '\0')
color = false;
result.use_colors = color;
result.log_file.has_value = false;
result.log_file.value = NULL;
return result;
}
void free_options(struct cli_options v) {
void free_options(cli_options v) {
if(v.file.has_value)
free(v.file.value);
}
// <max
const char* optstring = "f:v:hV";
const char* optstring = "f:v:Cl:hV";
const char* help_msg =
"Usage: %s [-v level] [-h] [-V]\n"
"Usage: %s [-v level] [-C] [-l file] [-h] [-V]\n"
"\n"
SCI_DESCRIPTION "\n"
"\n"
@ -30,7 +43,9 @@ const char* help_msg =
"\n"
"OPTIONS:\n"
" -f file set file\n"
" -v level Set verbosity level [0-3]\n"
" -v level Set verbosity level [0-4]\n"
" -C Force color output, ignoring $NO_COLOR\n"
" -l file Set log to output to a file\n"
" -h Show this message and exit\n"
" -V Show version and exit\n"
;
@ -40,8 +55,8 @@ void print_help(FILE * out, char* prog_name) {
fprintf(out, help_msg, prog_name);
}
struct cli_options parse(int argc, char** argv) {
struct cli_options options = new_options();
cli_options parse(int argc, char** argv) {
cli_options options = new_options();
int opt;
while((opt = getopt(argc, argv, optstring)) != -1) {
switch(opt) {
@ -52,6 +67,13 @@ struct cli_options parse(int argc, char** argv) {
case 'v':
options.verbosity = atoi(optarg);
break;
case 'C':
options.use_colors = true;
break;
case 'l':
options.log_file.value = strdup(optarg);
options.log_file.has_value = true;
break;
case 'V':
options.version = true;
break;

78
src/log.c Normal file
View File

@ -0,0 +1,78 @@
#include "log.h"
#include <stdbool.h>
#include <assert.h>
#include <time.h>
log_settings g_log_settings;
bool g_log_initialized = false;
void log_init(log_settings settings) {
g_log_settings.level = settings.level;
g_log_settings.use_colors = settings.use_colors;
g_log_settings.out_file = settings.out_file;
g_log_initialized = true;
}
#define COLOR_TRACE "\x1b[94m"
#define COLOR_INFO "\x1b[32m"
#define COLOR_WARN "\x1b[33m"
#define COLOR_ERROR "\x1b[31m"
#define COLOR_RESET "\x1b[0m"
#define COLOR_FILE "\x1b[90m"
const char* get_level_color(int level) {
switch(level) {
case LOG_TRACE:
return COLOR_TRACE;
case LOG_INFO:
return COLOR_INFO;
case LOG_WARN:
return COLOR_WARN;
case LOG_ERROR:
return COLOR_ERROR;
default:
return COLOR_INFO;
}
}
const char* get_level_name(int level) {
switch(level) {
case LOG_TRACE:
return "TRACE";
case LOG_INFO:
return "INFO";
case LOG_WARN:
return "WARN";
case LOG_ERROR:
return "ERROR";
default:
return "LOG";
}
}
struct tm* g_log_tm = NULL;
void log_log(const char* file, int line, int level, const char* fmt, ...) {
if(level > g_log_settings.level)
return;
char timestamp[16];
if(g_log_tm == NULL) {
time_t t = time(NULL);
g_log_tm = localtime(&t);
}
strftime(timestamp, sizeof(timestamp), "%H:%M:%S", g_log_tm);
const char* level_color = get_level_color(level);
const char* level_name = get_level_name(level);
if(g_log_settings.use_colors)
fprintf(g_log_settings.out_file, "%s %s%-5s"COLOR_RESET" "COLOR_FILE"%s:%d:"COLOR_RESET" ", timestamp,
level_color, level_name, file, line);
else
fprintf(g_log_settings.out_file, "%s %-5s %s:%d: ", timestamp, level_name, file, line);
va_list args;
va_start(args, format);
vfprintf(g_log_settings.out_file, fmt, args);
va_end(args);
fprintf(g_log_settings.out_file, "\n");
fflush(g_log_settings.out_file);
}

View File

@ -1,19 +1,29 @@
#include "cli.h"
#include "log.h"
#include "notify.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void on_notify_event(struct inotify_event* const e) {
fprintf(stdout, "got an event:\n");
fprintf(stdout, " wd: %d\n", e->wd);
fprintf(stdout, " mask: %d\n", e->mask);
fprintf(stdout, " cookie: %d\n", e->cookie);
fprintf(stdout, " len: %d\n", e->len);
fprintf(stdout, " name: %s\n", e->name);
void on_event(struct inotify_event* const e) {
const char* msg =
"got an event:\n"
" wd: %d\n"
" mask: %d\n"
" cookie: %d\n"
" len: %d\n"
" name: %s"
;
log_info(msg, e->wd, e->mask, e->cookie, e->len, e->name);
}
int main(int argc, char** argv) {
struct cli_options args = parse(argc, argv);
cli_options args = parse(argc, argv);
log_settings settings;
settings.level = args.verbosity;
settings.use_colors = args.use_colors;
settings.out_file = args.log_file.has_value ? fopen(args.log_file.value, "w+") : stdout;
log_init(settings);
if(args.help) {
print_help(stdout, argv[0]);
@ -30,7 +40,7 @@ int main(int argc, char** argv) {
fprintf(stderr, "no such file or directory %s\n", args.file.value);
exit(EXIT_FAILURE);
}
listen_for_changes(args.file.value, &on_notify_event);
listen_for_changes(args.file.value, &on_event);
}
free_options(args);

View File

@ -1,5 +1,6 @@
#include "notify.h"
#include "util.h"
#include "log.h"
#define EV_SIZE sizeof(struct inotify_event)
#define BUF_LEN EV_SIZE * 32
@ -9,7 +10,7 @@ void listen_for_changes(const char* filename, notify_callback callback) {
ASSERT_SYSCALL_SUCCESS(fd);
inotify_add_watch(fd, filename, IN_ATTRIB);
fprintf(stdout, "listening for changes in file: %s\n", filename);
log_info("listening for changes in file: %s", filename);
char buffer[BUF_LEN];
int r = read(fd, buffer, BUF_LEN);