1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
#include <string.h>
#include <time.h>
#include <errno.h>
#include "log.h"
/* TODO: replace this with something thread-safe later. */
static unsigned log_level = LOG_INFO;
void vl_log_setlevel(unsigned level)
{
log_level = level;
}
#define MAX_LOGLEN ((size_t)4096)
#define MAX_LOGTIMELEN ((size_t)64) /* december 999th of 10000 A.D. at 100 o'clock */
static const char *const log_names[] = {
"TRACE",
"DEBUG",
"INFO",
"WARN",
"ERROR",
NULL
};
static FILE *log_stream(unsigned level)
{
switch (level) {
case LOG_TRACE:
case LOG_DEBUG:
case LOG_INFO:
return stdout;
default:
return stderr;
}
}
void vl_logv(unsigned level, const char *fmt, va_list args)
{
char buf[MAX_LOGLEN];
char datebuf[MAX_LOGTIMELEN];
time_t now;
struct tm now_tm;
int en = errno;
if (log_level > level) return;
if (level > LOG_ERROR) return;
vsnprintf(buf, MAX_LOGLEN, fmt, args);
strcpy(buf + MAX_LOGLEN - 4, "...");
now = time(NULL);
localtime_r(&now, &now_tm);
if (!strftime(datebuf, MAX_LOGTIMELEN, "%H:%M:%S", &now_tm)) {
strcpy(datebuf, "???");
}
fprintf(log_stream(level), "[%s] %5s: %s\n", datebuf, log_names[level], buf);
errno = en;
}
void vl_log(unsigned level, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vl_logv(level, fmt, args);
va_end(args);
}
|