diff --git a/example/example.cpp b/example/example.cpp index 345f8bd1..0c3b8395 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -1,235 +1,11 @@ -// -// Copyright(c) 2015 Gabi Melman. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) -// -// -// spdlog usage example -// -// - -#include - -void stdout_logger_example(); -void basic_example(); -void rotating_example(); -void daily_example(); -void async_example(); -void binary_example(); -void trace_example(); -void multi_sink_example(); -void user_defined_example(); -void err_handler_example(); -void syslog_example(); -void clone_example(); - #include "spdlog/spdlog.h" -int main(int, char *[]) +int main() { - spdlog::info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH); - spdlog::warn("Easy padding in numbers like {:08d}", 12); - spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); - spdlog::info("Support for floats {:03.2f}", 1.23456); - spdlog::info("Positional args are {1} {0}..", "too", "supported"); - spdlog::info("{:>8} aligned, {:<8} aligned", "right", "left"); - - // Runtime log levels - spdlog::set_level(spdlog::level::info); // Set global log level to info - spdlog::debug("This message should not be displayed!"); - spdlog::set_level(spdlog::level::trace); // Set specific logger's log level - spdlog::debug("This message should be displayed.."); - - // Customize msg format for all loggers - spdlog::set_pattern("[%H:%M:%S %z] [%^%L%$] [thread %t] %v"); - spdlog::info("This an info message with custom format"); - spdlog::set_pattern("%+"); // back to default format - - try - { - stdout_logger_example(); - basic_example(); - rotating_example(); - daily_example(); - clone_example(); - async_example(); - binary_example(); - multi_sink_example(); - user_defined_example(); - err_handler_example(); - trace_example(); - - // Flush all *registered* loggers using a worker thread every 3 seconds. - // note: registered loggers *must* be thread safe for this to work correctly! - spdlog::flush_every(std::chrono::seconds(3)); - - // Apply some function on all registered loggers - spdlog::apply_all([&](std::shared_ptr l) { l->info("End of example."); }); - - // Release all spdlog resources, and drop all loggers in the registry. - // This is optional (only mandatory if using windows + async log). - spdlog::shutdown(); - } - - // Exceptions will only be thrown upon failed logger or sink construction (not during logging). - catch (const spdlog::spdlog_ex &ex) - { - std::printf("Log initialization failed: %s\n", ex.what()); - return 1; - } -} - -#include "spdlog/sinks/stdout_color_sinks.h" -// or #include "spdlog/sinks/stdout_sinks.h" if no colors needed. -void stdout_logger_example() -{ - // Create color multi threaded logger. - auto console = spdlog::stdout_color_mt("console"); - // or for stderr: - // auto console = spdlog::stderr_color_mt("error-logger"); -} - -#include "spdlog/sinks/basic_file_sink.h" -void basic_example() -{ - // Create basic file logger (not rotated). - auto my_logger = spdlog::basic_logger_mt("file_logger", "logs/basic-log.txt"); -} - -#include "spdlog/sinks/rotating_file_sink.h" -void rotating_example() -{ - // Create a file rotating logger with 5mb size max and 3 rotated files. - auto rotating_logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3); -} - -#include "spdlog/sinks/daily_file_sink.h" -void daily_example() -{ - // Create a daily logger - a new file is created every day on 2:30am. - auto daily_logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30); -} - -// Clone a logger and give it new name. -// Useful for creating component/subsystem loggers from some "root" logger. -void clone_example() -{ - auto network_logger = spdlog::default_logger()->clone("network"); - network_logger->info("Logging network stuff.."); -} - -#include "spdlog/async.h" -void async_example() -{ - // Default thread pool settings can be modified *before* creating the async logger: - // spdlog::init_thread_pool(32768, 1); // queue with max 32k items 1 backing thread. - auto async_file = spdlog::basic_logger_mt("async_file_logger", "logs/async_log.txt"); - // alternatively: - // auto async_file = spdlog::create_async("async_file_logger", "logs/async_log.txt"); - - for (int i = 1; i < 101; ++i) - { - async_file->info("Async message #{}", i); - } -} - -// Log binary data as hex. -// Many types of std::container types can be used. -// Iterator ranges are supported too. -// Format flags: -// {:X} - print in uppercase. -// {:s} - don't separate each byte with space. -// {:p} - don't print the position on each line start. -// {:n} - don't split the output to lines. - -#include "spdlog/fmt/bin_to_hex.h" -void binary_example() -{ - std::vector buf; - for (int i = 0; i < 80; i++) - { - buf.push_back(static_cast(i & 0xff)); - } - spdlog::info("Binary example: {}", spdlog::to_hex(buf)); - spdlog::info("Another binary example:{:n}", spdlog::to_hex(std::begin(buf), std::begin(buf) + 10)); - // more examples: - // logger->info("uppercase: {:X}", spdlog::to_hex(buf)); - // logger->info("uppercase, no delimiters: {:Xs}", spdlog::to_hex(buf)); - // logger->info("uppercase, no delimiters, no position info: {:Xsp}", spdlog::to_hex(buf)); -} - -// Compile time log levels. -// define SPDLOG_ACTIVE_LEVEL to required level (e.g. SPDLOG_LEVEL_TRACE) -void trace_example() -{ - // trace from default logger - SPDLOG_TRACE("Some trace message.. {} ,{}", 1, 3.23); - // debug from default logger - SPDLOG_DEBUG("Some debug message.. {} ,{}", 1, 3.23); - - // trace from logger object - auto logger = spdlog::get("file_logger"); - SPDLOG_LOGGER_TRACE(logger, "another trace message"); -} - -// A logger with multiple sinks (stdout and file) - each with a different format and log level. -void multi_sink_example() -{ - auto console_sink = std::make_shared(); - console_sink->set_level(spdlog::level::warn); - console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v"); - - auto file_sink = std::make_shared("logs/multisink.txt", true); - file_sink->set_level(spdlog::level::trace); - - spdlog::logger logger("multi_sink", {console_sink, file_sink}); - logger.set_level(spdlog::level::debug); - logger.warn("this should appear in both console and file"); - logger.info("this message should not appear in the console, only in the file"); -} - -// User defined types logging by implementing operator<< -#include "spdlog/fmt/ostr.h" // must be included -struct my_type -{ - int i; - template - friend OStream &operator<<(OStream &os, const my_type &c) - { - return os << "[my_type i=" << c.i << "]"; - } -}; - -void user_defined_example() -{ - spdlog::info("user defined type: {}", my_type{14}); -} - -// Custom error handler. Will be triggered on log failure. -void err_handler_example() -{ - // can be set globally or per logger(logger->set_error_handler(..)) - spdlog::set_error_handler([](const std::string &msg) { printf("*** Custom log error handler: %s ***\n", msg.c_str()); }); -} - -// syslog example (linux/osx/freebsd) -#ifndef _WIN32 -#include "spdlog/sinks/syslog_sink.h" -void syslog_example() -{ - std::string ident = "spdlog-example"; - auto syslog_logger = spdlog::syslog_logger_mt("syslog", ident, LOG_PID); - syslog_logger->warn("This is warning that will end up in syslog."); -} -#endif - -// Android example. -#if defined(__ANDROID__) -#include "spdlog/sinks/android_sink.h" -void android_example() -{ - std::string tag = "spdlog-android"; - auto android_logger = spdlog::android_logger_mt("android", tag); - android_logger->critical("Use \"adb shell logcat\" to view this message."); -} - -#endif + auto l = spdlog::default_logger(); + l->trace("HELLO {}!!!", "lite"); + l->debug("HELLO {}!!!", "lite"); + l->info("HELLO {}!!!", "lite"); + l->warn("HELLO {}!!!", "lite"); + l->critical("HELLO s{}!!!", "lite"); +} \ No newline at end of file diff --git a/lite-example/example.cpp b/lite-example/example.cpp index a1a78eb6..05d772aa 100644 --- a/lite-example/example.cpp +++ b/lite-example/example.cpp @@ -2,6 +2,6 @@ int main() { - auto l = spdlog::create_lite(); - l.trace("HELLO {}!!!", "lite"); + //auto l = spdlog::create_lite(); + spdlog::lite::info("HELLO info {}", 123); } \ No newline at end of file diff --git a/lite/logger.cpp b/lite/logger.cpp index 6098df84..39841553 100644 --- a/lite/logger.cpp +++ b/lite/logger.cpp @@ -2,20 +2,82 @@ #include "spdlog/spdlog.h" #include "spdlog/logger.h" +static spdlog::level::level_enum to_spdlog_level(spdlog::lite::level level) +{ + return static_cast(level); +} + +static spdlog::lite::level to_lite_level(spdlog::level::level_enum level) +{ + return static_cast(level); +} + spdlog::lite::logger::logger(std::shared_ptr impl) { impl_ = std::move(impl); } - -bool spdlog::lite::logger::should_log(spdlog::lite::level lvl) const SPDLOG_NOEXCEPT +bool spdlog::lite::logger::should_log(spdlog::lite::level level) const SPDLOG_NOEXCEPT { - auto spd_level = static_cast(lvl); + auto spd_level = to_spdlog_level(level); return impl_->should_log(spd_level);//TODO level } -void spdlog::lite::logger::log_formatted_(spdlog::lite::level lvl, const fmt::memory_buffer &formatted) +void spdlog::lite::logger::log_formatted_(spdlog::lite::level level, const fmt::memory_buffer &formatted) { - auto spd_level = static_cast(lvl); - impl_->log(spd_level, spdlog::details::fmt_helper::to_string_view(formatted)); //TODO and source_loc -} \ No newline at end of file + auto spd_level = to_spdlog_level(level); + impl_->log(spd_level, spdlog::details::fmt_helper::to_string_view(formatted)); +} + + +void spdlog::lite::logger::log_formatted_src(const spdlog::lite::src_loc &src, spdlog::lite::level lvl, const fmt::memory_buffer &formatted) +{ + auto spd_level = to_spdlog_level(lvl); + spdlog::source_loc source_loc{src.filename, src.line, src.funcname}; + impl_->log(source_loc, spd_level, spdlog::details::fmt_helper::to_string_view(formatted)); +} + +void spdlog::lite::logger::set_level(spdlog::lite::level level) +{ + auto spd_level = to_spdlog_level(level); + impl_->set_level(spd_level); +} + +spdlog::lite::level spdlog::lite::logger::get_level() const +{ + return to_lite_level(impl_->level()); +} + +std::string spdlog::lite::logger::name() const +{ + return impl_->name(); +} + +void spdlog::lite::logger::flush() +{ + impl_->flush(); +} + +void spdlog::lite::logger::flush_on(spdlog::lite::level level) +{ + auto spd_level = to_spdlog_level(level); + impl_->flush_on(spd_level); +} + +spdlog::lite::level spdlog::lite::logger::flush_level() const +{ + return to_lite_level(impl_->flush_level()); +} + +// pattern +void spdlog::lite::logger::set_pattern(std::string pattern) +{ + impl_->set_pattern(std::move(pattern)); +} + + +spdlog::lite::logger &spdlog::lite::default_logger() +{ + static spdlog::lite::logger s_default(spdlog::default_logger()); + return s_default; +} diff --git a/lite/logger.h b/lite/logger.h index 6cc60b09..b762b3f5 100644 --- a/lite/logger.h +++ b/lite/logger.h @@ -1,19 +1,36 @@ // // Created by gabi on 3/16/19. // - -#ifndef SPDLOG_LIB_LOGGER_H -#define SPDLOG_LIB_LOGGER_H +#pragma once #include -#include "spd_types.h" +#include #include "spdlog/fmt/fmt.h" +//#define SPDLITE_LOGGER_INFO(logger, ...) SPDLITE_LOGGER_CALL(logger, spdlog::lite::level::info, __VA_ARGS__) +//#define SPDLITE_INFO(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__) + namespace spdlog { class logger; namespace lite { + enum class level{ + trace, + debug, + info, + warn, + err, + critical, + off + }; + + struct src_loc { + const char *filename; + int line; + const char* funcname; + }; + class logger { public: logger() = default; @@ -37,28 +54,124 @@ namespace spdlog { log_formatted_(lvl, formatted_buf); } -// template -// void log(spdlog::lite::level lvl, const char *fmt, const Args &... args) -// { -// log(lvl, fmt, args...); -// } template - void trace(const char *fmt, const Args &... args) { + void log(const spdlog::lite::src_loc& src, spdlog::lite::level lvl, const char *fmt, const Args &... args) { + if (!should_log(lvl)) { + return; + } + fmt::memory_buffer formatted_buf; + fmt::format_to(formatted_buf, fmt, args...); + log_formatted_src(src, lvl, formatted_buf); + } + + + template + void trace(const char *fmt, const Args &... args) + { log(spdlog::lite::level::trace, fmt, args...); } + template + void trace(const char* source_file, int source_line, const char* source_func, const char *fmt, const Args &... args) + { + spdlog::lite::src_loc src{source_file, source_line, source_func}; + log(src, spdlog::lite::level::trace, fmt, args...); + } + + template + void debug(const char *fmt, const Args &... args) + { + log(spdlog::lite::level::debug, fmt, args...); + } + + template + void info(const char *fmt, const Args &... args) + { + log(spdlog::lite::level::info, fmt, args...); + } + + template + void warn(const char *fmt, const Args &... args) + { + log(spdlog::lite::level::warn, fmt, args...); + } + + template + void error(const char *fmt, const Args &... args) + { + log(spdlog::lite::level::err, fmt, args...); + } + + template + void critical(const char *fmt, const Args &... args) + { + log(spdlog::lite::level::critical, fmt, args...); + } + + std::string name() const; + + // level + void set_level(lite::level level); + lite::level get_level() const; + + // flush + void flush(); + void flush_on(spdlog::lite::level log_level); + spdlog::lite::level flush_level() const; + + // pattern + void set_pattern(std::string pattern); + protected: std::shared_ptr impl_; - void log_formatted_(spdlog::lite::level lvl, const fmt::memory_buffer &formatted); + void log_formatted_src(const spdlog::lite::src_loc& src, spdlog::lite::level lvl, const fmt::memory_buffer &formatted); }; + spdlog::lite::logger& default_logger(); + + + template + void trace(const char *fmt, const Args &... args) + { + default_logger().trace(fmt, args...); + } + template + void debug(const char *fmt, const Args &... args) + { + default_logger().debug(fmt, args...); + } + + template + void info(const char *fmt, const Args &... args) + { + default_logger().info(fmt, args...); + } + + template + void warn(const char *fmt, const Args &... args) + { + default_logger().warn(fmt, args...); + } + + template + void error(const char *fmt, const Args &... args) + { + default_logger().error(fmt, args...); + } + + template + void critical(const char *fmt, const Args &... args) + { + default_logger().critical(fmt, args...); + } + } // namespace lite // factory to create lite logger // implement it in a dedicated compilation unit for fast compiles spdlog::lite::logger create_lite(void* ctx = nullptr); -} // namespace spdlog -#endif //SPDLOG_LIB_LOGGER_H + +} // namespace spdlog \ No newline at end of file diff --git a/lite/spd_types.h b/lite/spd_types.h deleted file mode 100644 index 94be9b34..00000000 --- a/lite/spd_types.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright(c) 2019 Gabi Melman. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) -// - -// core types, forward declarations and defines used by spdlog - -#pragma once - -namespace spdlog -{ -namespace lite -{ - enum class level{ - trace, - debug, - info, - warning, - error, - critical, - off - - }; -}} \ No newline at end of file