-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlog.cpp
85 lines (71 loc) · 2.26 KB
/
log.cpp
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
#include "log.h"
#include "exception.h"
#include <limits.h>
#include <stdio.h>
#include <iostream>
#include <boost/thread.hpp>
namespace {
inline std::string exe_path() {
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid());
FD(open(buf, O_RDONLY)).read(buf, sizeof(buf));
return buf;
}
inline std::string cwd() {
char buf[PATH_MAX];
REQUIRE(getcwd(buf, sizeof(buf)) != 0, "couldn't get cwd");
return buf;
}
static struct InitLogger {
InitLogger() { Logger::instance(); }
} dummy;
static const char* strings[] = { "DEBUG", "WARN", "ERROR", "FATAL"};
inline const char* asString(Logger::Level level) {
REQUIRE(unsigned(level) < sizeof(strings) / sizeof(strings[0]), "Unknown level");
return strings[level];
}
inline Logger::Level asLevel(const std::string& name) {
for(size_t i = 0; i < sizeof(strings) / sizeof(strings[0]); ++i) {
if(strings[i] == name) return Logger::Level(i);
}
THROW("Unknown name: " << name);
}
}
void set_level(const std::string& name) {
try {
set_level(asLevel(name));
} catch(std::runtime_error& ex) {
ERROR("Couldn't set log level: " << ex.what());
}
}
Logger& Logger::instance() {
static Logger logger_(exe_path());
return logger_;
}
Logger::Logger(const std::string& exe) :
prefix_(exe.substr(exe.rfind('/') + 1)), level_(ERROR) {
try {
log_.reset(open(std::string(cwd() + "/" + prefix_ + ".log").c_str(),
O_RDWR | O_APPEND | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
} catch(std::runtime_error& ex) {
std::cerr << "ERROR: couldn't open log" << ex.what() << std::endl;
}
}
void Logger::write(Level level, const std::string& message) {
if(level < level_) return;
char buf[20];
time_t t = time(0);
struct tm tm;
strftime(&buf[0], sizeof(buf), "%F %T", localtime_r(&t, &tm));
std::stringstream s;
s << asString(level) << " " << buf << " " << prefix_
<< "[" << getpid() << ":" << boost::this_thread::get_id() << "]: "
<< message << std::endl;
if(log_.get() != -1) {
while(log_.write(s.str().c_str(), s.str().size()) == -1);
}
if(isatty(2) == 1) {
::write(2, s.str().c_str(), s.str().size());
}
}