core/logger/Logger.h (96 lines of code) (raw):

/* * Copyright 2022 iLogtail 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. */ #pragma once #include <fstream> #include <map> #include <sstream> #include "spdlog/spdlog.h" namespace logtail { class Logger { const std::string DEFAULT_LOGGER_NAME = "/"; const std::string DEFAULT_PATTERN = "[%Y-%m-%d %H:%M:%S.%f]\t[%l]\t[%t]\t%v"; public: using logger = std::shared_ptr<spdlog::logger>; static Logger& Instance(); void InitGlobalLoggers(); logger CreateLogger(const std::string& loggerName, const std::string& logFilePath, unsigned int maxLogFileNum, unsigned long long maxLogFileSize, unsigned int maxDaysFromModify = 0, // Not supported const std::string compress = ""); // Not supported // If not found, return the default logger. logger GetLogger(const std::string& loggerName); private: Logger(); ~Logger(); // Use it to log something during intiliazing logger, it will // be closed if logger has already been initialized successfully. std::ofstream mInnerLogger; void LogMsg(const std::string& msg); struct SinkConfig { std::string type; unsigned int maxLogFileNum; unsigned long long maxLogFileSize; unsigned int maxDaysFromModify; // Not supported. std::string logFilePath; std::string compress; // Not supported }; struct LoggerConfig { std::string sinkName; spdlog::level::level_enum level; }; // Try to load config, if failed, use default config. void LoadConfig(const std::string& filePath); // Save config in JSON to @filePath. void SaveConfig(const std::string& filePath, std::map<std::string, LoggerConfig>& loggerCfgs, std::map<std::string, SinkConfig>& sinkCfgs); // LoadDefaultConfig only loads the default ("/") into @loggerCfgs and @sinkCfgs. void LoadDefaultConfig(std::map<std::string, LoggerConfig>& loggerCfgs, std::map<std::string, SinkConfig>& sinkCfgs); // LoadAllDefaultConfigs loads all default configs into @loggerCfgs and @sinkCfgs. void LoadAllDefaultConfigs(std::map<std::string, LoggerConfig>& loggerCfgs, std::map<std::string, SinkConfig>& sinkCfgs); // EnsureSnapshotDirExist ensures the snapshot dir exists. void EnsureSnapshotDirExist(std::map<std::string, SinkConfig>& sinkCfgs); }; } // namespace logtail class LogMaker { std::ostringstream mOStringStream; public: template <typename T> LogMaker& operator()(const std::string& key, const T& value) { return this->operator()(key.c_str(), value); } template <typename T> LogMaker& operator()(const char* key, const T& value) { mOStringStream << "\t" << key << ":" << value; return *this; } LogMaker& operator()(const std::string& key, bool value) { return this->operator()(key.c_str(), value ? "true" : "false"); } LogMaker& operator()(const char* key, bool value) { return this->operator()(key, value ? "true" : "false"); } const std::string GetContent() const { return mOStringStream.str(); } }; #define LOG_X_IF(logger, condition, fields, level) \ do { \ if (condition && logger->should_log(level)) { \ LogMaker maker; \ (void)maker fields; \ logger->log(level, "{}:{}\t{}", __FILE__, __LINE__, maker.GetContent()); \ } \ } while (0) #define SHOULD_LOG(logger, level) logger->should_log(level) #define SHOULD_LOG_TRACE(logger) SHOULD_LOG(logger, spdlog::level::trace) #define SHOULD_LOG_DEBUG(logger) SHOULD_LOG(logger, spdlog::level::debug) #define SHOULD_LOG_INFO(logger) SHOULD_LOG(logger, spdlog::level::info) #define SHOULD_LOG_WARNING(logger) SHOULD_LOG(logger, spdlog::level::warn) #define SHOULD_LOG_ERROR(logger) SHOULD_LOG(logger, spdlog::level::err) #define SHOULD_LOG_FATAL(logger) SHOULD_LOG(logger, spdlog::level::info) #ifndef LOG_INFO #define LOG_TRACE(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::trace) #define LOG_DEBUG(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::debug) #define LOG_INFO(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::info) #define LOG_WARNING(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::warn) #define LOG_ERROR(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::err) #define LOG_FATAL(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::info) #endif // For compatibility with syslog. #define APSARA_LOG_DEBUG(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::debug) #define APSARA_LOG_INFO(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::info) #define APSARA_LOG_WARNING(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::warn) #define APSARA_LOG_ERROR(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::err) #define APSARA_LOG_FATAL(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::info) #define APSARA_LOG_TRACE(logger, fields) LOG_X_IF(logger, true, fields, spdlog::level::trace) // Global loggers. // NOTE: Please call Logger::Instance().InitGlobalLoggers() to init these loggers in main(). extern logtail::Logger::logger sLogger;