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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
// -*- mode: c++; c-basic-offset: 2; -*-
#include "common.hh"
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#include <cstdarg>
#include <cstdio>
#include <iostream>
#include <memory>
#include <syslog.h>
#include "logger.hh"
namespace {
class LoggerStdErr : public Logger {
public:
void out(Level UNUSED(lvl), char const* format, ...) override {
char* tmp;
va_list args;
va_start(args, format);
auto ret = vasprintf(&tmp, format, args);
va_end(args);
if (ret == -1) return;
std::cerr << tmp << std::endl;
free(tmp);
}
};
class LoggerSyslog : public Logger {
public:
LoggerSyslog(std::string const& name) {
openlog(name.c_str(), LOG_PID, LOG_DAEMON);
}
~LoggerSyslog() override {
closelog();
}
void out(Level lvl, char const* format, ...) override {
va_list args;
va_start(args, format);
vsyslog(lvl2prio(lvl), format, args);
va_end(args);
}
private:
static int lvl2prio(Level lvl) {
switch (lvl) {
case ERR:
return LOG_ERR;
case WARN:
return LOG_WARNING;
case INFO:
return LOG_INFO;
}
assert(false);
return LOG_INFO;
}
};
class LoggerFile : public Logger {
public:
LoggerFile()
: fh_(nullptr) {
}
bool open(std::string const& path) {
if (fh_) fclose(fh_);
fh_ = fopen(path.c_str(), "a");
return fh_ != NULL;
}
~LoggerFile() override {
if (fh_) fclose(fh_);
}
void out(Level lvl, char const* format, ...) override {
fputs(lvl2str(lvl), fh_);
fwrite(": ", 1, 2, fh_);
va_list args;
va_start(args, format);
vfprintf(fh_, format, args);
va_end(args);
fputc('\n', fh_);
}
private:
static char const* lvl2str(Level lvl) {
switch (lvl) {
case ERR:
return "Error";
case WARN:
return "Warning";
case INFO:
return "Info";
}
assert(false);
return "Info";
}
FILE* fh_;
};
} // namespace
// static
Logger* Logger::create_stderr() {
return new LoggerStdErr();
}
// static
Logger* Logger::create_syslog(std::string const& name) {
return new LoggerSyslog(name);
}
// static
Logger* Logger::create_file(std::string const& path) {
std::unique_ptr<LoggerFile> ret(new LoggerFile());
if (ret->open(path)) {
return ret.release();
}
return nullptr;
}
|