summaryrefslogtreecommitdiffstats
path: root/lib/log.c
blob: 6f0f40acf1759fddabd9c98b4e1e446eb7ce23a4 (plain) (blame)
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);
}