commit
537831abfc
|
@ -76,6 +76,9 @@ OPTIONS
|
||||||
*-S*::
|
*-S*::
|
||||||
Enable synchronous X operation (for debugging).
|
Enable synchronous X operation (for debugging).
|
||||||
|
|
||||||
|
*--log-level*::
|
||||||
|
Set the log level. Possible values are "TRACE", "DEBUG", "INFO", "WARN", "ERROR", in increasing level of importance. Case doesn't matter.
|
||||||
|
|
||||||
*--show-all-xerrors*::
|
*--show-all-xerrors*::
|
||||||
Show all X errors (for debugging).
|
Show all X errors (for debugging).
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
// Copyright (c) 2018 Yuxuan Shui <yshuiv7@gmail.com>
|
// Copyright (c) 2018 Yuxuan Shui <yshuiv7@gmail.com>
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdc-predef.h>
|
||||||
|
|
||||||
#define auto __auto_type
|
#define auto __auto_type
|
||||||
#define likely(x) __builtin_expect(!!(x), 1)
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
@ -79,3 +81,13 @@
|
||||||
#else
|
#else
|
||||||
# define unreachable do {} while(0)
|
# define unreachable do {} while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __STDC_NO_THREADS__
|
||||||
|
# include <threads.h>
|
||||||
|
#elif __STDC_VERSION__ >= 201112L
|
||||||
|
# define thread_local _Thread_local
|
||||||
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
|
# define thread_local __thread
|
||||||
|
#else
|
||||||
|
# define thread_local _Pragma("GCC error \"No thread local storage support\"") __error__
|
||||||
|
#endif
|
||||||
|
|
|
@ -2607,6 +2607,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
|
||||||
{ "version", no_argument, NULL, 318 },
|
{ "version", no_argument, NULL, 318 },
|
||||||
{ "no-x-selection", no_argument, NULL, 319 },
|
{ "no-x-selection", no_argument, NULL, 319 },
|
||||||
{ "no-name-pixmap", no_argument, NULL, 320 },
|
{ "no-name-pixmap", no_argument, NULL, 320 },
|
||||||
|
{ "log-level", required_argument, NULL, 321 },
|
||||||
{ "reredir-on-root-change", no_argument, NULL, 731 },
|
{ "reredir-on-root-change", no_argument, NULL, 731 },
|
||||||
{ "glx-reinit-on-root-change", no_argument, NULL, 732 },
|
{ "glx-reinit-on-root-change", no_argument, NULL, 732 },
|
||||||
{ "monitor-repaint", no_argument, NULL, 800 },
|
{ "monitor-repaint", no_argument, NULL, 800 },
|
||||||
|
@ -2895,6 +2896,15 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
|
||||||
" removed in the future. If you really need this feature, please report\n"
|
" removed in the future. If you really need this feature, please report\n"
|
||||||
"an issue to let us know\n");
|
"an issue to let us know\n");
|
||||||
break;
|
break;
|
||||||
|
case 321: {
|
||||||
|
enum log_level tmp_level = string_to_log_level(optarg);
|
||||||
|
if (tmp_level == LOG_LEVEL_INVALID) {
|
||||||
|
log_warn("Invalid log level, defaults to WARN");
|
||||||
|
} else {
|
||||||
|
log_set_level_tls(tmp_level);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
P_CASEBOOL(319, no_x_selection);
|
P_CASEBOOL(319, no_x_selection);
|
||||||
P_CASEBOOL(731, reredir_on_root_change);
|
P_CASEBOOL(731, reredir_on_root_change);
|
||||||
P_CASEBOOL(732, glx_reinit_on_root_change);
|
P_CASEBOOL(732, glx_reinit_on_root_change);
|
||||||
|
@ -3568,6 +3578,9 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log_init_tls();
|
||||||
|
log_add_target_tls(stderr_logger_new());
|
||||||
|
|
||||||
// Allocate a session and copy default values into it
|
// Allocate a session and copy default values into it
|
||||||
session_t *ps = cmalloc(session_t);
|
session_t *ps = cmalloc(session_t);
|
||||||
*ps = s_def;
|
*ps = s_def;
|
||||||
|
@ -4053,6 +4066,8 @@ session_destroy(session_t *ps) {
|
||||||
|
|
||||||
if (ps == ps_g)
|
if (ps == ps_g)
|
||||||
ps_g = NULL;
|
ps_g = NULL;
|
||||||
|
|
||||||
|
log_deinit_tls();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -281,6 +281,15 @@ void parse_config_libconfig(session_t *ps, bool *shadow_enable,
|
||||||
// --backend
|
// --backend
|
||||||
if (config_lookup_string(&cfg, "backend", &sval) && !parse_backend(ps, sval))
|
if (config_lookup_string(&cfg, "backend", &sval) && !parse_backend(ps, sval))
|
||||||
exit(1);
|
exit(1);
|
||||||
|
// --log-level
|
||||||
|
if (config_lookup_string(&cfg, "log-level", &sval)) {
|
||||||
|
auto level = string_to_log_level(sval);
|
||||||
|
if (level == LOG_LEVEL_INVALID) {
|
||||||
|
log_warn("Invalid log level, defaults to WARN");
|
||||||
|
} else {
|
||||||
|
log_set_level_tls(level);
|
||||||
|
}
|
||||||
|
}
|
||||||
// --sw-opti
|
// --sw-opti
|
||||||
lcfg_lookup_bool(&cfg, "sw-opti", &ps->o.sw_opti);
|
lcfg_lookup_bool(&cfg, "sw-opti", &ps->o.sw_opti);
|
||||||
// --use-ewmh-active-win
|
// --use-ewmh-active-win
|
||||||
|
|
|
@ -0,0 +1,299 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
#include <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 (*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);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Helper function for writing null terminated strings
|
||||||
|
static void log_strwrite(struct log_target *tgt, const char *str) {
|
||||||
|
return tgt->ops->write(tgt, str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
tgt->next = l->head;
|
||||||
|
l->head = tgt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Destroy a log struct
|
||||||
|
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_INVALID && level > 0);
|
||||||
|
l->log_level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func,
|
||||||
|
const char *fmt, ...) {
|
||||||
|
assert(level < LOG_LEVEL_INVALID && level > 0);
|
||||||
|
if (level < l->log_level)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
size_t len = vasprintf(&buf, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
struct timespec ts;
|
||||||
|
timespec_get(&ts, TIME_UTC);
|
||||||
|
auto tm = localtime(&ts.tv_sec);
|
||||||
|
char time_buf[100];
|
||||||
|
strftime(time_buf, sizeof time_buf, "%x %T", tm);
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *log_level_str = log_level_to_string(level);
|
||||||
|
char *common = NULL;
|
||||||
|
size_t plen = asprintf(&common, "[ %s.%03ld %s %s ] ", time_buf,
|
||||||
|
ts.tv_nsec / 1000000, func, log_level_str);
|
||||||
|
if (!common)
|
||||||
|
return;
|
||||||
|
|
||||||
|
common = crealloc(common, plen + len + 2);
|
||||||
|
strcpy(common + plen, buf);
|
||||||
|
strcpy(common + plen + len, "\n");
|
||||||
|
|
||||||
|
struct log_target *head = l->head;
|
||||||
|
while (head) {
|
||||||
|
if (head->ops->colorize_begin) {
|
||||||
|
// construct target specific prefix
|
||||||
|
const char *p = head->ops->colorize_begin(level);
|
||||||
|
const char *s = "";
|
||||||
|
if (head->ops->colorize_end)
|
||||||
|
s = head->ops->colorize_end(level);
|
||||||
|
char *str = NULL;
|
||||||
|
size_t plen2 =
|
||||||
|
asprintf(&str, "[ %s.%03ld %s %s%s%s ] ", time_buf,
|
||||||
|
ts.tv_nsec / 1000000, func, p, log_level_str, s);
|
||||||
|
if (!str) {
|
||||||
|
log_strwrite(head, common);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
str = crealloc(str, plen2 + len + 2);
|
||||||
|
strcpy(str + plen2, buf);
|
||||||
|
strcpy(str + plen2 + len, "\n");
|
||||||
|
log_strwrite(head, str);
|
||||||
|
free(str);
|
||||||
|
} else {
|
||||||
|
log_strwrite(head, common);
|
||||||
|
}
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
free(common);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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, const char *str, size_t len) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct log_ops null_logger_ops = {
|
||||||
|
.write = null_logger_write,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A file based logger that writes to file (or stdout/stderr)
|
||||||
|
struct file_logger {
|
||||||
|
struct log_target tgt;
|
||||||
|
FILE *f;
|
||||||
|
struct log_ops ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
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");
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *terminal_colorize_end(enum log_level level) {
|
||||||
|
return ANSI("0");
|
||||||
|
}
|
||||||
|
#undef PREFIX
|
||||||
|
|
||||||
|
static const struct log_ops file_logger_ops = {
|
||||||
|
.write = file_logger_write,
|
||||||
|
.destroy = file_logger_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct log_target *file_logger_new(const char *filename) {
|
||||||
|
FILE *f = fopen(filename, "w+");
|
||||||
|
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 glx_string_marker_logger {
|
||||||
|
struct log_target tgt;
|
||||||
|
void (*glx_string_marker)(GLsizei len, const char *);
|
||||||
|
};
|
||||||
|
|
||||||
|
void glx_string_marker_logger_write(struct log_target *tgt, const char *str, size_t len) {
|
||||||
|
auto g = (struct glx_string_marker_logger *)tgt;
|
||||||
|
g->glx_string_marker(len, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct log_ops glx_string_marker_logger_ops = {
|
||||||
|
.write = glx_string_marker_logger_write,
|
||||||
|
.destroy = logger_trivial_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct log_target *glx_string_marker_logger_new(void) {
|
||||||
|
void *fnptr = glXGetProcAddress((GLubyte *)"glStringMarkerGREMEDY");
|
||||||
|
if (!fnptr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
auto ret = cmalloc(struct glx_string_marker_logger);
|
||||||
|
ret->tgt.ops = &glx_string_marker_logger_ops;
|
||||||
|
ret->glx_string_marker = fnptr;
|
||||||
|
return &ret->tgt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
struct log_target *glx_string_marker_logger_new(void) {
|
||||||
|
return null_logger_new();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// vim: set noet sw=8 ts=8:
|
83
src/log.h
83
src/log.h
|
@ -2,28 +2,85 @@
|
||||||
// Copyright (c) 2018 Yuxuan Shui <yshuiv7@gmail.com>
|
// Copyright (c) 2018 Yuxuan Shui <yshuiv7@gmail.com>
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "compiler.h"
|
||||||
|
|
||||||
|
enum log_level {
|
||||||
|
LOG_LEVEL_TRACE = 0,
|
||||||
|
LOG_LEVEL_DEBUG,
|
||||||
|
LOG_LEVEL_INFO,
|
||||||
|
LOG_LEVEL_WARN,
|
||||||
|
LOG_LEVEL_ERROR,
|
||||||
|
LOG_LEVEL_INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LOG(level, x, ...) \
|
||||||
|
log_printf(tls_logger, LOG_LEVEL_##level, __func__, x, ##__VA_ARGS__)
|
||||||
|
#define log_trace(x, ...) LOG(TRACE, x, ##__VA_ARGS__)
|
||||||
|
#define log_debug(x, ...) LOG(DEBUG, x, ##__VA_ARGS__)
|
||||||
|
#define log_info(x, ...) LOG(INFO, x, ##__VA_ARGS__)
|
||||||
|
#define log_warn(x, ...) LOG(WARN, x, ##__VA_ARGS__)
|
||||||
|
#define log_error(x, ...) LOG(ERROR, x, ##__VA_ARGS__)
|
||||||
|
|
||||||
/// Print out an error message.
|
/// Print out an error message.
|
||||||
#define printf_err(format, ...) \
|
#define printf_err(format, ...) log_error(format, ##__VA_ARGS__)
|
||||||
fprintf(stderr, format "\n", ## __VA_ARGS__)
|
|
||||||
|
|
||||||
/// Print out an error message with function name.
|
/// Print out an error message with function name.
|
||||||
#define printf_errf(format, ...) \
|
#define printf_errf(format, ...) log_error(format, ##__VA_ARGS__)
|
||||||
printf_err("%s" format, __func__, ## __VA_ARGS__)
|
|
||||||
|
|
||||||
/// Print out an error message with function name, and quit with a
|
/// Print out an error message with function name, and quit with a
|
||||||
/// specific exit code.
|
/// specific exit code.
|
||||||
#define printf_errfq(code, format, ...) { \
|
#define printf_errfq(code, format, ...) \
|
||||||
printf_err("%s" format, __func__, ## __VA_ARGS__); \
|
{ \
|
||||||
exit(code); \
|
log_error(format, ##__VA_ARGS__); \
|
||||||
}
|
exit(code); \
|
||||||
|
}
|
||||||
|
|
||||||
/// Print out a debug message.
|
/// Print out a debug message.
|
||||||
#define printf_dbg(format, ...) \
|
#define printf_dbg(format, ...) log_debug(format, ##__VA_ARGS__)
|
||||||
printf(format, ## __VA_ARGS__); \
|
|
||||||
fflush(stdout)
|
|
||||||
|
|
||||||
/// Print out a debug message with function name.
|
/// Print out a debug message with function name.
|
||||||
#define printf_dbgf(format, ...) \
|
#define printf_dbgf(format, ...) log_debug(format, ##__VA_ARGS__)
|
||||||
printf_dbg("%s" format, __func__, ## __VA_ARGS__)
|
|
||||||
|
struct log;
|
||||||
|
struct log_target;
|
||||||
|
|
||||||
|
attr_printf(4, 5) void log_printf(struct log *, int level, const char *func,
|
||||||
|
const char *fmt, ...);
|
||||||
|
|
||||||
|
attr_malloc struct log *log_new(void);
|
||||||
|
attr_nonnull_all void log_destroy(struct log *);
|
||||||
|
attr_nonnull(1) void log_set_level(struct log *l, int level);
|
||||||
|
attr_nonnull_all void log_add_target(struct log *, struct log_target *);
|
||||||
|
attr_const enum log_level string_to_log_level(const char *);
|
||||||
|
|
||||||
|
extern thread_local struct log *tls_logger;
|
||||||
|
|
||||||
|
/// Create a thread local logger
|
||||||
|
static inline void log_init_tls(void) {
|
||||||
|
tls_logger = log_new();
|
||||||
|
}
|
||||||
|
/// Set thread local logger log level
|
||||||
|
static inline void log_set_level_tls(int level) {
|
||||||
|
assert(tls_logger);
|
||||||
|
log_set_level(tls_logger, level);
|
||||||
|
}
|
||||||
|
static inline attr_nonnull_all void log_add_target_tls(struct log_target *tgt) {
|
||||||
|
assert(tls_logger);
|
||||||
|
log_add_target(tls_logger, tgt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void log_deinit_tls(void) {
|
||||||
|
assert(tls_logger);
|
||||||
|
log_destroy(tls_logger);
|
||||||
|
tls_logger = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr_malloc struct log_target *stderr_logger_new(void);
|
||||||
|
attr_malloc struct log_target *file_logger_new(const char *file);
|
||||||
|
attr_malloc struct log_target *null_logger_new(void);
|
||||||
|
attr_malloc struct log_target *glx_string_marker_logger_new(void);
|
||||||
|
|
||||||
|
// vim: set noet sw=8 ts=8:
|
||||||
|
|
|
@ -5,7 +5,7 @@ deps = [
|
||||||
]
|
]
|
||||||
|
|
||||||
srcs = [ files('compton.c', 'win.c', 'c2.c', 'x.c', 'config.c', 'vsync.c',
|
srcs = [ files('compton.c', 'win.c', 'c2.c', 'x.c', 'config.c', 'vsync.c',
|
||||||
'diagnostic.c', 'string_utils.c', 'render.c', 'kernel.c')]
|
'diagnostic.c', 'string_utils.c', 'render.c', 'kernel.c', 'log.c')]
|
||||||
|
|
||||||
cflags = []
|
cflags = []
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue