Skip to content

Instantly share code, notes, and snippets.

@rlapz
Last active November 30, 2023 12:47
Show Gist options
  • Save rlapz/f40ee29c556c05fb46ae2e30565284dc to your computer and use it in GitHub Desktop.
Save rlapz/f40ee29c556c05fb46ae2e30565284dc to your computer and use it in GitHub Desktop.
simple logger
#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