README.md 8.86 KB
Newer Older
gabime's avatar
gabime committed
1 2
# spdlog

Gabi Melman's avatar
Gabi Melman committed
3 4
Very fast, header only, C++ logging library. [![Build Status](https://travis-ci.org/gabime/spdlog.svg?branch=master)](https://travis-ci.org/gabime/spdlog)  [![Build status](https://ci.appveyor.com/api/projects/status/d2jnxclg20vd0o50?svg=true)](https://ci.appveyor.com/project/gabime/spdlog)

gabime's avatar
gabime committed
5 6

## Install
Gabi Melman's avatar
Gabi Melman committed
7
#### Just copy the headers:
8

Gabi Melman's avatar
Gabi Melman committed
9 10
* Copy the source [folder](https://github.com/gabime/spdlog/tree/master/include/spdlog) to your build tree and use a C++11 compiler.

Gabi Melman's avatar
Gabi Melman committed
11
#### Or use your favorite package manager:
Gabi Melman's avatar
Gabi Melman committed
12

13 14
* Ubuntu: `apt-get install libspdlog-dev`
* Homebrew: `brew install spdlog`
Gabi Melman's avatar
Gabi Melman committed
15
* FreeBSD:  `cd /usr/ports/devel/spdlog/ && make install clean`
16
* Fedora: `yum install spdlog`
17
* Gentoo: `emerge dev-libs/spdlog`
Vitor Alves's avatar
Vitor Alves committed
18
* Arch Linux: `yaourt -S spdlog-git`
19 20
* vcpkg: `vcpkg install spdlog`
 
gabime's avatar
gabime committed
21 22

## Platforms
gabime's avatar
gabime committed
23
 * Linux, FreeBSD, Solaris, AIX
Gabi Melman's avatar
Gabi Melman committed
24
 * Windows (vc 2013+, cygwin)
Gabi Melman's avatar
Gabi Melman committed
25
 * Mac OSX (clang 3.5+)
Gabi Melman's avatar
Gabi Melman committed
26
 * Android
gabime's avatar
gabime committed
27

Devansh D's avatar
Devansh D committed
28
## Features
gabime's avatar
gabime committed
29
* Very fast - performance is the primary goal (see [benchmarks](#benchmarks) below).
Gabi Melman's avatar
Gabi Melman committed
30
* Headers only, just copy and use.
Gabi Melman's avatar
Gabi Melman committed
31
* Feature rich [call style](#usage-example) using the excellent [fmt](https://github.com/fmtlib/fmt) library.
gabime's avatar
gabime committed
32
* Fast asynchronous mode (optional)
gabime's avatar
gabime committed
33
* [Custom](https://github.com/gabime/spdlog/wiki/3.-Custom-formatting) formatting.
Asit Kumar Dhal's avatar
Asit Kumar Dhal committed
34
* Conditional Logging
gabime's avatar
gabime committed
35 36 37 38
* Multi/Single threaded loggers.
* Various log targets:
    * Rotating log files.
    * Daily log files.
Gabi Melman's avatar
Gabi Melman committed
39
    * Console logging (colors supported).
Gabi Melman's avatar
Gabi Melman committed
40
    * syslog.
Gabi Melman's avatar
Gabi Melman committed
41
    * Windows debugger (```OutputDebugString(..)```)
gabime's avatar
gabime committed
42 43 44 45 46 47 48
    * Easily extendable with custom log targets  (just implement a single function in the [sink](include/spdlog/sinks/sink.h) interface).
* Severity based filtering - threshold levels can be modified in runtime as well as in compile time.



## Benchmarks

gabime's avatar
gabime committed
49
Below are some [benchmarks](https://github.com/gabime/spdlog/blob/v1.x/bench/bench.cpp) done in Ubuntu 64 bit, Intel i7-4770 CPU @ 3.40GHz
gabime's avatar
gabime committed
50 51

#### Synchronous mode
gabime's avatar
gabime committed
52
```
gabime's avatar
gabime committed
53 54 55 56
*******************************************************************************
Single thread, 1,000,000 iterations
*******************************************************************************
basic_st...		Elapsed: 0.231041	4,328,228/sec
gabime's avatar
gabime committed
57
rotating...             Elapsed: 0.233466	4,283,282/sec
gabime's avatar
gabime committed
58 59 60 61 62 63 64 65 66
daily_st...		Elapsed: 0.244491	4,090,136/sec
null_st...		Elapsed: 0.162708	6,145,995/sec

*******************************************************************************
10 threads sharing same logger, 1,000,000 iterations
*******************************************************************************
basic_mt...		Elapsed: 0.854029	1,170,920/sec
rotating_mt		Elapsed: 0.867038	1,153,351/sec
daily_mt...		Elapsed: 0.869593	1,149,963/sec
gabime's avatar
gabime committed
67
null_mt...		Elapsed: 0.171215	2,033,537/sec
gabime's avatar
gabime committed
68
```
gabime's avatar
gabime committed
69
#### Asynchronous mode
gabime's avatar
gabime committed
70
```
gabime's avatar
gabime committed
71
*******************************************************************************
gabime's avatar
gabime committed
72
10 threads sharing same logger, 1,000,000 iterations 
gabime's avatar
gabime committed
73 74 75 76
*******************************************************************************
async...		Elapsed: 0.442731	2,258,706/sec
async...		Elapsed: 0.427072	2,341,527/sec
async...		Elapsed: 0.449768	2,223,369/sec
gabime's avatar
gabime committed
77
```
gabime's avatar
gabime committed
78

Gabi Melman's avatar
Gabi Melman committed
79 80 81
## Usage 

#### Terminal logging
gabime's avatar
gabime committed
82
```c++
gabime's avatar
gabime committed
83
#include "spdlog/spdlog.h"
Gabi Melman's avatar
Gabi Melman committed
84
#include "spdlog/sinks/stdout_color_sinks.h"
gabime's avatar
gabime committed
85
void stdout_example()
Gabi Melman's avatar
Gabi Melman committed
86
{
gabime's avatar
gabime committed
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
    // create color multi threaded logger
    auto console = spdlog::stdout_color_mt("console");
    console->info("Welcome to spdlog!");
    console->error("Some error message with arg: {}", 1);

    auto err_logger = spdlog::stderr_color_mt("stderr");
    err_logger->error("Some error message");

    // Formatting examples
    console->warn("Easy padding in numbers like {:08d}", 12);
    console->critical("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);
    console->info("Support for floats {:03.2f}", 1.23456);
    console->info("Positional args are {1} {0}..", "too", "supported");
    console->info("{:<30}", "left aligned");

    spdlog::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");

    // Runtime log levels
    spdlog::set_level(spdlog::level::info); // Set global log level to info
    console->debug("This message should not be displayed!");
    console->set_level(spdlog::level::trace); // Set specific logger's log level
    console->debug("This message should be displayed..");

    // Customize msg format for all loggers
    spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");
    console->info("This an info message with custom format");

    // Compile time log levels
    // define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON
    SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
    SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
}
Gabi Melman's avatar
Gabi Melman committed
119
```
Gabi Melman's avatar
Gabi Melman committed
120
---
Gabi Melman's avatar
Gabi Melman committed
121
#### Simple file logger
Gabi Melman's avatar
Gabi Melman committed
122
```c++
gabime's avatar
gabime committed
123 124 125 126 127
#include "spdlog/sinks/basic_file_sink.h"
void basic_logfile_example()
{
    // Create basic file logger (not rotated)
    try 
Gabi Melman's avatar
Gabi Melman committed
128
    {
gabime's avatar
gabime committed
129
        auto my_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic-log.txt");
Gabi Melman's avatar
Gabi Melman committed
130
    }
gabime's avatar
gabime committed
131
    catch (const spdlog::spdlog_ex &ex)
Gabi Melman's avatar
Gabi Melman committed
132 133 134 135
    {
        std::cout << "Log init failed: " << ex.what() << std::endl;
        return 1;
    }
gabime's avatar
gabime committed
136
}
Gabi Melman's avatar
Gabi Melman committed
137
```
Gabi Melman's avatar
Gabi Melman committed
138
---
Gabi Melman's avatar
Gabi Melman committed
139
#### Rotating files
Gabi Melman's avatar
Gabi Melman committed
140
```c++
gabime's avatar
gabime committed
141 142 143 144 145 146
#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);
}
Gabi Melman's avatar
Gabi Melman committed
147
```
148

Gabi Melman's avatar
Gabi Melman committed
149
---
Gabi Melman's avatar
Gabi Melman committed
150
#### Daily files
Gabi Melman's avatar
Gabi Melman committed
151
```c++
gabime's avatar
gabime committed
152 153 154 155 156 157 158 159

#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);
}

Gabi Melman's avatar
Gabi Melman committed
160
```
161 162 163 164 165 166 167 168 169 170

---
#### Periodic flush
```c++
// periodically flush all *registered* loggers every 3 seconds:
// warning: only use if all your loggers are thread safe!
spdlog::flush_every(std::chrono::seconds(3));

```

Gabi Melman's avatar
Gabi Melman committed
171
---
Gabi Melman's avatar
Gabi Melman committed
172 173
#### Asynchronous logging
```c++
Gabi Melman's avatar
Gabi Melman committed
174
#include "spdlog/async.h"
gabime's avatar
gabime committed
175 176
void async_example()
{
gabime's avatar
gabime committed
177
    // default thread pool settings can be modified *before* creating the async logger:
Gabi Melman's avatar
Gabi Melman committed
178
    // spdlog::init_thread_pool(8192, 1); // queue with 8k items and 1 backing thread.
gabime's avatar
gabime committed
179 180
    auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
    // alternatively:
Gabi Melman's avatar
Gabi Melman committed
181
    // auto async_file = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("async_file_logger", "logs/async_log.txt");   
gabime's avatar
gabime committed
182 183
}

Gabi Melman's avatar
Gabi Melman committed
184
```
Gabi Melman's avatar
Gabi Melman committed
185
---
Gabi Melman's avatar
Gabi Melman committed
186
#### Logger with multi targets - each with different format and log level
Gabi Melman's avatar
Gabi Melman committed
187 188
```c++

Gabi Melman's avatar
Gabi Melman committed
189 190
// create logger with 2 targets with different log levels and formats.
// the console will show only warnings or errors, while the file will log all.
gabime's avatar
gabime committed
191
void multi_sink_example()
Gabi Melman's avatar
Gabi Melman committed
192
{
gabime's avatar
gabime committed
193 194 195
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    console_sink->set_level(spdlog::level::warn);
    console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v");
gabime's avatar
gabime committed
196

gabime's avatar
gabime committed
197 198
    auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/multisink.txt", true);
    file_sink->set_level(spdlog::level::trace);
Gabi Melman's avatar
Gabi Melman committed
199

gabime's avatar
gabime committed
200 201 202 203 204
    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");
}
Gabi Melman's avatar
Gabi Melman committed
205
```
Gabi Melman's avatar
Gabi Melman committed
206
---
Gabi Melman's avatar
Gabi Melman committed
207
#### User defined types
Gabi Melman's avatar
Gabi Melman committed
208
```c++
gabime's avatar
gabime committed
209
// user defined types logging by implementing operator<<
gabime's avatar
gabime committed
210
#include "spdlog/fmt/ostr.h" // must be included
gabime's avatar
gabime committed
211 212 213 214
struct my_type
{
    int i;
    template<typename OStream>
Gabi Melman's avatar
Gabi Melman committed
215
    friend OStream &operator<<(OStream &os, const my_type &c)
gabime's avatar
gabime committed
216
    {
Gabi Melman's avatar
Gabi Melman committed
217
        return os << "[my_type i=" << c.i << "]";
gabime's avatar
gabime committed
218
    }
gabime's avatar
gabime committed
219 220 221 222
};

void user_defined_example()
{
gabime's avatar
gabime committed
223
    spdlog::get("console")->info("user defined type: {}", my_type{14});
gabime's avatar
gabime committed
224 225
}

Gabi Melman's avatar
Gabi Melman committed
226
```
Gabi Melman's avatar
Gabi Melman committed
227
---
Gabi Melman's avatar
Gabi Melman committed
228 229
#### Custom error handler
```c++
gabime's avatar
gabime committed
230
void err_handler_example()
Gabi Melman's avatar
Gabi Melman committed
231
{
gabime's avatar
gabime committed
232 233 234 235 236
    // can be set globally or per logger(logger->set_error_handler(..))
    spdlog::set_error_handler([](const std::string &msg) { spdlog::get("console")->error("*** LOGGER ERROR ***: {}", msg); });
    spdlog::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
}

Gabi Melman's avatar
Gabi Melman committed
237
```
Gabi Melman's avatar
Gabi Melman committed
238
---
Gabi Melman's avatar
Gabi Melman committed
239
#### syslog 
Gabi Melman's avatar
Gabi Melman committed
240
```c++
gabime's avatar
gabime committed
241 242 243 244 245 246
#include "spdlog/sinks/syslog_sink.h"
void syslog_example()
{
    std::string ident = "spdlog-example";
    auto syslog_logger = spdlog::syslog_logger("syslog", ident, LOG_PID);
    syslog_logger->warn("This is warning that will end up in syslog.");
gabime's avatar
gabime committed
247
}
Gabi Melman's avatar
Gabi Melman committed
248
```
Gabi Melman's avatar
Gabi Melman committed
249
---
Gabi Melman's avatar
Gabi Melman committed
250 251
#### Android example 
```c++
gabime's avatar
gabime committed
252 253 254 255 256 257 258
#incude "spdlog/sinks/android_sink.h"
void android_example()
{
    std::string tag = "spdlog-android";
    auto android_logger = spdlog::android_logger("android", tag);
    android_logger->critical("Use \"adb shell logcat\" to view this message.");
}
gabime's avatar
gabime committed
259 260 261 262
```

## Documentation
Documentation can be found in the [wiki](https://github.com/gabime/spdlog/wiki/1.-QuickStart) pages.