-
Notifications
You must be signed in to change notification settings - Fork 308
/
Logger.h
240 lines (208 loc) · 8.82 KB
/
Logger.h
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#ifndef OPENSIM_LOG_H_
#define OPENSIM_LOG_H_
/* -------------------------------------------------------------------------- *
* OpenSim: Logger.h *
* -------------------------------------------------------------------------- *
* The OpenSim API is a toolkit for musculoskeletal modeling and simulation. *
* See http://opensim.stanford.edu and the NOTICE file for more information. *
* OpenSim is developed at Stanford University and supported by the US *
* National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA *
* through the Warrior Web program. *
* *
* Copyright (c) 2005-2019 Stanford University and the Authors *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain a *
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* -------------------------------------------------------------------------- */
#include "osimCommonDLL.h"
#include <set>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <string>
#include <spdlog/fmt/ostr.h>
namespace OpenSim {
class LogSink;
/// This is a singleton class (single instance) for logging messages and
/// controlling how those messages are presented to the user.
class OSIMCOMMON_API Logger {
public:
/// This is a static singleton class: there is no way of constructing it
Logger() = delete;
/// This enum lists the types of messages that should be logged. These
/// levels match those of the spdlog logging library that OpenSim uses for
/// logging.
enum class Level {
/// Do not log any messages. Useful when running an optimization or
/// automated pipeline.
Off = 6,
/// Only log critical errors.
Critical = 5,
/// Log all messages that require user intervention.
Error = 4,
/// Log warnings. Warnings are generated when the software will proceed
/// but the user should check their input.
Warn = 3,
/// Default.
Info = 2,
/// Log information that may be useful when debugging the operation of
/// the
/// software to investigate unexpected results.
Debug = 1,
/// Log as much as possible, including messages that describe the
/// software's
/// behavior step by step. Note: OpenSim has very few Trace-level
/// messages.
Trace = 0
};
/// Log messages of importance `level` and greater.
/// For example, if the level is set to Info, then Critical, Error, Warn,
/// and Info messages are logged, while Debug and Trace messages are not
/// logged.
static void setLevel(Level level);
static Level getLevel();
/// Set the logging level using one of the following strings
/// (case-insensitive):
/// - Off
/// - Critical
/// - Error
/// - Warn
/// - Info
/// - Debug
/// - Trace
/// This variant of setLevel() is for use in Matlab.
/// @see Level.
static void setLevelString(std::string level);
static std::string getLevelString();
/// Returns true if messages at the provided level should be logged,
/// based on the set logging level. The following code will produce output:
/// @code
/// Log::setLevel(Log::Level::Warn);
/// if (shouldLog(Log::Level::Error)) {
/// std::cout << "Error encountered." << std::endl;
/// }
/// @endcode
static bool shouldLog(Level level);
/// @name Commands to log messages
/// Use these functions instead of using spdlog directly.
/// @{
template <typename... Args>
static void critical(spdlog::string_view_t fmt, const Args&... args) {
if (shouldLog(Level::Critical)) {
getDefaultLogger().critical(fmt, args...);
}
}
template <typename... Args>
static void error(spdlog::string_view_t fmt, const Args&... args) {
if (shouldLog(Level::Error)) {
getDefaultLogger().error(fmt, args...);
}
}
template <typename... Args>
static void warn(spdlog::string_view_t fmt, const Args&... args) {
if (shouldLog(Level::Warn)) {
getDefaultLogger().warn(fmt, args...);
}
}
template <typename... Args>
static void info(spdlog::string_view_t fmt, const Args&... args) {
if (shouldLog(Level::Info)) {
getDefaultLogger().info(fmt, args...);
}
}
template <typename... Args>
static void debug(spdlog::string_view_t fmt, const Args&... args) {
if (shouldLog(Level::Debug)) {
getDefaultLogger().debug(fmt, args...);
}
}
template <typename... Args>
static void trace(spdlog::string_view_t fmt, const Args&... args) {
if (shouldLog(Level::Trace)) {
getDefaultLogger().trace(fmt, args...);
}
}
/// Use this function to log messages that would normally be sent to
/// std::cout. These messages always appear (unless the logger is off), and
/// are also logged to the filesink (addFileSink()) and any sinks added via
/// addSink(). The main use case for this function is inside of functions
/// whose intent is to print information (e.g., Component::printSubcomponentInfo()).
/// Besides such use cases, this function should be used sparingly to
/// give users control over what gets logged.
template <typename... Args>
static void cout(spdlog::string_view_t fmt, const Args&... args) {
getCoutLogger().log(spdlog::level::critical, fmt, args...);
}
/// @}
/// Log messages to a file at the level getLevel().
/// OpenSim logs messages to the file opensim.log by default.
/// If we are already logging messages to a file, then this
/// function issues a warning and returns; invoke removeFileSink() first.
/// @note This function is not thread-safe. Do not invoke this function
/// concurrently, or concurrently with addSink() or removeSink().
/// @note If filepath can't be opened, no log file is created.
static void addFileSink(const std::string& filepath = "opensim.log");
/// Remove the filesink if it exists.
/// If the filesink was already removed, then this does nothing.
/// @note This function is not thread-safe. Do not invoke this function
/// concurrently, or concurrently with addSink() or removeSink().
static void removeFileSink();
/// Start reporting messages to the provided sink.
/// @note This function is not thread-safe. Do not invoke this function
/// concurrently, or concurrently with addLogFile() or removeSink().
static void addSink(const std::shared_ptr<LogSink> sink);
/// Remove a sink. If it doesn't exist, do nothing.
/// @note This function is not thread-safe. Do not invoke this function
/// concurrently, or concurrently with addLogFile() or addSink().
static void removeSink(const std::shared_ptr<LogSink> sink);
private:
static spdlog::logger& getCoutLogger();
static spdlog::logger& getDefaultLogger();
};
/// @name Logging functions
/// @{
/// @related Logger
template <typename... Args>
void log_critical(spdlog::string_view_t fmt, const Args&... args) {
Logger::critical(fmt, args...);
}
/// @related Logger
template <typename... Args>
void log_error(spdlog::string_view_t fmt, const Args&... args) {
Logger::error(fmt, args...);
}
/// @related Logger
template <typename... Args>
void log_warn(spdlog::string_view_t fmt, const Args&... args) {
Logger::warn(fmt, args...);
}
/// @related Logger
template <typename... Args>
void log_info(spdlog::string_view_t fmt, const Args&... args) {
Logger::info(fmt, args...);
}
/// @related Logger
template <typename... Args>
void log_debug(spdlog::string_view_t fmt, const Args&... args) {
Logger::debug(fmt, args...);
}
/// @related Logger
template <typename... Args>
void log_trace(spdlog::string_view_t fmt, const Args&... args) {
Logger::trace(fmt, args...);
}
/// @copydoc Logger::cout()
/// @related Logger
template <typename... Args>
void log_cout(spdlog::string_view_t fmt, const Args&... args) {
Logger::cout(fmt, args...);
}
/// @}
} // namespace OpenSim
#endif // OPENSIM_LOG_H_