diff options
| author | allusive-dev <[email protected]> | 2023-09-19 17:46:20 +1000 |
|---|---|---|
| committer | allusive-dev <[email protected]> | 2023-09-19 17:46:20 +1000 |
| commit | 5650d887357bf2a3fac8c5fd4f467bf8795b5fc4 (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/log.c | |
| parent | Update picom.sample.conf (diff) | |
| download | compfy-5650d887357bf2a3fac8c5fd4f467bf8795b5fc4.tar.xz compfy-5650d887357bf2a3fac8c5fd4f467bf8795b5fc4.zip | |
reset
Diffstat (limited to 'src/log.c')
| -rw-r--r-- | src/log.c | 376 |
1 files changed, 0 insertions, 376 deletions
diff --git a/src/log.c b/src/log.c deleted file mode 100644 index 0b663e7..0000000 --- a/src/log.c +++ /dev/null @@ -1,376 +0,0 @@ -#include <assert.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/uio.h> -#include <time.h> -#include <unistd.h> - -#ifdef CONFIG_OPENGL -#include <GL/gl.h> -#include "backend/gl/gl_common.h" -#include "backend/gl/glx.h" -#endif - -#include "compiler.h" -#include "log.h" -#include "utils.h" - -thread_local struct log *tls_logger; - -struct log_target; - -struct log { - struct log_target *head; - - int log_level; -}; - -struct log_target { - const struct log_ops *ops; - struct log_target *next; -}; - -struct log_ops { - void (*write)(struct log_target *, const char *, size_t); - void (*writev)(struct log_target *, const struct iovec *, int vcnt); - void (*destroy)(struct log_target *); - - /// Additional strings to print around the log_level string - const char *(*colorize_begin)(enum log_level); - const char *(*colorize_end)(enum log_level); -}; - -/// Fallback writev for targets don't implement it -static attr_unused void -log_default_writev(struct log_target *tgt, const struct iovec *vec, int vcnt) { - size_t total = 0; - for (int i = 0; i < vcnt; i++) { - total += vec[i].iov_len; - } - - if (!total) { - // Nothing to write - return; - } - char *buf = ccalloc(total, char); - total = 0; - for (int i = 0; i < vcnt; i++) { - memcpy(buf + total, vec[i].iov_base, vec[i].iov_len); - total += vec[i].iov_len; - } - tgt->ops->write(tgt, buf, total); - free(buf); -} - -static attr_const const char *log_level_to_string(enum log_level level) { - switch (level) { - case LOG_LEVEL_TRACE: return "TRACE"; - case LOG_LEVEL_DEBUG: return "DEBUG"; - case LOG_LEVEL_INFO: return "INFO"; - case LOG_LEVEL_WARN: return "WARN"; - case LOG_LEVEL_ERROR: return "ERROR"; - case LOG_LEVEL_FATAL: return "FATAL ERROR"; - default: return "????"; - } -} - -enum log_level string_to_log_level(const char *str) { - if (strcasecmp(str, "TRACE") == 0) - return LOG_LEVEL_TRACE; - else if (strcasecmp(str, "DEBUG") == 0) - return LOG_LEVEL_DEBUG; - else if (strcasecmp(str, "INFO") == 0) - return LOG_LEVEL_INFO; - else if (strcasecmp(str, "WARN") == 0) - return LOG_LEVEL_WARN; - else if (strcasecmp(str, "ERROR") == 0) - return LOG_LEVEL_ERROR; - return LOG_LEVEL_INVALID; -} - -struct log *log_new(void) { - auto ret = cmalloc(struct log); - ret->log_level = LOG_LEVEL_WARN; - ret->head = NULL; - return ret; -} - -void log_add_target(struct log *l, struct log_target *tgt) { - assert(tgt->ops->writev); - tgt->next = l->head; - l->head = tgt; -} - -/// Remove a previously added log target for a log struct, and destroy it. If the log -/// target was never added, nothing happens. -void log_remove_target(struct log *l, struct log_target *tgt) { - struct log_target *now = l->head, **prev = &l->head; - while (now) { - if (now == tgt) { - *prev = now->next; - tgt->ops->destroy(tgt); - break; - } - prev = &now->next; - now = now->next; - } -} - -/// Destroy a log struct and every log target added to it -void log_destroy(struct log *l) { - // free all tgt - struct log_target *head = l->head; - while (head) { - auto next = head->next; - head->ops->destroy(head); - head = next; - } - free(l); -} - -void log_set_level(struct log *l, int level) { - assert(level <= LOG_LEVEL_FATAL && level >= 0); - l->log_level = level; -} - -enum log_level log_get_level(const struct log *l) { - return l->log_level; -} - -attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func, - const char *fmt, ...) { - assert(level <= LOG_LEVEL_FATAL && level >= 0); - if (level < l->log_level) - return; - - char *buf = NULL; - va_list args; - - va_start(args, fmt); - int blen = vasprintf(&buf, fmt, args); - va_end(args); - - if (blen < 0 || !buf) { - free(buf); - return; - } - - struct timespec ts; - timespec_get(&ts, TIME_UTC); - struct tm now; - localtime_r(&ts.tv_sec, &now); - char time_buf[100]; - strftime(time_buf, sizeof time_buf, "%x %T", &now); - - char *time = NULL; - int tlen = asprintf(&time, "%s.%03ld", time_buf, ts.tv_nsec / 1000000); - if (tlen < 0 || !time) { - free(buf); - free(time); - return; - } - - const char *log_level_str = log_level_to_string(level); - size_t llen = strlen(log_level_str); - size_t flen = strlen(func); - - struct log_target *head = l->head; - while (head) { - const char *p = "", *s = ""; - size_t plen = 0, slen = 0; - - if (head->ops->colorize_begin) { - // construct target specific prefix - p = head->ops->colorize_begin(level); - plen = strlen(p); - if (head->ops->colorize_end) { - s = head->ops->colorize_end(level); - slen = strlen(s); - } - } - head->ops->writev( - head, - (struct iovec[]){{.iov_base = "[ ", .iov_len = 2}, - {.iov_base = time, .iov_len = (size_t)tlen}, - {.iov_base = " ", .iov_len = 1}, - {.iov_base = (void *)func, .iov_len = flen}, - {.iov_base = " ", .iov_len = 1}, - {.iov_base = (void *)p, .iov_len = plen}, - {.iov_base = (void *)log_level_str, .iov_len = llen}, - {.iov_base = (void *)s, .iov_len = slen}, - {.iov_base = " ] ", .iov_len = 3}, - {.iov_base = buf, .iov_len = (size_t)blen}, - {.iov_base = "\n", .iov_len = 1}}, - 11); - head = head->next; - } - free(time); - free(buf); -} - -/// A trivial deinitializer that simply frees the memory -static attr_unused void logger_trivial_destroy(struct log_target *tgt) { - free(tgt); -} - -/// A null log target that does nothing -static const struct log_ops null_logger_ops; -static struct log_target null_logger_target = { - .ops = &null_logger_ops, -}; - -struct log_target *null_logger_new(void) { - return &null_logger_target; -} - -static void null_logger_write(struct log_target *tgt attr_unused, - const char *str attr_unused, size_t len attr_unused) { - return; -} - -static void null_logger_writev(struct log_target *tgt attr_unused, - const struct iovec *vec attr_unused, int vcnt attr_unused) { - return; -} - -static const struct log_ops null_logger_ops = { - .write = null_logger_write, - .writev = null_logger_writev, -}; - -/// A file based logger that writes to file (or stdout/stderr) -struct file_logger { - struct log_target tgt; - FILE *f; - struct log_ops ops; -}; - -static void file_logger_write(struct log_target *tgt, const char *str, size_t len) { - auto f = (struct file_logger *)tgt; - fwrite(str, 1, len, f->f); -} - -static void file_logger_writev(struct log_target *tgt, const struct iovec *vec, int vcnt) { - auto f = (struct file_logger *)tgt; - fflush(f->f); - writev(fileno(f->f), vec, vcnt); -} - -static void file_logger_destroy(struct log_target *tgt) { - auto f = (struct file_logger *)tgt; - fclose(f->f); - free(tgt); -} - -#define ANSI(x) "\033[" x "m" -static const char *terminal_colorize_begin(enum log_level level) { - switch (level) { - case LOG_LEVEL_TRACE: return ANSI("30;2"); - case LOG_LEVEL_DEBUG: return ANSI("37;2"); - case LOG_LEVEL_INFO: return ANSI("92"); - case LOG_LEVEL_WARN: return ANSI("33"); - case LOG_LEVEL_ERROR: return ANSI("31;1"); - case LOG_LEVEL_FATAL: return ANSI("30;103;1"); - default: return ""; - } -} - -static const char *terminal_colorize_end(enum log_level level attr_unused) { - return ANSI("0"); -} -#undef PREFIX - -static const struct log_ops file_logger_ops = { - .write = file_logger_write, - .writev = file_logger_writev, - .destroy = file_logger_destroy, -}; - -struct log_target *file_logger_new(const char *filename) { - FILE *f = fopen(filename, "a"); - if (!f) { - return NULL; - } - - auto ret = cmalloc(struct file_logger); - ret->tgt.ops = &ret->ops; - ret->f = f; - - // Always assume a file is not a terminal - ret->ops = file_logger_ops; - - return &ret->tgt; -} - -struct log_target *stderr_logger_new(void) { - int fd = dup(STDERR_FILENO); - if (fd < 0) { - return NULL; - } - - FILE *f = fdopen(fd, "w"); - if (!f) { - return NULL; - } - - auto ret = cmalloc(struct file_logger); - ret->tgt.ops = &ret->ops; - ret->f = f; - ret->ops = file_logger_ops; - - if (isatty(fd)) { - ret->ops.colorize_begin = terminal_colorize_begin; - ret->ops.colorize_end = terminal_colorize_end; - } - return &ret->tgt; -} - -#ifdef CONFIG_OPENGL -/// An opengl logger that can be used for logging into opengl debugging tools, -/// such as apitrace -struct gl_string_marker_logger { - struct log_target tgt; - PFNGLSTRINGMARKERGREMEDYPROC gl_string_marker; -}; - -static void -gl_string_marker_logger_write(struct log_target *tgt, const char *str, size_t len) { - auto g = (struct gl_string_marker_logger *)tgt; - // strip newlines at the end of the string - while (len > 0 && str[len-1] == '\n') { - len--; - } - g->gl_string_marker((GLsizei)len, str); -} - -static const struct log_ops gl_string_marker_logger_ops = { - .write = gl_string_marker_logger_write, - .writev = log_default_writev, - .destroy = logger_trivial_destroy, -}; - -struct log_target *gl_string_marker_logger_new(void) { - if (!gl_has_extension("GL_GREMEDY_string_marker")) { - return NULL; - } - - void *fnptr = glXGetProcAddress((GLubyte *)"glStringMarkerGREMEDY"); - if (!fnptr) - return NULL; - - auto ret = cmalloc(struct gl_string_marker_logger); - ret->tgt.ops = &gl_string_marker_logger_ops; - ret->gl_string_marker = fnptr; - return &ret->tgt; -} - -#else -struct log_target *gl_string_marker_logger_new(void) { - return NULL; -} -#endif - -// vim: set noet sw=8 ts=8: |