A lightweight C++ logging library

Related tags

Logging loguru
Overview

Loguru: a lightweight and flexible C++ logging library.

Build status

At a glance

Loguru terminal output

Documentation

Documentation can be found at https://emilk.github.io/loguru/index.html.

License

This software is in the public domain. Where that dedication is not recognized, you are granted a perpetual, irrevocable license to copy, modify and distribute it as you see fit.

That being said, I would appreciate credit! If you find Loguru useful, tweet me at @ernerfeldt mail me at [email protected].

Why another logging library?

I have yet to come across a nice, light-weight logging library for C++ that does everything I want. So I made one!

In 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).

Features:

  • Simple integration
    • Just two files: loguru.hpp and loguru.cpp.
    • Either build and link loguru.cpp or just #include <loguru.cpp> in one of your own .cpp files.
  • Small, simple library.
    • Small header with no #includes for fast compile times (see separate heading).
    • No dependencies.
    • Cross-platform
  • Flexible:
    • User can install callbacks for logging (e.g. to draw log messages on screen in a game).
    • User can install callbacks for fatal error (e.g. to pause an attached debugger or throw an exception).
  • Support multiple file outputs, either trunc or append:
    • e.g. a logfile with just the latest run at low verbosity (high readability).
    • e.g. a full logfile at highest verbosity which is appended to on every run.
  • Full featured:
    • Verbosity levels.
    • Supports assertions: CHECK_F(fp != nullptr, "Failed to open '%s'", filename)
    • Supports abort: ABORT_F("Something went wrong, debug value is %d", value).
  • Stack traces printed on abort.
    • Stack traces are cleaned up somewhat.
      • 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&)
      • After cleanup: some_function_name(std::vector<std::string> const&)
    • Stack traces are printed the right way:
      • Chronological order with the most relevant at the end.
  • (most) signals writes stack traces.
  • Fast:
    • When configured in unbuffered mode (loguru::g_flush_interval_ms = 0):
      • 6-8 us when logging to stderr + file (rMBP + SSD + Clang).
      • About 25%-75% faster than GLOG on my MacBook Pro (Clang).
      • About the same as GLOG on my Linux Desktop (GCC).
    • With loguru::g_flush_interval_ms set to ~100 ms:
      • 3-5 us when logging to stderr + file (rMBP + SSD + Clang).
      • About twice as fast as GLOG.
  • Drop-in replacement for most of GLOG (except for setup code).
  • Choose between using printf-style or std::cout-style formatting.
  • Compile-time checked printf-formating (on supported compilers).
  • Support for fmtlib formatting.
    • Add #define LOGURU_USE_FMTLIB 1, before including loguru.hpp
    • 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.
  • Assertion failures are marked with noreturn for the benefit of the static analyzer and optimizer.
  • All logging also written to stderr.
    • With colors on supported terminals.
  • Thread-safe.
  • Can be configured to either:
    • Flush every loguru::g_flush_interval_ms in a background thread
    • Flushes output on each call so you won't miss anything even on hard crashes (and still faster than buffered GLOG!).
  • Prefixes each log line with:
    • Date and time to millisecond precision.
    • Application uptime to millisecond precision.
    • Thread name or id (you can set the name with loguru::set_thread_name).
    • File and line.
    • Log level.
    • Indentation (see Scopes).
  • Error context:
    • Catch the values of local variables and print them only on a crash (see Error context).
  • Scopes (see Scopes).
  • grep:able logs:
    • Each line has all the info you need (e.g. date).
    • You can easily filter out high verbosity levels after the fact.

Compiling

Just include <loguru.hpp> where you want to use Loguru. Then either compile and link with loguru.cpp or in one .cpp file: #include <loguru.cpp> Make sure you compile with -std=c++11 -lpthread -ldl on relevant environments.

Usage

#include <loguru.hpp>// Optional, but useful to time-stamp the start of the log.
// Will also detect verbosity level on command line as -v.
loguru::init(argc, argv);

// Put every log message in "everything.log":
loguru::add_file("everything.log", loguru::Append, loguru::Verbosity_MAX);

// Only log INFO, WARNING, ERROR and FATAL to "latest_readable.log":
loguru::add_file("latest_readable.log", loguru::Truncate, loguru::Verbosity_INFO);

