LoggerPtr LogRegistry::getOrCreateLogger(const std::string &logger_name) { // If logger already exists, return a copy of it auto spd_logger = spdlog::get(logger_name); if (!spd_logger) { // Bummer, it didn't exist. We'll create one from scratch. try { spd_logger = spdlog::details::registry::instance().create( logger_name, begin(sinks_), end(sinks_)); spd_logger->set_pattern(DEFAULT_PATTERN); /// @todo should this level be different than other levels? spd_logger->set_level(convertToLevelEnum(minLevel_)); spd_logger->flush_on( convertToLevelEnum(DEFAULT_FLUSH_LEVEL)); } catch (const std::exception &e) { generalPurposeLog_->error() << "Caught exception attempting to create logger: " << e.what(); generalPurposeLog_->error() << "Error creating logger. " "Will only log to the " "console."; } catch (...) { generalPurposeLog_->error() << "Error creating logger. " "Will only log to the " "console."; } } return Logger::makeFromExistingImplementation(logger_name, spd_logger); }
LogRegistry::LogRegistry(std::string const &logFileBaseName) : minLevel_(std::min(DEFAULT_LEVEL, DEFAULT_CONSOLE_LEVEL)), consoleLevel_(std::max(DEFAULT_LEVEL, DEFAULT_CONSOLE_LEVEL)), logFileBaseName_(logFileBaseName) { // Set default pattern and level spdlog::set_pattern(DEFAULT_PATTERN); spdlog::set_level(convertToLevelEnum(minLevel_)); // Instantiate console and file sinks. These sinks will be used with // each logger that is created via the registry. #if defined(OSVR_ANDROID) // Android doesn't have a console, it has logcat. // We won't filter because we won't log to file on Android. auto android_sink = getDefaultUnfilteredSink(); sinks_.push_back(android_sink); auto &main_sink = android_sink; #else // Console sink console_filter_ = getDefaultFilteredSink(convertToLevelEnum(consoleLevel_)); sinks_.push_back(console_filter_); auto &main_sink = console_filter_; #endif consoleOnlyLog_ = Logger::makeWithSink(OSVR_GENERAL_LOG_NAME, main_sink); generalPurposeLog_ = consoleOnlyLog_.get(); createFileSink(); auto binLoc = getBinaryLocation(); if (!binLoc.empty()) { generalPurposeLog_->notice("Logging for ") << binLoc; } }
LoggerPtr Logger::makeWithSink(std::string const &name, spdlog::sink_ptr sink) { if (!sink) { // bad sink! std::cerr << "WARNING: Logger::makeWithSink(\"" << name << "\", sink) called with a null sink! Will result " "in a fallback logger!" << std::endl; return makeFallback(name); } auto spd_logger = std::make_shared<spdlog::logger>(name, sink); spd_logger->set_pattern(DEFAULT_PATTERN); spd_logger->flush_on(convertToLevelEnum(DEFAULT_FLUSH_LEVEL)); return makeLogger(name, spd_logger); }
LoggerPtr Logger::makeWithSinks(std::string const &name, spdlog::sinks_init_list sinks) { for (auto &sink : sinks) { if (!sink) { std::cerr << "WARNING: " "Logger::makeWithSinks(\"" << name << "\", sinks) called " "with at least one null sink! Will " "result in a fallback logger!" << std::endl; // got a bad sink /// @todo should we be making a fallback logger here, just /// hoping spdlog will deal with a bad sink pointer without /// issue, or filtering the init list to a non-nullptr /// vector? return makeFallback(name); } } auto spd_logger = std::make_shared<spdlog::logger>(name, sinks); spd_logger->set_pattern(DEFAULT_PATTERN); spd_logger->flush_on(convertToLevelEnum(DEFAULT_FLUSH_LEVEL)); return makeLogger(name, spd_logger); }
void Logger::write(LogLevel level, const char* msg) { logger_->log(convertToLevelEnum(level), msg); }
void Logger::flushOn(LogLevel level) { logger_->flush_on(convertToLevelEnum(level)); }
void Logger::setLogLevel(LogLevel level) { logger_->set_level(convertToLevelEnum(level)); }
void LogRegistry::setConsoleLevelImpl(LogLevel severity) { consoleLevel_ = severity; if (console_filter_) { console_filter_->set_level(convertToLevelEnum(severity)); } }
void LogRegistry::setLevelImpl(LogLevel severity) { spdlog::set_level(convertToLevelEnum(severity)); minLevel_ = severity; }