• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

docs/H03-May-2022-

glog_bench/H03-May-2022-

glog_example/H03-May-2022-

images/H03-May-2022-

loguru_bench/H03-May-2022-

loguru_example/H03-May-2022-

test/H03-May-2022-

.gitignoreH A D09-Apr-201826

README.mdH A D09-Apr-201814.1 KiB

appveyor.ymlH A D09-Apr-2018326

loguru.hppH A D03-May-202298.9 KiB

README.md

1# Loguru: a header-only C++ logging library.
2
3[![Build status](https://ci.appveyor.com/api/projects/status/hret4rx3xakjs7j4?svg=true)](https://ci.appveyor.com/project/emilk/loguru)
4
5## At a glance
6
7![Loguru terminal output](images/terminal_colors.png)
8
9## Documentation
10Documentation can be found at https://emilk.github.io/loguru/index.html.
11
12## License
13This software is in the public domain. Where that dedication is not recognized, you are granted a perpetual, irrevocable license to copy and modify this file as you see fit.
14
15That being said, I would appreciate credit!
16If you find Loguru useful, tweet me at @ernerfeldt mail me at emil.ernerfeldt@gmail.com.
17
18## Why another logging library?
19I have yet to come across a nice, light-weight logging library for C++ that does everything I want. So I made one!
20
21In particular, I want logging that produces logs that are both human-readable and easily grep:ed. I also want to be able to hook into the logging process to print some of the more severe messages on-screen in my app (for dev-purposes).
22
23## Features:
24* Header only
25	* No linking woes! Just include and enjoy.
26* Small, simple library.
27	* Small header with no `#include`s for **fast compile times** (see separate heading).
28	* No dependencies.
29	* Cross-platform
30* Flexible:
31	* User can install callbacks for logging (e.g. to draw log messages on screen in a game).
32	* User can install callbacks for fatal error (e.g. to pause an attached debugger or throw an exception).
33* Support multiple file outputs, either trunc or append:
34	* e.g. a logfile with just the latest run at low verbosity (high readability).
35	* e.g. a full logfile at highest verbosity which is appended to on every run.
36* Full featured:
37	* Verbosity levels.
38	* Supports assertions: `CHECK_F(fp != nullptr, "Failed to open '%s'", filename)`
39	* Supports abort: `ABORT_F("Something went wrong, debug value is %d", value)`.
40* Stack traces printed on abort.
41	* Stack traces are cleaned up somewhat.
42		* Before cleanup: `some_function_name(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&)`
43		* After cleanup: `some_function_name(std::vector<std::string> const&)`
44	* Stack traces are printed [the right way](http://yellerapp.com/posts/2015-01-22-upside-down-stacktraces.html):
45		* Chronological order with the most relevant at the end.
46* (most) signals writes stack traces.
47* Fast:
48	- When configured in unbuffered mode (loguru::g_flush_interval_ms = 0):
49		+ 6-8 us when logging to stderr + file (rMBP + SSD + Clang).
50		+ About 25%-75% faster than GLOG on my MacBook Pro (Clang).
51		+ About the same as GLOG on my Linux Desktop (GCC).
52	- With loguru::g_flush_interval_ms set to ~100 ms:
53		+ 3-5 us when logging to stderr + file (rMBP + SSD + Clang).
54		+ About twice as fast as GLOG.
55* Drop-in replacement for most of GLOG (except for setup code).
56* Choose between using printf-style or std::cout-style formatting.
57* Compile-time checked printf-formating (on supported compilers).
58* Support for [fmtlib](https://github.com/fmtlib/fmt) formatting.
59	* Add `#define LOGURU_USE_FMTLIB 1`, before including `loguru.hpp`
60	* You also need to set up the `fmtlib` include directory for building as well as linking against `fmtlib`, alternatively use the `FMT_HEADER_ONLY` preprocessor definition.
61* Assertion failures are marked with `noreturn` for the benefit of the static analyzer and optimizer.
62* All logging also written to stderr.
63	* With colors on supported terminals.
64* Thread-safe.
65* Can be configured to either:
66	* Flush every `loguru::g_flush_interval_ms` in a background thread
67	* Flushes output on each call so you won't miss anything even on hard crashes (and still faster than buffered GLOG!).
68* Prefixes each log line with:
69	* Date and time to millisecond precision.
70	* Application uptime to millisecond precision.
71	* Thread name or id (you can set the name with `loguru::set_thread_name`).
72	* File and line.
73	* Log level.
74	* Indentation (see *Scopes*).
75* Error context:
76	* Catch the values of local variables and print them only on a crash (see *Error context*).
77* Scopes (see *Scopes*).
78* grep:able logs:
79	* Each line has all the info you need (e.g. date).
80	* You can easily filter out high verbosity levels after the fact.
81
82## Compiling
83
84Just include <loguru.hpp> where you want to use Loguru.
85Then, in one .cpp file:
86``` C++
87	#define LOGURU_IMPLEMENTATION 1
88	#include <loguru.hpp>
89```
90Make sure you compile with `-std=c++11 -lpthread -ldl` on relevant environments.
91
92## Usage
93
94``` C++
95#include <loguru.hpp>
96...
97// Optional, but useful to time-stamp the start of the log.
98// Will also detect verbosity level on command line as -v.
99loguru::init(argc, argv);
100
101// Put every log message in "everything.log":
102loguru::add_file("everything.log", loguru::Append, loguru::Verbosity_MAX);
103
104// Only log INFO, WARNING, ERROR and FATAL to "latest_readable.log":
105loguru::add_file("latest_readable.log", loguru::Truncate, loguru::Verbosity_INFO);
106
107// Only show most relevant things on stderr:
108loguru::g_stderr_verbosity = 1;
109
110LOG_SCOPE_F(INFO, "Will indent all log messages within this scope.");
111LOG_F(INFO, "I'm hungry for some %.3f!", 3.14159);
112LOG_F(2, "Will only show if verbosity is 2 or higher");
113VLOG_F(get_log_level(), "Use vlog for dynamic log level (integer in the range 0-9, inclusive)");
114LOG_IF_F(ERROR, badness, "Will only show if badness happens");
115auto fp = fopen(filename, "r");
116CHECK_F(fp != nullptr, "Failed to open file '%s'", filename);
117CHECK_GT_F(length, 0); // Will print the value of `length` on failure.
118CHECK_EQ_F(a, b, "You can also supply a custom message, like to print something: %d", a + b);
119
120// Each function also comes with a version prefixed with D for Debug:
121DCHECK_F(expensive_check(x)); // Only checked #if !NDEBUG
122DLOG_F(INFO, "Only written in debug-builds");
123
124// Turn off writing to stderr:
125loguru::g_stderr_verbosity = loguru::Verbosity_OFF;
126
127// Turn off writing err/warn in red:
128loguru::g_colorlogtostderr = false;
129
130// Throw exceptions instead of aborting on CHECK fails:
131loguru::set_fatal_handler([](const loguru::Message& message){
132	throw std::runtime_error(std::string(message.prefix) + message.message);
133});
134```
135
136If you prefer logging with streams:
137
138``` C++
139#define LOGURU_WITH_STREAMS 1
140#include <loguru.hpp>
141...
142LOG_S(INFO) << "Look at my custom object: " << a.cross(b);
143CHECK_EQ_S(pi, 3.14) << "Maybe it is closer to " << M_PI;
144```
145
146## Configuration options
147
148Before including `<loguru.hpp>` you may #define the following
149configuration options to 1:
150
151`LOGURU_DEBUG_LOGGING` (default 1 #if !NDEBUG, else 0):
152
153	Enables debug versions of logging statements.
154
155`LOGURU_DEBUG_CHECKS` (default 1 #if !NDEBUG, else 0):
156
157	Enables debug versions of checks.
158
159`LOGURU_REDEFINE_ASSERT` (default 0):
160
161	Redefine "assert" to call Loguru version instead (!NDEBUG only).
162
163`LOGURU_WITH_STREAMS` (default 0):
164
165	Add support for _S versions for all LOG and CHECK functions:
166		LOG_S(INFO) << "My vec3: " << x.cross(y);
167		CHECK_EQ_S(a, b) << "I expected a and b to be the same!";
168	This is off by default to keep down compilation times.
169
170`LOGURU_REPLACE_GLOG` (default 0):
171
172	Make Loguru mimic GLOG as close as possible,
173	including #defining LOG, CHECK, VLOG_IS_ON etc.
174	LOGURU_REPLACE_GLOG implies LOGURU_WITH_STREAMS.
175
176`LOGURU_UNSAFE_SIGNAL_HANDLER` (default 1):
177
178	Make Loguru try to do unsafe but useful things,
179	like printing a stack trace, when catching signals.
180	This may lead to bad things like deadlocks in certain situations.
181
182`LOGURU_USE_FMTLIB` (default 0):
183
184	Use fmtlib formatting. See https://github.com/fmtlib/fmt
185	This will make loguru.hpp depend on <fmt/format.h>
186	You will need to link against `fmtlib` or use the `FMT_HEADER_ONLY` preprocessor definition.
187	Feature by kolis (https://github.com/emilk/loguru/pull/22)
188
189`LOGURU_WITH_FILEABS` (default 0):
190
191	When LOGURU_WITH_FILEABS is defined, a check of file change
192	will be performed on every call to file_log.  If the file is
193	moved, or inode changes, file is reopened using the same
194	FileMode as is done by add_file.  Such a scheme is useful if
195	you have a daemon program that moves the log file every 24
196	hours and expects new file to be created.  Feature by scinart
197	(https://github.com/emilk/loguru/pull/23).
198
199`LOGURU_STACKTRACES` (default 1 on supported platforms):
200
201	Print stack traces on abort.
202
203`LOGURU_RTTI` (try to detect automatically by default):
204
205	Set to 0 if your platform does not support runtime type information (-fno-rtti).
206
207
208## Grep:able logs
209``` bash
210# Only show warnings, errors and fatal messages:
211cat logfile.txt | egrep "[^0-9]\|"
212
213# Ignore verbosity-levels 4 and above:
214cat logfile.txt | egrep "[^4-9]\|"
215
216# Only show verbosity-level 6:
217cat logfile.txt | egrep "6\|"
218
219# Only show messages from the main thread:
220cat logfile.txt | egrep "\[main thread     \]"
221```
222
223## No includes in loguru.h
224I abhor logging libraries that `#include`'s everything from `iostream` to `windows.h` into every compilation unit in your project. Logging should be frequent in your source code, and thus as lightweight as possible. Loguru's header has *no #includes*. This means it will not slow down the compilation of your project.
225
226In a test of a medium-sized project, including `loguru.hpp` instead of `glog/logging.hpp` everywhere gave about 10% speedup in compilation times.
227
228Note, however, that this gives you the bare-bones version of Loguru with printf-style logging. If you want std::ostream style logging (or GLOG functionality) you need to `#define LOGURU_WITH_STREAMS 1` before `#include <loguru.hpp>`, and that will make loguru.hpp include `<sstream>`. No away around it!
229
230## Scopes
231The library supports scopes for indenting the log-file. Here's an example:
232
233``` C++
234int main(int argc, char* argv[])
235{
236	loguru::init(argc, argv);
237	LOG_SCOPE_FUNCTION(INFO);
238	LOG_F(INFO, "Doing some stuff...");
239	for (int i=0; i<2; ++i) {
240		VLOG_SCOPE_F(1, "Iteration %d", i);
241		auto result = some_expensive_operation();
242		LOG_IF_F(WARNING, result == BAD, "Bad result");
243	}
244	LOG_F(INFO, "Time to go!");
245	return 0;
246}
247```
248
249This will output:
250
251```
252date       time         ( uptime  ) [ thread name/id ]                   file:line     v|
2532015-10-04 15:28:30.547 (   0.000s) [main thread     ]             loguru.cpp:184      0| arguments:       ./loguru_test test -v1
2542015-10-04 15:28:30.548 (   0.000s) [main thread     ]             loguru.cpp:185      0| Verbosity level: 1
2552015-10-04 15:28:30.548 (   0.000s) [main thread     ]             loguru.cpp:186      0| -----------------------------------
2562015-10-04 15:28:30.548 (   0.000s) [main thread     ]        loguru_test.cpp:108      0| { int main_test(int, char **)
2572015-10-04 15:28:30.548 (   0.000s) [main thread     ]        loguru_test.cpp:109      0| .   Doing some stuff...
2582015-10-04 15:28:30.548 (   0.000s) [main thread     ]        loguru_test.cpp:111      1| .   { Iteration 0
2592015-10-04 15:28:30.681 (   0.133s) [main thread     ]        loguru_test.cpp:111      1| .   } 0.133 s: Iteration 0
2602015-10-04 15:28:30.681 (   0.133s) [main thread     ]        loguru_test.cpp:111      1| .   { Iteration 1
2612015-10-04 15:28:30.815 (   0.267s) [main thread     ]        loguru_test.cpp:113      0| .   .   Bad result
2622015-10-04 15:28:30.815 (   0.267s) [main thread     ]        loguru_test.cpp:111      1| .   } 0.134 s: Iteration 1
2632015-10-04 15:28:30.815 (   0.267s) [main thread     ]        loguru_test.cpp:115      0| .   Time to go!
2642015-10-04 15:28:30.815 (   0.267s) [main thread     ]        loguru_test.cpp:108      0| } 0.267 s: int main_test(int, char **)
265```
266
267Which looks like this in the terminal:
268
269![Terminal colors](images/terminal_colors.png)
270
271(Notice how verbosity levels higher than 0 are slightly gray).
272
273Scopes affects logging on all threads.
274
275
276## Error context
277A stack trace gives you the names of the function at the point of a crash. With `ERROR_CONTEXT`, you can also get the values of select local variables. `ERROR_CONTEXT` is in effect a logging that only occurs if there is a crash.
278
279Usage:
280
281``` C++
282void process_customers(const std::string& filename)
283{
284    ERROR_CONTEXT("Processing file", filename.c_str());
285    for (size_t i = 0; i < num_customers; ++i) {
286	    ERROR_CONTEXT("Customer index", i);
287	    if (i == 42) { crashy_code(); }
288    }
289}
290```
291
292The context is in effect during the scope of the `ERROR_CONTEXT`.
293To get the contents of the stack manually, use `loguru::get_error_context()`.
294
295Example result:
296
297	------------------------------------------------
298	[ErrorContext]                main.cpp:416   Processing file:    "customers.json"
299	[ErrorContext]                main.cpp:417   Customer index:     42
300	------------------------------------------------
301
302Error contexts are printed automatically on crashes. Note that values captured by `ERROR_CONTEXT` are **only printed on a crash**. They do not litter the log file otherwise. They also have a very small performance hit (about 12 nanoseconds per `ERROR_CONTEXT` on my MacBook Pro, compared to about 4-7 milliseconds a line in the logfile).
303
304`ERROR_CONTEXT` works with built-in types (`float`, `int`, `char` etc) as well as `const char*`. You can also add support for your own types by overloading `loguru::ec_to_text` (see [`loguru.hpp`](https://github.com/emilk/loguru/blob/master/loguru.hpp) for details).
305
306The `ERROR_CONTEXT` feature of Loguru is actually orthogonal to the logging. If you want to, you can use Loguru just for its `ERROR_CONTEXT` (and use some other library for logging). You can print the error context stack at any time like this:
307
308```
309auto text = loguru::get_error_context();
310printf("%s", text.c_str());
311some_stream << text.c_str(); // Or like this
312```
313
314## Streams vs printf#
315Some logging libraries only supports stream style logging, not printf-style. This means that what in Loguru is:
316
317``` C++
318LOG_F(INFO, "Some float: %+05.3f", number);
319```
320
321in Glog becomes something along the lines of:
322
323``` C++
324LOG(INFO) << "Some float: " << std::setfill('0') << std::setw(5) << std::setprecision(3) << number;
325```
326
327Loguru allows you to use whatever style you prefer.
328
329
330## Limitations and TODO
331* Rename ERROR to avoid conflict with windows.h macro?
332* File-only logging: LOG_F(FILE, "Always written to file, never to stderr")
333* Windows limitations:
334	* No stack-traces (you can add them yourself with `loguru::set_fatal_handler`).
335	* No signal handlers.
336