diff --git a/CMakeLists.txt b/CMakeLists.txt index 5137907d..8bb9460d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,41 +47,47 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(SPDLOG_MASTER_PROJECT ON) endif() -option(SPDLOG_HEADER_ONLY "Header only version. Turn OFF to build as static lib" OFF) +option(SPDLOG_HEADER_ONLY "Header only version. Turn OFF to build as static lib" ON) option(SPDLOG_BUILD_EXAMPLES "Build examples" ${SPDLOG_MASTER_PROJECT}) option(SPDLOG_BUILD_BENCH "Build benchmarks (Requires https://github.com/google/benchmark.git to be installed)" ON) option(SPDLOG_BUILD_TESTS "Build tests" ${SPDLOG_MASTER_PROJECT}) option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF) option(SPDLOG_INSTALL "Generate the install target." ${SPDLOG_MASTER_PROJECT}) +set(HEADER_BASE "${CMAKE_CURRENT_SOURCE_DIR}/include") + if(SPDLOG_HEADER_ONLY) add_definitions(-DSPDLOG_HEADER_ONLY) add_library(spdlog INTERFACE) add_library(spdlog::spdlog ALIAS spdlog) + target_include_directories( + spdlog + INTERFACE + "$" + ) else() remove_definitions(-DSPDLOG_HEADER_ONLY) - file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp) - add_library(spdlog ${SRC_FILES} ) + file(GLOB SRC_FILES ${HEADER_BASE}/spdlog/impl/*.cpp) + add_library(spdlog STATIC ${SRC_FILES}) add_library(spdlog::spdlog ALIAS spdlog) + target_include_directories( + spdlog + PUBLIC + "$" + ) endif() if(SPDLOG_FMT_EXTERNAL AND NOT TARGET fmt::fmt) find_package(fmt REQUIRED CONFIG) endif() -target_include_directories( - spdlog - PUBLIC - "$" -) if(SPDLOG_FMT_EXTERNAL) target_compile_definitions(spdlog INTERFACE SPDLOG_FMT_EXTERNAL) target_link_libraries(spdlog INTERFACE fmt::fmt) endif() -set(HEADER_BASE "${CMAKE_CURRENT_SOURCE_DIR}/include") if(SPDLOG_BUILD_EXAMPLES) add_subdirectory(example) @@ -95,3 +101,18 @@ endif() if(SPDLOG_BUILD_BENCH) add_subdirectory(bench) endif() + +#--------------------------------------------------------------------------------------- +# install +#--------------------------------------------------------------------------------------- +install(DIRECTORY ${HEADER_BASE}/spdlog DESTINATION include) + +if(!SPDLOG_HEADER_ONLY) + install(TARGETS spdlog ARCHIVE DESTINATION lib) +endif() + +#--------------------------------------------------------------------------------------- +# register project in CMake user registry +#--------------------------------------------------------------------------------------- +export(PACKAGE ${PROJECT_NAME}) + diff --git a/example/example.cpp b/example/example.cpp index 132494fd..345f8bd1 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -7,15 +7,229 @@ // // +#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" -#include "spdlog/async.h" -#include "spdlog/sinks/stdout_color_sinks.h" int main(int, char *[]) { - using spdlog::sinks::stderr_color_sink_mt; - auto logger = spdlog::create_async("async"); - logger->info("HEllo xsdsdfs {}", 123); - //spdlog::error("HEllo err {}", "HG FS"); + 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 diff --git a/include/spdlog/.spdlog.h.kate-swp b/include/spdlog/.spdlog.h.kate-swp new file mode 100644 index 00000000..546ce39c Binary files /dev/null and b/include/spdlog/.spdlog.h.kate-swp differ diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h index 3d1c9578..94a1edbd 100644 --- a/include/spdlog/async_logger.h +++ b/include/spdlog/async_logger.h @@ -67,7 +67,7 @@ private: } // namespace spdlog #ifdef SPDLOG_HEADER_ONLY -#include "../src/async_logger.cpp" +#include "spdlog/impl/async_logger.cpp" #endif // SPDLOG_HEADER_ONLY diff --git a/include/spdlog/common.h b/include/spdlog/common.h index bb5ec94e..a4c3407c 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -14,6 +14,7 @@ #include #include #include +#include #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) #include @@ -94,6 +95,7 @@ using filename_t = std::string; using log_clock = std::chrono::system_clock; using sink_ptr = std::shared_ptr; using sinks_init_list = std::initializer_list; +using err_handler = std::function; // string_view type - either std::string_view or fmt::string_view (pre c++17) #if defined(FMT_USE_STD_STRING_VIEW) diff --git a/include/spdlog/details/file_helper.h b/include/spdlog/details/file_helper.h index 1a352c6f..62cd2ee3 100644 --- a/include/spdlog/details/file_helper.h +++ b/include/spdlog/details/file_helper.h @@ -58,5 +58,5 @@ private: } // namespace spdlog #ifdef SPDLOG_HEADER_ONLY -#include "../../../src/file_helper.cpp" +#include "spdlog/impl/file_helper.cpp" #endif // ! SPDLOG_HEADER_ONLY diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 86918fd4..3ac381be 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -34,5 +34,5 @@ struct log_msg } // namespace spdlog #ifdef SPDLOG_HEADER_ONLY -#include "../../../src/log_msg.cpp" +#include "spdlog/impl/log_msg.cpp" #endif // SPDLOG_HEADER_ONLY diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h index 9dd94ebe..5f87f5fd 100644 --- a/include/spdlog/details/os.h +++ b/include/spdlog/details/os.h @@ -89,5 +89,5 @@ void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target } // namespace spdlog #ifdef SPDLOG_HEADER_ONLY -#include "../src/os.cpp" +#include "spdlog/impl/os.cpp" #endif diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 3388743d..64686017 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -103,5 +103,5 @@ private: } // namespace spdlog #ifdef SPDLOG_HEADER_ONLY -#include "../src/pattern_formatter.cpp" +#include "spdlog/impl/pattern_formatter.cpp" #endif diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 24e72e2f..5afff601 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -102,5 +102,5 @@ private: } // namespace spdlog #ifdef SPDLOG_HEADER_ONLY -#include "../src/registry.cpp" +#include "spdlog/impl/registry.cpp" #endif // SPDLOG_HEADER_ONLY diff --git a/src/async_logger.cpp b/include/spdlog/impl/async_logger.cpp similarity index 100% rename from src/async_logger.cpp rename to include/spdlog/impl/async_logger.cpp diff --git a/src/file_helper.cpp b/include/spdlog/impl/file_helper.cpp similarity index 100% rename from src/file_helper.cpp rename to include/spdlog/impl/file_helper.cpp diff --git a/src/log_msg.cpp b/include/spdlog/impl/log_msg.cpp similarity index 100% rename from src/log_msg.cpp rename to include/spdlog/impl/log_msg.cpp diff --git a/src/logger.cpp b/include/spdlog/impl/logger.cpp similarity index 100% rename from src/logger.cpp rename to include/spdlog/impl/logger.cpp diff --git a/src/os.cpp b/include/spdlog/impl/os.cpp similarity index 100% rename from src/os.cpp rename to include/spdlog/impl/os.cpp diff --git a/src/pattern_formatter.cpp b/include/spdlog/impl/pattern_formatter.cpp similarity index 100% rename from src/pattern_formatter.cpp rename to include/spdlog/impl/pattern_formatter.cpp diff --git a/src/registry.cpp b/include/spdlog/impl/registry.cpp similarity index 100% rename from src/registry.cpp rename to include/spdlog/impl/registry.cpp diff --git a/src/sink.cpp b/include/spdlog/impl/sink.cpp similarity index 100% rename from src/sink.cpp rename to include/spdlog/impl/sink.cpp diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index fdba2a11..070e9875 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -33,7 +33,6 @@ namespace spdlog { class logger { public: - using err_handler = std::function; template logger(std::string name, It begin, It end) : name_(std::move(name)) @@ -345,5 +344,5 @@ public: } // namespace spdlog #ifdef SPDLOG_HEADER_ONLY -#include "../src/logger.cpp" +#include "spdlog/impl/logger.cpp" #endif // SPDLOG_HEADER_ONLY diff --git a/include/spdlog/sinks/sink.h b/include/spdlog/sinks/sink.h index 11c54fb6..8515b041 100644 --- a/include/spdlog/sinks/sink.h +++ b/include/spdlog/sinks/sink.h @@ -42,5 +42,5 @@ protected: } // namespace spdlog #ifdef SPDLOG_HEADER_ONLY -#include "../src/sink.cpp" +#include "spdlog/impl/sink.cpp" #endif // SPDLOG_HEADER_ONLY