43 #include <boost/filesystem.hpp>
44 #include <spdlog/common.h>
45 #include <spdlog/spdlog.h>
55 static const auto LOG_FILE_BASENAME =
"osvr";
57 static const auto LOG_FILE_EXTENSION =
"log";
62 static inline std::string computeDefaultBasename() {
63 namespace fs = boost::filesystem;
66 return LOG_FILE_BASENAME;
68 auto exePath = fs::path{binLoc};
69 auto fn = exePath.filename().stem().string();
71 auto sanitized = sanitizeFilenamePiece(fn);
72 if (sanitized.empty()) {
73 return LOG_FILE_BASENAME;
79 LogRegistry &LogRegistry::instance(std::string
const *baseNamePtr) {
80 static LogRegistry instance_{
81 baseNamePtr ? *baseNamePtr : computeDefaultBasename()};
88 auto spd_logger = spdlog::get(logger_name);
92 spd_logger = spdlog::details::registry::instance().create(
93 logger_name, begin(sinks_), end(sinks_));
94 spd_logger->set_pattern(DEFAULT_PATTERN);
96 spd_logger->set_level(convertToLevelEnum(minLevel_));
98 convertToLevelEnum(DEFAULT_FLUSH_LEVEL));
99 }
catch (
const std::exception &e) {
100 generalPurposeLog_->error()
101 <<
"Caught exception attempting to create logger: "
103 generalPurposeLog_->error() <<
"Error creating logger. "
104 "Will only log to the "
107 generalPurposeLog_->error() <<
"Error creating logger. "
108 "Will only log to the "
118 spdlog::drop(logger_name);
124 for (
auto &sink : sinks_) {
134 spdlog::set_pattern(pattern.c_str());
138 if (severity > consoleLevel_) {
142 setLevelImpl(severity);
146 if (severity < minLevel_) {
149 setLevelImpl(severity);
151 setConsoleLevelImpl(severity);
154 LogRegistry::LogRegistry(std::string
const &logFileBaseName)
155 : minLevel_(
std::min(DEFAULT_LEVEL, DEFAULT_CONSOLE_LEVEL)),
156 consoleLevel_(
std::max(DEFAULT_LEVEL, DEFAULT_CONSOLE_LEVEL)),
157 logFileBaseName_(logFileBaseName) {
159 spdlog::set_pattern(DEFAULT_PATTERN);
160 spdlog::set_level(convertToLevelEnum(minLevel_));
165 #if defined(OSVR_ANDROID)
168 auto android_sink = getDefaultUnfilteredSink();
169 sinks_.push_back(android_sink);
170 auto &main_sink = android_sink;
174 getDefaultFilteredSink(convertToLevelEnum(consoleLevel_));
175 sinks_.push_back(console_filter_);
176 auto &main_sink = console_filter_;
180 generalPurposeLog_ = consoleOnlyLog_.get();
185 if (!binLoc.empty()) {
186 generalPurposeLog_->notice(
"Logging for ") << binLoc;
190 LogRegistry::~LogRegistry() {
195 void LogRegistry::setLevelImpl(LogLevel severity) {
196 spdlog::set_level(convertToLevelEnum(severity));
197 minLevel_ = severity;
200 void LogRegistry::setConsoleLevelImpl(LogLevel severity) {
201 consoleLevel_ = severity;
202 if (console_filter_) {
203 console_filter_->set_level(convertToLevelEnum(severity));
207 static inline bool shouldLogToFile() {
210 if (!fileLoggingEnabled || *fileLoggingEnabled ==
"0") {
216 void LogRegistry::createFileSink() {
217 #if defined(OSVR_ANDROID)
221 if (!shouldLogToFile()) {
229 spdlog::set_async_mode(q_size);
230 namespace fs = boost::filesystem;
231 auto base_name = fs::path(getLoggingDirectory(
true));
232 if (!base_name.empty()) {
233 logDir = base_name.string();
234 base_name /= logFileBaseName_;
235 auto daily_file_sink =
236 std::make_shared<spdlog::sinks::daily_file_sink_mt>(
237 base_name.string().c_str(), LOG_FILE_EXTENSION, 0,
239 sinks_.push_back(daily_file_sink);
241 }
catch (
const std::exception &e) {
242 if (consoleOnlyLog_) {
243 consoleOnlyLog_->error()
244 <<
"Error creating log file sink: " << e.what()
245 <<
". Will log to console only.";
248 <<
"[OSVR] Error creating log file sink: " << e.what()
249 <<
". Will log to console only." << std::endl;
253 if (consoleOnlyLog_) {
254 consoleOnlyLog_->error(
255 "Error creating log file sink. Will log to "
259 <<
"[OSVR] Error creating log file sink. Will log to "
270 {sinks_[0], sinks_[1]});
273 generalPurposeLog_ = generalLog_.get();
276 consoleOnlyLog_->error(
277 "Could not make a general log with both sinks!");
280 generalPurposeLog_->notice() <<
"Log file created in " << logDir;
281 generalPurposeLog_->notice() <<
"Log file name starts with \""
282 << logFileBaseName_ <<
"\"";
283 #endif // OSVR_ANDROID
LoggerPtr getOrCreateLogger(const std::string &logger_name)
Gets or creates a logger named logger_name.
static LoggerPtr makeFromExistingImplementation(std::string const &name, std::shared_ptr< spdlog::logger > logger)
void setConsoleLevel(LogLevel severity)
Sets the minimum level of messages to be logged to the console.
Header for basic internal log reference. To actually log to the produced loggers, include
static LoggerPtr makeWithSinks(std::string const &name, spdlog::sinks_init_list sinks)
void flush()
Flush all sinks manually.
static LoggerPtr makeWithSink(std::string const &name, spdlog::sink_ptr sink)
Regstry to maintain instantiated loggers and global settings.
std::string getBinaryLocation()
boost::optional< std::string > getEnvironmentVariable(std::string const &var)
Gets an environment variable's value. On systems that don't distinguish between having a variable def...
Header to include for OSVR-internal usage of the logging mechanism: provides the needed definition of...
void setPattern(const std::string &pattern)
Sets the output pattern on all registered loggers.
void setLevel(LogLevel severity)
Sets the minimum level of messages to be logged on all registered loggers.
void drop(const std::string &name)
Drops a logger from the registry.
void dropAll()
Removes all the registered loggers from the registry.