Last active
November 30, 2023 12:47
-
-
Save rlapz/f40ee29c556c05fb46ae2e30565284dc to your computer and use it in GitHub Desktop.
simple logger
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdarg.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <pthread.h> | |
#include <time.h> | |
struct log { | |
pthread_mutex_t mutex; | |
char context[32]; | |
char message[128]; | |
}; | |
void log_init(struct log *self, const char fmt[], ...); | |
void log_printf(struct log *self, const char fmt[], ...); | |
void log_errorf(struct log *self, int number, const char fmt[], ...); | |
/* | |
* log | |
*/ | |
static char __datetime[32]; | |
static pthread_mutex_t __datetime_mutex = PTHREAD_MUTEX_INITIALIZER; | |
static void | |
__cstr_copy(char dest[], size_t size, const char src[]) | |
{ | |
size_t i = 0; | |
for (; (i < size) && (src[i] != '\0'); i++) | |
dest[i] = src[i]; | |
dest[i] = '\0'; | |
} | |
static const char * | |
__datetime_now(char dest[], size_t size) | |
{ | |
size_t len = 0; | |
time_t tm_raw; | |
struct tm *tm; | |
pthread_mutex_lock(&__datetime_mutex); /* LOCK */ | |
tm_raw = time(NULL); | |
tm = localtime(&tm_raw); | |
if (tm == NULL) | |
goto out0; | |
const char *const res = asctime(tm); | |
if (res == NULL) | |
goto out0; | |
const size_t res_len = strlen(res); | |
if (res_len == 0) | |
goto out0; | |
__cstr_copy(dest, size, res); | |
len = res_len - 1; | |
out0: | |
dest[len] = '\0'; | |
pthread_mutex_unlock(&__datetime_mutex); /* UNLOCK */ | |
return dest; | |
} | |
void | |
log_init(struct log *self, const char fmt[], ...) | |
{ | |
int ret; | |
va_list va; | |
const size_t size = sizeof(self->context); | |
va_start(va, fmt); | |
ret = vsnprintf(self->context, size, fmt, va); | |
va_end(va); | |
if (ret < 0) | |
self->context[0] = '\0'; | |
if ((size_t)ret >= size) | |
__cstr_copy(&self->context[size - 4], 4, "..."); | |
self->message[0] = '\0'; | |
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | |
self->mutex = mutex; | |
} | |
void | |
log_printf(struct log *self, const char fmt[], ...) | |
{ | |
int ret; | |
va_list va; | |
const size_t size = sizeof(self->message); | |
pthread_mutex_lock(&self->mutex); /* LOCK */ | |
va_start(va, fmt); | |
ret = vsnprintf(self->message, size, fmt, va); | |
va_end(va); | |
if (ret < 0) | |
self->message[0] = '\0'; | |
if ((size_t)ret >= size) | |
__cstr_copy(&self->message[size - 4], 4, "..."); | |
const char *const datetime_now = __datetime_now(__datetime, sizeof(__datetime)); | |
printf("%s: %s: %s\n", datetime_now, self->context, self->message); | |
pthread_mutex_unlock(&self->mutex); /* UNLOCK */ | |
} | |
void | |
log_errorf(struct log *self, int number, const char fmt[], ...) | |
{ | |
int ret; | |
va_list va; | |
const size_t size = sizeof(self->message); | |
pthread_mutex_lock(&self->mutex); /* LOCK */ | |
va_start(va, fmt); | |
ret = vsnprintf(self->message, size, fmt, va); | |
va_end(va); | |
if (ret < 0) | |
self->message[0] = '\0'; | |
if ((size_t)ret >= size) | |
__cstr_copy(&self->message[size - 4], 4, "..."); | |
const char *const datetime_now = __datetime_now(__datetime, sizeof(__datetime)); | |
if (number == 0) { | |
fprintf(stderr, "%s: %s: %s\n", datetime_now, self->context, | |
self->message); | |
} else { | |
fprintf(stderr, "%s: %s: %s: %s\n", datetime_now, self->context, | |
self->message, strerror(abs(number))); | |
} | |
pthread_mutex_unlock(&self->mutex); /* UNLOCK */ | |
} | |
/* | |
* main | |
*/ | |
int | |
main(void) | |
{ | |
struct log l; | |
log_init(&l, "main a"); | |
log_printf(&l, "test aaa"); | |
log_errorf(&l, 1,"test bbb"); | |
struct log ll; | |
log_init(&ll, "main b loooooooooooooooooooooooooooooooooooooooooooooong"); | |
log_printf(&ll, __func__); | |
log_errorf(&ll, 1, | |
"test looooooooooooooooooooooooooooooooooooooooooooooooooooo" | |
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" | |
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" | |
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" | |
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" | |
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"); | |
log_printf(&ll, "test cccc"); | |
struct log lll; | |
log_init(&lll, __FUNCTION__); | |
log_printf(&lll, "test aaa"); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment