MULE 0.0.1
Multi-Use Library Essentials
Loading...
Searching...
No Matches
log.c
1#include "log/log.h"
2#include "str/str.h"
3
4#include <stdarg.h>
5#include <stdlib.h>
6#include <string.h>
7#include <unistd.h>
8
9LogLevel log_level_ = LOG_INFO;
10static FILE *log_out_; /* null means stderr */
11static int log_color_ = -1; /* -1 until the first message decides */
12
13static const char *const log_names_[] = {
14 [LOG_TRACE] = "TRACE", [LOG_DEBUG] = "DEBUG", [LOG_INFO] = "INFO ",
15 [LOG_WARN] = "WARN ", [LOG_ERROR] = "ERROR", [LOG_FATAL] = "FATAL",
16};
17static const char *const log_colors_[] = {
18 [LOG_TRACE] = "", [LOG_DEBUG] = "", [LOG_INFO] = LOG_GREEN,
20};
21
23 log_level_ = level;
24}
25
26void log_set_output(FILE *f) {
27 log_out_ = f;
28 log_color_ = -1;
29}
30
31/* Set to anything other than empty or "0". */
32static bool log_env_on_(const char *name) {
33 const char *v = getenv(name);
34 return v != NULL && v[0] != '\0' && strcmp(v, "0") != 0;
35}
36
37bool log_color_enabled(FILE *f) {
38 const char *no_color = getenv("NO_COLOR");
39 if (no_color != NULL && no_color[0] != '\0') return false;
40 if (log_env_on_("CLICOLOR_FORCE") || log_env_on_("FORCE_COLOR"))
41 return true;
42 if (!isatty(fileno(f))) return false;
43
44 const char *term = getenv("TERM");
45 return term != NULL && term[0] != '\0' && strcmp(term, "dumb") != 0;
46}
47
48MULE_PRINTF(4, 0)
49static FILE *log_vwrite_(LogLevel level, const char *file, int line,
50 const char *fmt, va_list ap) {
51 FILE *out = log_out_ != NULL ? log_out_ : stderr;
52 if (log_color_ < 0) log_color_ = log_color_enabled(out);
53 const char *on = log_color_ ? log_colors_[level] : "";
54 const char *off = on[0] != '\0' ? LOG_RESET : "";
55
56 /* shortcut: one allocation per line. Reuse a thread_local buffer if
57 * logging ever shows up in a profile. */
58 Str s = { 0 };
59 bool ok = str_appendf(&s, "%s%s%s %s:%d: ", on, log_names_[level], off,
60 file, line) &&
61 str_vappendf(&s, fmt, ap) &&
62 str_push(&s, '\n');
63 if (ok)
64 fwrite(s.data, 1, s.len, out);
65 else
66 fprintf(out, "%s %s:%d: (out of memory formatting this message)\n",
67 log_names_[level], file, line);
68 str_free(&s);
69 return out;
70}
71
72void log_write_(LogLevel level, const char *file, int line, const char *fmt,
73 ...) {
74 va_list ap;
75 va_start(ap, fmt);
76 log_vwrite_(level, file, line, fmt, ap);
77 va_end(ap);
78}
79
80void log_fatal_(const char *file, int line, const char *fmt, ...) {
81 va_list ap;
82 va_start(ap, fmt);
83 FILE *out = log_vwrite_(LOG_FATAL, file, line, fmt, ap);
84 va_end(ap);
85 fflush(out);
86 abort();
87}
void log_set_output(FILE *f)
Write messages to f from now on.
Definition log.c:26
#define LOG_YELLOW
Yellow text.
Definition log.h:99
void log_set_level(LogLevel level)
Drop messages below level from now on.
Definition log.c:22
#define LOG_GREEN
Green text.
Definition log.h:98
#define LOG_RED
Red text.
Definition log.h:97
#define LOG_RESET
Back to the terminal's default style.
Definition log.h:100
bool log_color_enabled(FILE *f)
True when colour escapes written to f will render as colour.
Definition log.c:37
LogLevel
How much a message matters, from chattiest to most severe.
Definition log.h:40
@ LOG_ERROR
An operation failed.
Definition log.h:45
@ LOG_TRACE
Step-by-step detail, usually off.
Definition log.h:41
@ LOG_INFO
Normal progress worth recording.
Definition log.h:43
@ LOG_DEBUG
Detail for whoever is debugging.
Definition log.h:42
@ LOG_FATAL
The program cannot continue.
Definition log.h:46
@ LOG_WARN
Something odd that the program survived.
Definition log.h:44
size_t len
Bytes of content, excluding the terminator.
Definition str.h:66
char * data
Buffer, or null when nothing is allocated.
Definition str.h:65
void str_free(Str *s)
Free the buffer and reset s to the zero state.
Definition str.c:50
bool str_appendf(Str *s, const char *fmt,...)
Append the printf-style expansion of fmt.
Definition str.c:123
bool str_push(Str *s, char c)
Append the single byte c.
Definition str.c:76
bool str_vappendf(Str *s, const char *fmt, va_list ap)
str_appendf() for a va_list, like vprintf.
Definition str.c:131
Owned, growable byte string.
Definition str.h:64