// Only show most relevant things on stderr:
loguru::g_stderr_verbosity = 1;

LOG_SCOPE_F(INFO, "Will indent all log messages within this scope.");
LOG_F(INFO, "I'm hungry for some %.3f!", 3.14159);
LOG_F(2, "Will only show if verbosity is 2 or higher");
VLOG_F(get_log_level(), "Use vlog for dynamic log level (integer in the range 0-9, inclusive)");
LOG_IF_F(ERROR, badness, "Will only show if badness happens");
auto fp = fopen(filename, "r");
CHECK_F(fp != nullptr, "Failed to open file '%s'", filename);
CHECK_GT_F(length, 0); // Will print the value of `length` on failure.
CHECK_EQ_F(a, b, "You can also supply a custom message, like to print something: %d", a + b);

// Each function also comes with a version prefixed with D for Debug:
DCHECK_F(expensive_check(x)); // Only checked #if !NDEBUG
DLOG_F(INFO, "Only written in debug-builds");

// Turn off writing to stderr:
loguru::g_stderr_verbosity = loguru::Verbosity_OFF;

// Turn off writing err/warn in red:
loguru::g_colorlogtostderr = false;

// Throw exceptions instead of aborting on CHECK fails:
loguru::set_fatal_handler([](const loguru::Message& message){
	throw std::runtime_error(std::string(message.prefix) + message.message);
});

If you prefer logging with streams:

#define LOGURU_WITH_STREAMS 1
#include <loguru.hpp>
...
LOG_S(INFO) << "Look at my custom object: " << a.cross(b);
CHECK_EQ_S(pi, 3.14) << "Maybe it is closer to " << M_PI;

For more info, see the official documentation.

Grep:able logs

# Only show warnings, errors and fatal messages:
cat logfile.txt | egrep "[^0-9]\|"

# Ignore verbosity-levels 4 and above:
cat logfile.txt | egrep "[^4-9]\|"

# Only show verbosity-level 6:
cat logfile.txt | egrep "6\|"

# Only show messages from the main thread:
cat logfile.txt | egrep "\[main thread     \]"

No includes in loguru.hpp

I 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.

In a test of a medium-sized project, including loguru.hpp instead of glog/logging.hpp everywhere gave about 10% speedup in compilation times.

Note, 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!

Scopes

The library supports scopes for indenting the log-file. Here's an example:

int main(int argc, char* argv[])
{
	loguru::init(argc, argv);
	LOG_SCOPE_FUNCTION(INFO);
	LOG_F(INFO, "Doing some stuff...");
	for (int i=0; i<2; ++i) {
		VLOG_SCOPE_F(1, "Iteration %d", i);
		auto result = some_expensive_operation();
		LOG_IF_F(WARNING, result == BAD, "Bad result");
	}
	LOG_F(INFO, "Time to go!");
	return 0;
}

This will output:

	     loguru.cpp:184      0| arguments:       ./loguru_test test -v1
	     loguru.cpp:185      0| Verbosity level: 1
	     loguru.cpp:186      0| -----------------------------------
	loguru_test.cpp:108      0| { int main_test(int, char **)
	loguru_test.cpp:109      0| .   Doing some stuff...
	loguru_test.cpp:111      1| .   { Iteration 0
	loguru_test.cpp:111      1| .   } 0.133 s: Iteration 0
	loguru_test.cpp:111      1| .   { Iteration 1
	loguru_test.cpp:113      0| .   .   Bad result
	loguru_test.cpp:111      1| .   } 0.134 s: Iteration 1
	loguru_test.cpp:115      0| .   Time to go!
	loguru_test.cpp:108      0| } 0.267 s: int main_test(int, char **)

ERROR_CONTEXT

You can also optionally log things ONLY if there is a crash. This is a very useful feature:

	void process_file(const char* filename)
	{
		ERROR_CONTEXT("filename", filename);
		parse_file(filename); // Only if this crashes will filename be logged.
	}

Streams vs printf

Some logging libraries only supports stream style logging, not printf-style. This means that what in Loguru is:

LOG_F(INFO, "Some float: %+05.3f", number);

in Glog becomes something along the lines of:

LOG(INFO) << "Some float: " << std::setfill('0') << std::setw(5) << std::setprecision(3) << number;

