gabime / spdlog Goto Github PK
View Code? Open in Web Editor NEWFast C++ logging library.
License: Other
Fast C++ logging library.
License: Other
would be very cool to have an option to output source file + line no in debug logging. is it easily doable? thx
Currently the async_sink have a single back thread to do it's job.
Thread pool might give extra perf boost in some cases where (over the network for example)
I've tried using spdlog
and cppformat
simultaneously. But 1st do #include spdlog/spdlog.h
cause error.
#define FMT_HEADER_ONLY
in spdlog
cause some functions (in the anonymous namespace) were declared twice.
It would be nice if there was a macro only interface to the logger, so that it could easily be removed from a whole project.
because of
_priorities[static_cast(level::ALWAYS)] = LOG_INFO;
in spdlog/sinks/syslog_sinks.h
from commit log I think this line can be safely removed ?
hi, I 'd like to use spdlog in vs2013, is "format.cc " required ?and are all files (except format.cc ) needed?
looking forward for your reply.thanks.
Not sure when this changed but my custom types are no longer streamable to the log. Is there an acceptable alternative?
@gabime:
Would you consider writing some unit/regression tests and a .travis.yml
file so that they run on each git push? I had to fix a few minor bugs last time I did a git subtree pull
. I'd especially like to see the bench
program run on each git push
on travis-ci so we can easily see if a commit introduces any performance regressions.
Here is an example C++11 project .travis.yml
file you could base yours off of, if you've never used travis-ci before, it's super straightforward to get started:
https://github.com/zaphoyd/websocketpp/blob/master/.travis.yml
I do not have time to do this myself right now or I'd submit this as a pull request. If I have time this summer, I'll add some performance/unit tests as well, but maybe you could start with lightly modified versions of the example or bench programs that output the max message rate/sec, time to log 1,000,000 entries with each of the various logging methods (sync st file, async mt file, async st file, etc.)? Then move on to unit tests of the public API?
If you don't have time, thanks again for taking your time to write this library in the first place. :-)
I am looking to create a log file in an xml or json format, but this requires some file header and footer information.
To do this, I need to add the header only once when the file is created and then put in the footer as the file is closed (but also remove it if it was there previously, so that it appends new entries properly). Is this something that can be added?
Changing the global log level only changes the output of already created loggers, but loggers created after changing the global level still use the default level.
Fixing it should be easy; in registry.h add the following line to the implementation of set_level
:
_level = log_level;
because it is impossible to handle log level runtime otherwise.
E.g. I would like to have a file logger, but that at compile-time/run-time would also display the output to the screen. I can achieve this by wrapping two loggers. But I could also do this by having a single logger with 2 sinks and setting the level to the console sink to on
/off
(i.e. having a different level per sink in the logger with multiple sinks).
I think wrapping two different loggers is better, but without documentation about loggers with multiple sinks it is hard to know what is the best way to achieve what I want to do.
I am trying to write a logger that outputs in different formats (JSON, XML, Text, etc). To do so, I need to initially write out a opening tag, then log the entries, then write a closing tag. I attempted to do this by setting the pattern on instantiation and then during destruction, but I seem to be running into issues, and the set_pattern seems to reset the file.
Can the pattern be changed dynamically?
Edit: It was an oops on my side...I accidentally did not initialize the SizeInMB variable and it ended up writing a new log entry for every record.
In async mode the formatting is done in the worker thread and hence the call std::this_thread::get_id() in pattern_formatter_impl.h returns id of the worker thread.
Possible fix: add thread id to the async_msg struct and pass it to the worker (only if it doesn't hurt performance, otherwise, find other solution)
Hi. I'm new spdlog user & English :)
I met this error message.
I want use this great logging library!! (love async mod logging!!)
my OSX g++ version
g++ --version ✚ ✱ ◼
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
"/Applications/CLion EAP.app/Contents/bin/cmake/bin/cmake" --build /Users/md/Library/Caches/clion10/cmake/generated/34156cd6/34156cd6/Debug --target timo_echoes -- -j 4
Scanning dependencies of target timo_echoes
[100%] Building CXX object CMakeFiles/timo_echoes.dir/main.cpp.o
In file included from /Users/md/Documents/workspace/timo-echoes/main.cpp:22:
In file included from /Users/md/Documents/workspace/timo-echoes/spdlog/include/spdlog/spdlog.h:34:
In file included from /Users/md/Documents/workspace/timo-echoes/spdlog/include/spdlog/logger.h:36:
In file included from /Users/md/Documents/workspace/timo-echoes/spdlog/include/spdlog/sinks/base_sink.h:35:
In file included from /Users/md/Documents/workspace/timo-echoes/spdlog/include/spdlog/sinks/./sink.h:27:
In file included from /Users/md/Documents/workspace/timo-echoes/spdlog/include/spdlog/sinks/../details/log_msg.h:28:
In file included from /Users/md/Documents/workspace/timo-echoes/spdlog/include/spdlog/sinks/../details/./format.h:2880:
/Users/md/Documents/workspace/timo-echoes/spdlog/include/spdlog/sinks/../details/format.cc:145:11: error: cannot initialize a variable of type 'char *' with an rvalue of type 'int'
char *message = strerror_r(error_code, buffer, buffer_size);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
make[3]: *** [CMakeFiles/timo_echoes.dir/main.cpp.o] Error 1
make[2]: *** [CMakeFiles/timo_echoes.dir/all] Error 2
make[1]: *** [CMakeFiles/timo_echoes.dir/rule] Error 2
make: *** [timo_echoes] Error 2
Compiling examples on mingw
cd example
make --makefile=Makefile.mingw all
Fails due to an missing syslog sink on windows
Quick fix: Wrap function include/spdlog/details/spdlog_impl.h:88
#ifdef __linux__
// Create syslog logger
inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& logger_name)
{
return create<spdlog::sinks::syslog_sink>(logger_name);
}
#endif
Or create dummy windows impl in syslog_sink.h - skip syslog.h include and make log function empty on windows?
namespace level
{
typedef enum
{
trace = 0,
debug = 1,
info = 2,
notice = 3,
warn = 4,
err = 5,
critical = 6,
alert = 7,
emerg = 8,
off = 9
} level_enum;
Compiling the current head of spdlog in my project throws the following error
out/g++-debug/testbed/TestbedARAClient.o: In function `spdlog::details::os::now()':
/home/mfrey/testbed/ara-sim/spdlog/include/spdlog/sinks/../details/./os.h:51:
undefined reference to `clock_gettime'
collect2: error: ld returned 1 exit status
Makefile:251: recipe for target 'out/g++-debug/testbed/TestbedDaemon' failed
make: *** [out/g++-debug/testbed/TestbedDaemon] Error 1
Apparently, this can be solved adding -lrt
to the linker flags in the makefile. If I compile the code on my development machine (without adding the -lrt
flag and using clang++) the code compiles fine nevertheless. I'm not sure if this is an issue with the fairly old Debian on the server (I'm working on)? However, I thought it might be helpful for somebody who runs into the same issue.
By walking the code-base I've checked that differently named console loggers like spd::stdout_logger_mt("A")
, spd::stdout_logger_mt("B")
, ..
. seem to create a stdout_sink_mt
for each. Each will be protected by independent std::mutex
s right? So,
I ask this because if this is the behaviour that has been implemented, it's quite likely that a user will not expect that by having multiple named multi-threaded stdout loggers they won't be in sync solely because of their name.
=77204== 4,096 bytes in 1 blocks are definitely lost in loss record 823 of 856
==77204== at 0x10014B5CB: malloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==77204== by 0x1017BE856: __smakebuf (in /usr/lib/system/libsystem_c.dylib)
==77204== by 0x1017D33A7: __swsetup (in /usr/lib/system/libsystem_c.dylib)
==77204== by 0x1017BDAF0: __sfvwrite (in /usr/lib/system/libsystem_c.dylib)
==77204== by 0x1017BE0CA: fwrite (in /usr/lib/system/libsystem_c.dylib)
==77204== by 0x1000665E5: spdlog::details::file_helper::write(spdlog::details::log_msg const&) [clone .lto_priv.91](in ./dist/Debug/GNU-MacOSX/lightq)
==77204== by 0x100002B06: spdlog::sinks::rotating_file_sinkstd::mutex::_sink_it(spdlog::details::log_msg const&) [clone .lto_priv.258](in ./dist/Debug/GNU-MacOSX/lightq)
==77204== by 0x100001E9B: spdlog::sinks::base_sinkstd::mutex::log(spdlog::details::log_msg const&) [clone .lto_priv.257](in ./dist/Debug/GNU-MacOSX/lightq)
==77204== by 0x10006B0D1: spdlog::logger::_log_msg(spdlog::details::log_msg&) [clone .lto_priv.2365](in ./dist/Debug/GNU-MacOSX/lightq)
==77204== by 0x10006ABCF: spdlog::details::line_logger::~line_logger() [clone .lto_priv.2016](in ./dist/Debug/GNU-MacOSX/lightq)
I've setup spdlog the following way:
shared_ptr<logger> init_logger(const Settings& settings) {
spdlog::set_level(spdlog::level::debug);
try {
return rotating_logger_mt(kAppName,
settings.logfile,
settings.max_file_size,
settings.max_files,
false);
}catch (const spdlog_ex& e) {
throw logic_error(e.what());
}
}
with settings.logfile
, settings.max_file_size
and settings.max_files
being
logfile = emperor.log
max_file_size = 10
max_files = 10
I'm only using it in a main.cpp file and call it the following way:
uv_loop_t* loop = uv_default_loop();
try {
// Init logging.
logging = init_logger(settings);
logging->info() << "Init logger";
stringstream error;
uv_pipe_t server;
uint16_t retrn = uv_pipe_init(loop, &server, 0);
logging->info() << "Init pipe";
if (retrn < 0) {
error << "Error initializing pipe: " << uv_strerror(retrn);
logging->error(error.str().c_str());
throw logic_error(error.str());
}
retrn = uv_pipe_bind(&server, settings.socket_file.c_str());
logging->info() << "Bind to pipe";
if (retrn < 0) {
error << "Error binding to socket " << settings.socket_file << ": " << uv_strerror(retrn);
logging->error(error.str().c_str());
throw logic_error(error.str());
}
retrn = uv_listen((uv_stream_t*) &server, 128, on_new_connection);
logging->info() << "Listen on pipe";
if (retrn < 0) {
error << "Listen error: " << uv_strerror(retrn);
logging->error(error.str().c_str());
throw logic_error(error.str());
}
}catch(const logic_error& e) {
logging->error() << e.what();
return 2;
}
The problem is that each call to logging->info()
seems to generate a new log file so after my program has run I end up with several log files: emperor.txt
, emperor.1.txt
, emperor.2.txt
.
Easily extendable with custom log targets (just implement a single function in the sink interface).
E.g. an example for a single file logger (no-rotatory file logger) should be easy to add.
Currently the library supports thread ids but not PID. I think that even thought it's a repetitive information, it may be useful for later querying stored logs by PID. I'm asking since I see some other libraries support this, and I believe this is one of the reasons.
It would be nice to use spdlog from Rust (and perhaps other languages with a C FFI).
:-)
When spdlog is used in multiple translation units it produces linking errors of already defined functions.
Patchfile is posted here http://pastebin.com/wnY79GTz
Hello,
On my system (debian Jessie, g++ 4.9.1) the provided examples compiles with warnings.
I am not sure how to fix theses (expect disabling the unused-parameter
warnings). This may be annoying for project using spdlog, as it clutter the build log.
Here is my build log: https://gist.github.com/xaqq/8cafb1c2d787e0090f3f
Thanks,
Add a built-in logger to std::clog
to match the stderr
and stdout
loggers.
In format.h
, there are a pair of constructors that are made private to avoid the streaming of [const] volatile char *:
// The following two methods are private to disallow formatting of
// arbitrary pointers. If you want to output a pointer cast it to
// "void *" or "const void *". In particular, this forbids formatting
// of "[const] volatile char *" which is printed as bool by iostreams.
// Do not implement!
template <typename T>
MakeValue(const T *value);
template <typename T>
MakeValue(T *value);
In all cases besides these, the user just wants to see the hex value for the pointer anyway so I think the restriction created by these private constructors is too onerous and the goal could be achieved by making private constructors that overload on [const] volatile char *
unless I'm missing something totally obvious.
I noticed that daily logger emptied the log file if I stop the program and then restart it.
For my project I need all log to be preserved, but I find no argument to do that, so I simply change "wb" to "ab" ...
I have an application that logs network calls so it is at the very lowest level. Within this trace, a password may appear, usually in some pattern like <password>whatever</password>
. I couldn't think of a sanctioned way to turn this into <password>[redacted]</password>
so it doesn't mean there isn't one, but if there isn't, I'd like there to be!
Other logging frameworks have this. I wonder if a compiled regex would be sufficient.
Hi,
I've got the "issue" that the logging output (file logger) is not written immediately to the logfile. I'm wondering if it is possible to "flush" from time to time the logging output to the file?
I've also got the weird behavior that the console logging ist not writen immediatly to stdout. Is that on purpose or is this most likely an issue in my code?
Thanks in advance!
Best,
Michael
Loggers usually have an option to change rolling time, 00:00 is currently the only option in spdlog.
A list with links to their implementations would already be helpful.
is spdlog meant to be thread-safe?
I have 3 loggers in multiple threads and the output in the console looks a little messed up like this:
[11:52:57] [logger1] [info] some log message
[[1111::5522::5577]] [[lwneoggseoa1k]e 2r[]n o[tiincfeo]] ENnoO cdeaatna Lteoa rsneMnodd
e ON
it should more look like
[11:52:58] [logger1] [info] some log message
[11:52:58] [logger2] [info] another log message
[11:52:58] [logger3] [notice] the last log message
when cross compiling the project with a gcc 4.8.2. i do get the error message:
./src/async_log_helper.h:273:22: error: 'yield' was not declared in this scope
When compiling on mac against clang LLVM 3.5, I have the following compilation error,
spdlog/include/spdlog/sinks/../details/./os.h:188:12: error: cannot initialize return object of type 'size_t' (aka 'unsigned long') with an rvalue of type 'pthread_t' (aka '_opaque_pthread_t *')
return pthread_self();
if you look at the file os.h
, under the function:
inline size_t thread_id()
{
#ifdef SPDLOG_NO_THREAD_ID
return 0;
#else
#ifdef _WIN32
return ::GetCurrentThreadId();
#elif __linux__
return syscall(SYS_gettid);
#else
return pthread_self();
#endif
#endif //SPDLOG_NO_THREAD_ID
}
spdlog attempts to return the struct pthread_t
which resolves to a pointer of type _opaque_pthread_t *
of the current thread as the thread id however there is no implicit conversion for this to size_t
. A workaround is to cast the pointer to size_t
.
I'm sorry this is not a real issue rather a question, but I'm trying to understand how to modify the locale used by spdlog but I haven't been able to find locale or imbue function inside of it.
But given
double theta = -0.142566
cout << theta;
prints -0.142566
while
log.error() << theta;
prints -0,142566
Using 4.9.1 mingw64 and building examples
make all in examples dir doesn't find 'makefile'. Recapitalise to 'Makefile' and all OK
details/os.h uses GetDynamicTimeZoneInfo from windows.h
mingw defaults to _WIN32_WINNT=0x502 (XP) so doesn't find this newer api
a) Adjust Makefile to add -D_WIN32_WINNT=0x600 or
b) add logic into os.h to cater for this or adapt to XP targets by using a different API
inline int utc_minutes_offset(const std::tm& tm = localtime())
{
(void)tm; // avoid unused param warning
Creating a queue which uses a CAS style intrusive linked list for pushed items seems like a good candidate for the async logger. It currently have multiple producers but on a single consumer.
This would allow for pushing items being a simple CAS of a pointer (with loop for conflicts) and a consumer doing the same and just revering the order of the popped data.
The overhead of using a mutex would then go away and probably improve the performance for the async logger.
Would you like to replace any double quotes by angle brackets around file names for include statements?
It would be much more pleasant to use by simply dropping that one header file into the include directory.
is there, or will there be support for STL containers like vectors?
-Werror says:
There is an errant #pragma clang diagnostic pop
at the end of details/format.h
because you are missing a clang diagnostic push
before line 105 of that file.
My application needs to fork an unknown number of processes but I want them all to log to the same file at runtime. Is it possible and advisable to share an instance of shared_ptr between all processes?
I've tried to enable the trace and debug logging using macros as shown in the example.
It seems like the level (enum) definitions have changed since the creation of these lines in the example demonstrating the macro use.
So I changed level::DEBUG
to spdlog::level::debug
and did the same for the trace. I think it is a good idea to fully state the namespace (spdlog
) because otherwise a using namespace spdlog
is necessary in order to be able to use the macros.
This way, the debug macro works fine. But the trace macro only logs the filename of the current source file.
call: SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
msg: *** [22:08:13 +01:00] [thread 10767463625927578443] example.cpp ***
This behavior results from the signature of force_log which does not expect any file or line number information but gets called this way:
call: logger->force_log(spdlog::level::TRACE, __FILE__, " #", __LINE__,": " __VA_ARGS__)
definition: force_log(level::level_enum lvl, const char* fmt, const Args&... args)
So I assume that the force_log function once accepted this kind of arguments. I couldn't find this state in the Git history. How can this be fixed? How was it intended to work?
And possibly notify somehow to the calling thread about the exception
Hi,
I'm not sure if it's a bug, or a feature, so here's the issue anyways. I've read the documentation and decided to start using spdlog in my (for now, single-threaded) project. Thus, I figured that spdlog::stdout_logger_mt won't bring me anything and spdlog::stdout_logger_st is the right choice. However, as I compiled the project, I've got a bunch of linking errors connected to pthreads. Adding -pthread or -fopenmp switch to the driver invocation fixed them.
So, the question is whether the single-threaded logger is supposed to be usable without threads at all? This is what I would have expected, and I think that it would be a fairly useful property. If not, then I beg my pardon, but it would be nice at least to have it documented.
As a corollary, is my understanding correct that if I ever go for -fopenmp, I wouldn't need threading support explicitly, as -pthread will be magically brought in by -fopenmp, or this is platform/compiler dependent?
Many thanks!
If a crash occurs, how do the unwritten log entries get flushed?
An improvement suggestion: I'd be curious to know how several members of Log4* C/C++ family (log4c, log4cxx and especially log4qt) fare on the same benchmark as the other logging libraries that you've already benchmarked :)
TIA.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.