forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtext_logging.cc
151 lines (127 loc) · 4.6 KB
/
text_logging.cc
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "drake/common/text_logging.h"
#include <memory>
#include <mutex>
#include <utility>
#ifdef HAVE_SPDLOG
#include <spdlog/sinks/dist_sink.h>
#include <spdlog/sinks/stdout_sinks.h>
#endif
#include "drake/common/never_destroyed.h"
namespace drake {
#ifdef HAVE_SPDLOG
namespace {
// Returns the default logger. NOTE: This function assumes that it is mutexed,
// as in the initializer of a static local.
std::shared_ptr<logging::logger> onetime_create_log() {
// Check if anyone has already set up a logger named "console". If so, we
// will just return it; if not, we'll create our own default one.
std::shared_ptr<logging::logger> result(spdlog::get("console"));
if (!result) {
// We wrap our stderr sink in a dist_sink so that users can atomically swap
// out the sinks used by all Drake logging, via dist_sink_mt's APIs.
auto wrapper = std::make_shared<spdlog::sinks::dist_sink_mt>();
// We use the stderr_sink_mt (instead of stderr_sink_st) so more than one
// thread can use this logger and have their messages be staggered by line,
// instead of co-mingling their character bytes.
wrapper->add_sink(std::make_shared<spdlog::sinks::stderr_sink_mt>());
result = std::make_shared<logging::logger>("console", std::move(wrapper));
result->set_level(spdlog::level::info);
}
return result;
}
} // namespace
logging::logger* log() {
static const never_destroyed<std::shared_ptr<logging::logger>> g_logger(
onetime_create_log());
return g_logger.access().get();
}
logging::sink* logging::get_dist_sink() {
// Extract the dist_sink_mt from Drake's logger instance.
auto* sink = log()->sinks().empty() ? nullptr : log()->sinks().front().get();
auto* result = dynamic_cast<spdlog::sinks::dist_sink_mt*>(sink);
if (result == nullptr) {
throw std::logic_error(
"drake::logging::get_sink(): error: the spdlog sink configuration has"
"unexpectedly changed.");
}
return result;
}
std::string logging::set_log_level(const std::string& level) {
spdlog::level::level_enum prev_value = drake::log()->level();
spdlog::level::level_enum value{};
if (level == "trace") {
value = spdlog::level::trace;
} else if (level == "debug") {
value = spdlog::level::debug;
} else if (level == "info") {
value = spdlog::level::info;
} else if (level == "warn") {
value = spdlog::level::warn;
} else if (level == "err") {
value = spdlog::level::err;
} else if (level == "critical") {
value = spdlog::level::critical;
} else if (level == "off") {
value = spdlog::level::off;
} else if (level == "unchanged") {
value = prev_value;
} else {
throw std::runtime_error(fmt::format("Unknown spdlog level: {}", level));
}
drake::log()->set_level(value);
switch (prev_value) {
case spdlog::level::trace: return "trace";
case spdlog::level::debug: return "debug";
case spdlog::level::info: return "info";
case spdlog::level::warn: return "warn";
case spdlog::level::err: return "err";
case spdlog::level::critical: return "critical";
case spdlog::level::off: return "off";
default: {
// N.B. `spdlog::level::level_enum` is not a `enum class`, so the
// compiler does not know that it has a closed set of values. For
// simplicity in linking, we do not use `DRAKE_UNREACHABLE`.
throw std::runtime_error("Should not reach here!");
}
}
}
const char* const logging::kSetLogLevelHelpMessage =
"sets the spdlog output threshold; possible values are "
"'unchanged', "
"'trace', "
"'debug', "
"'info', "
"'warn', "
"'err', "
"'critical', "
"'off'";
void logging::set_log_pattern(const std::string& pattern) {
drake::log()->set_pattern(pattern);
}
const char* const logging::kSetLogPatternHelpMessage =
"sets the spdlog pattern for formatting; for more information, see "
"https://github.com/gabime/spdlog/wiki/3.-Custom-formatting";
#else // HAVE_SPDLOG
logging::logger::logger() {}
logging::sink::sink() {}
logging::logger* log() {
// A do-nothing logger instance.
static logging::logger g_logger;
return &g_logger;
}
logging::sink* logging::get_dist_sink() {
// An empty sink instance.
static logging::sink g_sink;
return &g_sink;
}
std::string logging::set_log_level(const std::string&) {
return "";
}
const char* const logging::kSetLogLevelHelpMessage =
"(Text logging is unavailable.)";
void logging::set_log_pattern(const std::string&) {}
const char* const logging::kSetLogPatternHelpMessage =
"(Text logging is unavailable.)";
#endif // HAVE_SPDLOG
const char* const logging::kSetLogLevelUnchanged = "unchanged";
} // namespace drake