Loguru allows you to use whatever style you prefer.

Comments
  • compile error vs2013

    compile error vs2013

    Hi, how to work around this error?

    http://stackoverflow.com/questions/24573963/move-constructor-invalid-type-for-defaulted-constructor-vs-2013

    loguru.h(452): error C2610: 'loguru::LogScopeRAII::LogScopeRAII(loguru::LogScopeRAII &&)' : is not a special member function which can be defaulted

        // Helper class for LOG_SCOPE_F
        class LogScopeRAII
        {
        public:
            LogScopeRAII() : _file(nullptr) {} // No logging
            LogScopeRAII(Verbosity verbosity, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, ...) LOGURU_PRINTF_LIKE(5, 6);
            ~LogScopeRAII();
    
            LogScopeRAII(LogScopeRAII&& other) = default;                       //  here
    
    opened by sailfish009 9
  • Allow custom level names in log output and arg parsing.

    Allow custom level names in log output and arg parsing.

    This patch adds the ability to set a custom name for each log level.

    My only concern is that it adds a bit of overhead by introducing more mutex locks, but this is worthwhile for the improved readability in our application. C++17's shared_mutex would likely make this a non-issue, since the most frequent accessed are for reading only. But for now, this just locks the existing loguru mutex.

    opened by allisonvacanti 7
  • How to prevent multiple definition errors?

    How to prevent multiple definition errors?

    This may not be an issue with loguru per se but more an issue with my little C++ experience, but I haven't found any easy way to prevent multiple definition errors when using loguru in both a static library and the main program.

    In my main C++ program main.cpp, I use:

    #include "utils.h"
    
    #ifndef LOGURU_INCLUDED
    #define LOGURU_INLUDED 1
    #define LOGURU_WITH_STREAMS 1
    #include <loguru.cpp>
    #endif
    

    But I also have a static helper library that uses loguru, too. It includes the same in its utils.h header file:

    #ifndef LOGURU_INCLUDED
    #define LOGURU_INLUDED 1
    #define LOGURU_WITH_STREAMS 1
    #include <loguru.cpp>
    #endif
    

    The linker however errors with various multiple definition issues:

    /builddir/../include/loguru/loguru.cpp:1865: multiple definition ofloguru::signal_handler(int, siginfo_t*, void*)'; src/main.p/main.cpp.o:/builddir/../include/loguru/loguru.cpp:1865: first defined here`

    What can I do to prevent this?

    opened by slhck 6
  • Logger object?

    Logger object?

    Hi, I was looking through multiple logging libraries and I saw that many have some kind of notion of different loggers (with their own severity levels and output style and sinks), and I was wondering if loguru has anything like that? I looked in the documentation but it seems there is only one main logger...

    opened by mike239x 6
  • Stream function for skipping stack lines?

    Stream function for skipping stack lines?

    It'd be great if I could do something like the following:

    LOG_S(INFO) << loguru::skip_stack(1) << "some text";
    

    The use-case here is that I often write perror()-like functions that aren't useful where LOG_S is being used but are instead important where the wrapper was called.

    opened by Qix- 6
  • Fixed compilation error on Visual Studio 2017

    Fixed compilation error on Visual Studio 2017

    The error was caused by macros being defined in one of the Windows SDK source file (minwindef.h to be exact). Simply undefining those macros fix issue and doesn't affect code since these macros are not used anyway.

    opened by rlewicki 6
  • callback

    callback

    Hi, how to use loguru callback function? i am trying to send error message to another thread.

    to use it, i tried to use event queue from mbed-events library. it seems work fine. https://github.com/ARMmbed/mbed-events

    opened by sailfish009 6
  • Added flags to configure preamble

    Added flags to configure preamble

    Hi,

    I was looking for a logging lib and found this one. It looks great (thanks) and it almost did everything I wanted. But there was no option to configure the preamble (it is a bit to verbose for my purposes), so I added this feature.

    Feel free to reject if you don't like it ;)

    - Alex

    opened by alexandervanrenen 5
  • Problems with PATH_MAX

    Problems with PATH_MAX

    Loguru doesn't compile on Debian Jessie with g++ 4.9.2 because PATH_MAX isn't defined. I have a basic fix here (it has a typo, MAX_PATH instead of PATH_MAX). It also doesn't compile with g++ 5.3 on Mac OS X, because that requires to include limits.h to get PATH_MAX.

    I would propose the following solution:

    1. When in a POSIX environment, include limits.h first.
    2. If PATH_MAX is not defined yet, and it is a Linux environment, include linux/limits.h
    3. If that didn't work, manually define PATH_MAX to a reasonable default, e.g. 1024.

    The most important point here I think is to have a default to fallback on, because apparently, PATH_MAX is not reliable at all.

    opened by bjoernpollex 5
  • Is there any option to turn off printing to stdout?

    Is there any option to turn off printing to stdout?

    I prefer to have everything logged to a file while not printing anything to stdout. I tried different verbosity options and none of them prevents printing to stdout. Perhaps, this option doesn't exist?

    opened by marethyu 4
  • Blank thread names on Windows

    Blank thread names on Windows

    On Linux threads are assigned names in the form of random (?) hex codes by default but on Windows their names stay blank. Is there any particular reason for this or maybe the behavior of loguru can be adjusted to be the same for both OS'es (e.g. that Windows also receives automatic thread naming)? I know that you can use loguru to set the thread name via loguru::set_thread_name but I would rather have the automatic way of assigning thread names on Windows as well for consistency reasons.

    bug help wanted windows 
    opened by BullyWiiPlaza 4
  • possible leaks in add_file function

    possible leaks in add_file function

    There is no fclose after fopen for file variable.

    fflush(file);
    //fclose(file)<===missing!!
    VLOG_F(g_internal_verbosity, "Logging to '" LOGURU_FMT(s) "', mode: '" LOGURU_FMT(s) "', verbosity: " LOGURU_FMT(d) "", path, mode_str, verbosity);
    return true;
    
    opened by darktrial 0
  • Fix MINGW32 errors and warnings

    Fix MINGW32 errors and warnings

    • Include share.h for _SH_DENYNO’s definition
    • Define NOMINMAX only if not already defined; MINGW warns of redefinition since bits/os_defines.h included by <algorithm> already defines it
    • Use C++11 thread_local instead of the non-standard option of __declspec(thread) 1
    opened by legends2k 2
  • Logging to files fails on Windows if the path contains Unicode characters

    Logging to files fails on Windows if the path contains Unicode characters

    For example, trying to save a log file to a path which contains Greek, Russian etc. letters. The problem is that _fsopen and mkdir on Windows treat the file path argument as encoded in the platform codepage, which can in theory be set to UTF-8 but in practice is most often a language-specific codepage like Latin-1.

    To fix this, it's necessary to use _wfsopen and _wmkdir and convert the paths to wide char before calling the functions. Something along those lines:

    const auto needed = MultiByteToWideChar(CP_UTF8, 0, file_path, -1, nullptr, 0);
    auto w_file_path = std::unique_ptr<wchar_t[]>(new wchar_t[needed]);
    MultiByteToWideChar(CP_UTF8, 0, file_path, -1, w_file_path.get(), needed);
    
    if (_wmkdir(w_file_path.get()) == -1) {
    
    opened by lethal-guitar 0
  • Loguru and glog conflict error

    Loguru and glog conflict error

    Hi, I use loguru in my project, and I installed Glog library at the same time. #define LOGURU_REPLACE_GLOG 1 #include <loguru.hpp> ... LOG(1) << ...; When I compiled my project, the error, 'error: ‘COMPACT_GOOGLE_LOG_1’ was not declared in this scope; did you mean ‘COMPACT_GOOGLE_LOG_0’?', occurs.

    opened by lfwin 0
  • some improvement points

    some improvement points

    Hi. I'm using your lib and it's great but some problems exist. It's a good thing to add #ifndef before NOMINMAX & WIN32_LEAN_AND_MEAN to prevent macro redefinition in environments where those two are defined. may be add green color to Info verbosity like many other logging libs or provide a way to customize verbosity colors. and does logging macros by default support c++ types like string or filesystem::path? i tried it, it worked but i get some portability warnings and supporting that types is a good feature. thanks.

    opened by amrezaee 0
Releases(v2.1.0)
Owner
Emil Ernerfeldt
Rust coder at Embark Studios. Previously worked with physics simulation, games, 3D scanning and cyber security. I am @ernerfeldt on Twitter
Emil Ernerfeldt
Colorful Logging is a simple and efficient library allowing for logging and benchmarking.

Colorful-Logging "Colorful Logging" is a library allowing for simple and efficient logging as well for benchmarking. What can you use it for? -Obvious

Mateusz Antkiewicz 1 Feb 17, 2022
A lightweight C++ logging library

Loguru: a lightweight and flexible C++ logging library. At a glance Documentation Documentation can be found at https://emilk.github.io/loguru/index.h

Emil Ernerfeldt 1.5k Jan 7, 2023
Yet another logging library.

Blackhole - eating your logs with pleasure Blackhole is an attribute-based logger with strong focus on gaining maximum performance as possible for suc

Evgeny Safronov 191 Dec 20, 2022
Portable, simple and extensible C++ logging library

Plog - portable, simple and extensible C++ logging library Pretty powerful logging library in about 1000 lines of code Introduction Hello log! Feature

Sergey Podobry 1.6k Dec 29, 2022
Fast C++ logging library.

spdlog Very fast, header-only/compiled, C++ logging library. Install Header only version Copy the source folder to your build tree and use a C++11 com

Gabi Melman 16.6k Jan 1, 2023
Asynchronous Low Latency C++ Logging Library

Quill Asynchronous Low Latency C++ Logging Library Introduction Features Performance Supported Platforms And Compilers Basic Usage CMake Integration D

Odysseas Georgoudis 677 Dec 20, 2022
Cute Log is a C++ Library that competes to be a unique logging tool.

Cute Log Cute Log is a C++ Library that competes to be a unique logging tool. Version: 2 Installation Click "Code" on the main repo page (This one.).

null 3 Oct 13, 2022
fmtlog is a performant fmtlib-style logging library with latency in nanoseconds.

fmtlog fmtlog is a performant asynchronous logging library using fmt library format. Features Faster - lower runtime latency than NanoLog and higher t

Meng Rao 443 Jan 6, 2023
Minimalistic logging library with threads and manual callstacks

Minimalistic logging library with threads and manual callstacks

Sergey Kosarevsky 20 Dec 5, 2022
A Fast and Convenient C++ Logging Library for Low-latency or Real-time Environments

xtr What is it? XTR is a C++ logging library aimed at applications with low-latency or real-time requirements. The cost of log statements is minimised

null 10 Jul 17, 2022
logog is a portable C++ library to facilitate logging of real-time events in performance-oriented applications

logog is a portable C++ library to facilitate logging of real-time events in performance-oriented applications, such as games. It is especially appropriate for projects that have constrained memory and constrained CPU requirements.

John Byrd 46 Oct 21, 2020
Boost Logging library

Boost.Log, part of collection of the Boost C++ Libraries, provides tools for adding logging to libraries and applications. Directories build - Boost.L

Boost.org 157 Dec 22, 2022
C++ implementation of the Google logging module

Google Logging Library The Google Logging Library (glog) implements application-level logging. The library provides logging APIs based on C++-style st

Google 5.9k Jan 9, 2023
log4cplus is a simple to use C++ logging API providing thread-safe, flexible, and arbitrarily granular control over log management and configuration. It is modelled after the Java log4j API.

% log4cplus README Short Description log4cplus is a simple to use C++17 logging API providing thread--safe, flexible, and arbitrarily granular control

null 1.4k Jan 4, 2023
Uberlog - Cross platform multi-process C++ logging system

uberlog uberlog is a cross platform C++ logging system that is: Small Fast Robust Runs on Linux, Windows, OSX MIT License Small Two headers, and three

IMQS Software 15 Sep 29, 2022
Reckless logging. Low-latency, high-throughput, asynchronous logging library for C++.

Introduction Reckless is an extremely low-latency, high-throughput logging library. It was created because I needed to perform extensive diagnostic lo

Mattias Flodin 445 Dec 20, 2022
Colorful Logging is a simple and efficient library allowing for logging and benchmarking.

Colorful-Logging "Colorful Logging" is a library allowing for simple and efficient logging as well for benchmarking. What can you use it for? -Obvious

Mateusz Antkiewicz 1 Feb 17, 2022