Commit 96886899 authored by Gabi Melman's avatar Gabi Melman Committed by GitHub

Merge pull request #531 from fogo/printf

Support for printf-style logging
parents dc8ac4c6 e8b7f419
...@@ -85,6 +85,7 @@ script: ...@@ -85,6 +85,7 @@ script:
- ./"${BIN}" - ./"${BIN}"
- valgrind --trace-children=yes --leak-check=full ./"${BIN}" - valgrind --trace-children=yes --leak-check=full ./"${BIN}"
- cd $CHECKOUT_PATH/tests; make rebuild; ./tests - cd $CHECKOUT_PATH/tests; make rebuild; ./tests
- cd $CHECKOUT_PATH/tests; STYLE=printf make rebuild; ./tests
notifications: notifications:
email: false email: false
...@@ -58,7 +58,6 @@ inline void spdlog::logger::set_pattern(const std::string& pattern, pattern_time ...@@ -58,7 +58,6 @@ inline void spdlog::logger::set_pattern(const std::string& pattern, pattern_time
_set_pattern(pattern, pattern_time); _set_pattern(pattern, pattern_time);
} }
template <typename... Args> template <typename... Args>
inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args) inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args)
{ {
...@@ -67,7 +66,12 @@ inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Ar ...@@ -67,7 +66,12 @@ inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Ar
try try
{ {
details::log_msg log_msg(&_name, lvl); details::log_msg log_msg(&_name, lvl);
#if defined(SPDLOG_FMT_PRINTF)
fmt::printf(log_msg.raw, fmt, args...);
#else
log_msg.raw.write(fmt, args...); log_msg.raw.write(fmt, args...);
#endif
_sink_it(log_msg); _sink_it(log_msg);
} }
catch (const std::exception &ex) catch (const std::exception &ex)
......
/*
Formatting library for C++
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#include "format.h"
#include "printf.h"
namespace fmt {
template <typename Char>
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args);
FMT_FUNC int fprintf(std::FILE *f, CStringRef format, ArgList args) {
MemoryWriter w;
printf(w, format, args);
std::size_t size = w.size();
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
}
#ifndef FMT_HEADER_ONLY
template void PrintfFormatter<char>::format(CStringRef format);
template void PrintfFormatter<wchar_t>::format(WCStringRef format);
#endif // FMT_HEADER_ONLY
} // namespace fmt
This diff is collapsed.
...@@ -19,10 +19,16 @@ ...@@ -19,10 +19,16 @@
#define FMT_USE_WINDOWS_H 0 #define FMT_USE_WINDOWS_H 0
#endif #endif
#include "spdlog/fmt/bundled/format.h" #include "spdlog/fmt/bundled/format.h"
#if defined(SPDLOG_FMT_PRINTF)
#include "spdlog/fmt/bundled/printf.h"
#endif
#else //external fmtlib #else //external fmtlib
#include <fmt/format.h> #include <fmt/format.h>
#if defined(SPDLOG_FMT_PRINTF)
#include <fmt/printf.h>
#endif
#endif #endif
...@@ -96,6 +96,14 @@ ...@@ -96,6 +96,14 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Uncomment to use printf-style messages in your logs instead of the usual
// format-style used by default.
//
// #define SPDLOG_FMT_PRINTF
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Uncomment to enable syslog (disabled by default) // Uncomment to enable syslog (disabled by default)
// //
......
CXX ?= g++ CXX ?= g++
CXXFLAGS = -Wall -pedantic -std=c++11 -pthread -O2 -I../include ifeq ($(STYLE),printf)
$(info *** PRINTF STYLE ***)
CXXFLAGS = -DSPDLOG_FMT_PRINTF -Wall -pedantic -std=c++11 -pthread -O2 -I../include
else
$(info *** FORMAT STYLE ***)
CXXFLAGS = -Wall -pedantic -std=c++11 -pthread -O2 -I../include
endif
LDPFALGS = -pthread LDPFALGS = -pthread
CPP_FILES := $(wildcard *.cpp) CPP_FILES := $(wildcard *.cpp)
......
...@@ -135,6 +135,7 @@ TEST_CASE("conditional_trace_varargs", "[conditional_trace_varargs]") ...@@ -135,6 +135,7 @@ TEST_CASE("conditional_trace_varargs", "[conditional_trace_varargs]")
//const char //const char
for (auto i = 0; i < 2; i++) for (auto i = 0; i < 2; i++)
{ {
#if !defined(SPDLOG_FMT_PRINTF)
REQUIRE(conditional_log_varags(spdlog::level::trace, (i % 2 == 0), "Hello {}", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : "")); REQUIRE(conditional_log_varags(spdlog::level::trace, (i % 2 == 0), "Hello {}", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : ""));
REQUIRE(conditional_log_varags(spdlog::level::debug, (i % 2 == 0), "Hello {}", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : "")); REQUIRE(conditional_log_varags(spdlog::level::debug, (i % 2 == 0), "Hello {}", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : ""));
REQUIRE(conditional_log_varags(spdlog::level::info, (i % 2 == 0), "Hello {}", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : "")); REQUIRE(conditional_log_varags(spdlog::level::info, (i % 2 == 0), "Hello {}", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : ""));
...@@ -150,5 +151,24 @@ TEST_CASE("conditional_trace_varargs", "[conditional_trace_varargs]") ...@@ -150,5 +151,24 @@ TEST_CASE("conditional_trace_varargs", "[conditional_trace_varargs]")
REQUIRE(conditional_log_varags(spdlog::level::err, (i % 2 == 0), L"Hello {}", i) == (i % 2 == 0 ? L"Hello " + std::to_wstring(i) : L"")); REQUIRE(conditional_log_varags(spdlog::level::err, (i % 2 == 0), L"Hello {}", i) == (i % 2 == 0 ? L"Hello " + std::to_wstring(i) : L""));
REQUIRE(conditional_log_varags(spdlog::level::critical, (i % 2 == 0), L"Hello {}", i) == (i % 2 == 0 ? L"Hello " + std::to_wstring(i) : L"")); REQUIRE(conditional_log_varags(spdlog::level::critical, (i % 2 == 0), L"Hello {}", i) == (i % 2 == 0 ? L"Hello " + std::to_wstring(i) : L""));
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
#else
REQUIRE(conditional_log_varags(spdlog::level::trace, (i % 2 == 0), "Hello %d", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : ""));
REQUIRE(conditional_log_varags(spdlog::level::debug, (i % 2 == 0), "Hello %d", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : ""));
REQUIRE(conditional_log_varags(spdlog::level::info, (i % 2 == 0), "Hello %d", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : ""));
REQUIRE(conditional_log_varags(spdlog::level::warn, (i % 2 == 0), "Hello %d", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : ""));
REQUIRE(conditional_log_varags(spdlog::level::err, (i % 2 == 0), "Hello %d", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : ""));
REQUIRE(conditional_log_varags(spdlog::level::critical, (i % 2 == 0), "Hello %d", i) == (i % 2 == 0 ? "Hello " + std::to_string(i) : ""));
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
REQUIRE(conditional_log_varags(spdlog::level::trace, (i % 2 == 0), L"Hello %d", i) == (i % 2 == 0 ? L"Hello " + std::to_wstring(i) : L""));
REQUIRE(conditional_log_varags(spdlog::level::debug, (i % 2 == 0), L"Hello %d", i) == (i % 2 == 0 ? L"Hello " + std::to_wstring(i) : L""));
REQUIRE(conditional_log_varags(spdlog::level::info, (i % 2 == 0), L"Hello %d", i) == (i % 2 == 0 ? L"Hello " + std::to_wstring(i) : L""));
REQUIRE(conditional_log_varags(spdlog::level::warn, (i % 2 == 0), L"Hello %d", i) == (i % 2 == 0 ? L"Hello " + std::to_wstring(i) : L""));
REQUIRE(conditional_log_varags(spdlog::level::err, (i % 2 == 0), L"Hello %d", i) == (i % 2 == 0 ? L"Hello " + std::to_wstring(i) : L""));
REQUIRE(conditional_log_varags(spdlog::level::critical, (i % 2 == 0), L"Hello %d", i) == (i % 2 == 0 ? L"Hello " + std::to_wstring(i) : L""));
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
#endif // !defined(SPDLOG_FMT_PRINTF)
} }
} }
\ No newline at end of file
...@@ -26,8 +26,13 @@ TEST_CASE("default_error_handler", "[errors]]") ...@@ -26,8 +26,13 @@ TEST_CASE("default_error_handler", "[errors]]")
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename, true); auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename, true);
logger->set_pattern("%v"); logger->set_pattern("%v");
#if !defined(SPDLOG_FMT_PRINTF)
logger->info("Test message {} {}", 1); logger->info("Test message {} {}", 1);
logger->info("Test message {}", 2); logger->info("Test message {}", 2);
#else
logger->info("Test message %d %d", 1);
logger->info("Test message %d", 2);
#endif
logger->flush(); logger->flush();
REQUIRE(file_contents(filename) == std::string("Test message 2\n")); REQUIRE(file_contents(filename) == std::string("Test message 2\n"));
...@@ -50,7 +55,11 @@ TEST_CASE("custom_error_handler", "[errors]]") ...@@ -50,7 +55,11 @@ TEST_CASE("custom_error_handler", "[errors]]")
throw custom_ex(); throw custom_ex();
}); });
logger->info("Good message #1"); logger->info("Good message #1");
#if !defined(SPDLOG_FMT_PRINTF)
REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex); REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex);
#else
REQUIRE_THROWS_AS(logger->info("Bad format msg %s %s", "xxx"), custom_ex);
#endif
logger->info("Good message #2"); logger->info("Good message #2");
REQUIRE(count_lines(filename) == 2); REQUIRE(count_lines(filename) == 2);
} }
...@@ -81,7 +90,11 @@ TEST_CASE("async_error_handler", "[errors]]") ...@@ -81,7 +90,11 @@ TEST_CASE("async_error_handler", "[errors]]")
ofs << err_msg; ofs << err_msg;
}); });
logger->info("Good message #1"); logger->info("Good message #1");
#if !defined(SPDLOG_FMT_PRINTF)
logger->info("Bad format msg {} {}", "xxx"); logger->info("Bad format msg {} {}", "xxx");
#else
logger->info("Bad format msg %s %s", "xxx");
#endif
logger->info("Good message #2"); logger->info("Good message #2");
spdlog::drop("logger"); //force logger to drain the queue and shutdown spdlog::drop("logger"); //force logger to drain the queue and shutdown
spdlog::set_sync_mode(); spdlog::set_sync_mode();
......
...@@ -12,9 +12,13 @@ TEST_CASE("simple_file_logger", "[simple_logger]]") ...@@ -12,9 +12,13 @@ TEST_CASE("simple_file_logger", "[simple_logger]]")
auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename); auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename);
logger->set_pattern("%v"); logger->set_pattern("%v");
#if !defined(SPDLOG_FMT_PRINTF)
logger->info("Test message {}", 1); logger->info("Test message {}", 1);
logger->info("Test message {}", 2); logger->info("Test message {}", 2);
#else
logger->info("Test message %d", 1);
logger->info("Test message %d", 2);
#endif
logger->flush(); logger->flush();
REQUIRE(file_contents(filename) == std::string("Test message 1\nTest message 2\n")); REQUIRE(file_contents(filename) == std::string("Test message 1\nTest message 2\n"));
REQUIRE(count_lines(filename) == 2); REQUIRE(count_lines(filename) == 2);
...@@ -33,8 +37,13 @@ TEST_CASE("flush_on", "[flush_on]]") ...@@ -33,8 +37,13 @@ TEST_CASE("flush_on", "[flush_on]]")
logger->trace("Should not be flushed"); logger->trace("Should not be flushed");
REQUIRE(count_lines(filename) == 0); REQUIRE(count_lines(filename) == 0);
#if !defined(SPDLOG_FMT_PRINTF)
logger->info("Test message {}", 1); logger->info("Test message {}", 1);
logger->info("Test message {}", 2); logger->info("Test message {}", 2);
#else
logger->info("Test message %d", 1);
logger->info("Test message %d", 2);
#endif
logger->flush(); logger->flush();
REQUIRE(file_contents(filename) == std::string("Should not be flushed\nTest message 1\nTest message 2\n")); REQUIRE(file_contents(filename) == std::string("Should not be flushed\nTest message 1\nTest message 2\n"));
REQUIRE(count_lines(filename) == 3); REQUIRE(count_lines(filename) == 3);
...@@ -47,7 +56,13 @@ TEST_CASE("rotating_file_logger1", "[rotating_logger]]") ...@@ -47,7 +56,13 @@ TEST_CASE("rotating_file_logger1", "[rotating_logger]]")
auto logger = spdlog::rotating_logger_mt("logger", basename, 1024, 0); auto logger = spdlog::rotating_logger_mt("logger", basename, 1024, 0);
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
{
#if !defined(SPDLOG_FMT_PRINTF)
logger->info("Test message {}", i); logger->info("Test message {}", i);
#else
logger->info("Test message %d", i);
#endif
}
logger->flush(); logger->flush();
auto filename = basename; auto filename = basename;
...@@ -67,7 +82,13 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]") ...@@ -67,7 +82,13 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
auto filename = basename; auto filename = basename;
REQUIRE(count_lines(filename) == 10); REQUIRE(count_lines(filename) == 10);
for (int i = 0; i < 1000; i++) for (int i = 0; i < 1000; i++)
{
#if !defined(SPDLOG_FMT_PRINTF)
logger->info("Test message {}", i); logger->info("Test message {}", i);
#else
logger->info("Test message %d", i);
#endif
}
logger->flush(); logger->flush();
REQUIRE(get_filesize(filename) <= 1024); REQUIRE(get_filesize(filename) <= 1024);
...@@ -88,7 +109,13 @@ TEST_CASE("daily_logger", "[daily_logger]]") ...@@ -88,7 +109,13 @@ TEST_CASE("daily_logger", "[daily_logger]]")
auto logger = spdlog::daily_logger_mt("logger", basename, 0, 0); auto logger = spdlog::daily_logger_mt("logger", basename, 0, 0);
logger->flush_on(spdlog::level::info); logger->flush_on(spdlog::level::info);
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
{
#if !defined(SPDLOG_FMT_PRINTF)
logger->info("Test message {}", i); logger->info("Test message {}", i);
#else
logger->info("Test message %d", i);
#endif
}
auto filename = w.str(); auto filename = w.str();
REQUIRE(count_lines(filename) == 10); REQUIRE(count_lines(filename) == 10);
...@@ -110,7 +137,13 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger_dateonly]]") ...@@ -110,7 +137,13 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger_dateonly]]")
auto logger = spdlog::create<sink_type>("logger", basename, 0, 0); auto logger = spdlog::create<sink_type>("logger", basename, 0, 0);
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
{
#if !defined(SPDLOG_FMT_PRINTF)
logger->info("Test message {}", i); logger->info("Test message {}", i);
#else
logger->info("Test message %d", i);
#endif
}
logger->flush(); logger->flush();
auto filename = w.str(); auto filename = w.str();
REQUIRE(count_lines(filename) == 10); REQUIRE(count_lines(filename) == 10);
...@@ -142,7 +175,13 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger_custom]]") ...@@ -142,7 +175,13 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger_custom]]")
auto logger = spdlog::create<sink_type>("logger", basename, 0, 0); auto logger = spdlog::create<sink_type>("logger", basename, 0, 0);
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
{
#if !defined(SPDLOG_FMT_PRINTF)
logger->info("Test message {}", i); logger->info("Test message {}", i);
#else
logger->info("Test message %d", i);
#endif
}
logger->flush(); logger->flush();
auto filename = w.str(); auto filename = w.str();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment