Sink Types¶
ConsoleSink¶
The ConsoleSink class sends logging output to streams stdout or stderr. Printing color codes to terminal or Windows console is also supported.
FileSink¶
The FileSink
is a straightforward sink that outputs to a file. The filepath of the FileSink serves as a unique identifier, allowing you to retrieve the same sink later using FrontendImpl::get_sink()
.
Each file can only have a single instance of FileSink.
1#include "quill/Backend.h"
2#include "quill/Frontend.h"
3#include "quill/LogMacros.h"
4#include "quill/Logger.h"
5#include "quill/sinks/FileSink.h"
6
7#include <utility>
8
9int main()
10{
11 quill::Backend::start();
12
13 // Frontend
14 auto file_sink = quill::Frontend::create_or_get_sink<quill::FileSink>(
15 "trivial_logging.log",
16 []()
17 {
18 quill::FileSinkConfig cfg;
19 cfg.set_open_mode('w');
20 cfg.set_filename_append_option(quill::FilenameAppendOption::StartDateTime);
21 return cfg;
22 }(),
23 quill::FileEventNotifier{});
24
25 quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(file_sink));
26
27 LOG_INFO(logger, "log something {}", 123);
28 LOG_WARNING(logger, "something else {}", 456);
29}
RotatingFileSink¶
The RotatingFileSink
is built on top of the FileSink and provides log file rotation based on specified time intervals, file sizes, or daily schedules.
1#include "quill/Backend.h"
2#include "quill/Frontend.h"
3#include "quill/LogMacros.h"
4#include "quill/Logger.h"
5#include "quill/sinks/RotatingFileSink.h"
6
7#include <utility>
8
9/**
10 * This example demonstrates how to create a RotatingFileSink with daily rotation and automatic rotation based on maximum file size.
11 * For additional configuration options, refer to RotatingFileSinkConfig.
12 */
13
14int main()
15{
16 // Start the backend thread
17 quill::BackendOptions backend_options;
18 quill::Backend::start(backend_options);
19
20 // Frontend
21 auto rotating_file_sink = quill::Frontend::create_or_get_sink<quill::RotatingFileSink>(
22 "rotating_file.log",
23 []()
24 {
25 // See RotatingFileSinkConfig for more options
26 quill::RotatingFileSinkConfig cfg;
27 cfg.set_open_mode('w');
28 cfg.set_filename_append_option(quill::FilenameAppendOption::StartDateTime);
29 cfg.set_rotation_time_daily("18:30");
30 cfg.set_rotation_max_file_size(1024); // small value to demonstrate the example
31 return cfg;
32 }());
33
34 quill::Logger* logger = quill::Frontend::create_or_get_logger(
35 "root", std::move(rotating_file_sink),
36 quill::PatternFormatterOptions{"%(time) [%(thread_id)] %(short_source_location:<28) "
37 "LOG_%(log_level:<9) %(logger:<12) %(message)",
38 "%H:%M:%S.%Qns", quill::Timezone::GmtTime});
39
40 for (int i = 0; i < 20; ++i)
41 {
42 LOG_INFO(logger, "Hello from rotating logger, index is {}", i);
43 }
44}
JsonFileSink/JsonConsoleSink¶
1#include "quill/Backend.h"
2#include "quill/Frontend.h"
3#include "quill/LogMacros.h"
4#include "quill/Logger.h"
5#include "quill/sinks/JsonSink.h"
6#include <string>
7
8int main()
9{
10 // Start the backend thread
11 quill::BackendOptions backend_options;
12 quill::Backend::start(backend_options);
13
14 // Create a json sink
15 auto json_sink = quill::Frontend::create_or_get_sink<quill::JsonFileSink>("example_json.log",
16 []()
17 {
18 quill::FileSinkConfig config;
19 return config;
20 }());
21
22 // PatternFormatter is only used for non-structured logs formatting
23 // When logging only json, it is ideal to set the logging pattern to empty to avoid unnecessary message formatting.
24 quill::Logger* logger = quill::Frontend::create_or_get_logger(
25 "json_logger", std::move(json_sink),
26 quill::PatternFormatterOptions{"", "%H:%M:%S.%Qns", quill::Timezone::GmtTime});
27
28 int var_a = 123;
29 std::string var_b = "test";
30
31 // Log via the convenient LOGJ_ macros
32 LOGJ_INFO(logger, "A json message", var_a, var_b);
33
34 // Or manually specify the desired names of each variable
35 LOG_INFO(logger, "A json message with {var_1} and {var_2}", var_a, var_b);
36}
RotatingJsonFileSink¶
The RotatingJsonFileSink
is built on top of the JsonFileSink and provides log file rotation based on specified time intervals, file sizes, or daily schedules.
1#include "quill/Backend.h"
2#include "quill/Frontend.h"
3#include "quill/LogMacros.h"
4#include "quill/Logger.h"
5#include "quill/sinks/RotatingJsonFileSink.h"
6
7#include <utility>
8
9/**
10 * This example demonstrates how to create a RotatingFileSink with daily rotation and automatic rotation based on maximum file size.
11 * For additional configuration options, refer to RotatingFileSinkConfig.
12 */
13
14int main()
15{
16 // Start the backend thread
17 quill::BackendOptions backend_options;
18 quill::Backend::start(backend_options);
19
20 // Frontend
21 auto rotating_json_sink = quill::Frontend::create_or_get_sink<quill::RotatingJsonFileSink>(
22 "rotating_json.log",
23 []()
24 {
25 // See RotatingFileSinkConfig for more options
26 quill::RotatingFileSinkConfig cfg;
27 cfg.set_open_mode('w');
28 cfg.set_filename_append_option(quill::FilenameAppendOption::StartDateTime);
29 cfg.set_rotation_time_daily("18:30");
30 cfg.set_rotation_max_file_size(1024); // small value to demonstrate the example
31 return cfg;
32 }());
33
34 quill::Logger* logger = quill::Frontend::create_or_get_logger(
35 "root", std::move(rotating_json_sink),
36 quill::PatternFormatterOptions{"%(time) [%(thread_id)] %(short_source_location:<28) "
37 "LOG_%(log_level:<9) %(logger:<12) %(message)",
38 "%H:%M:%S.%Qns", quill::Timezone::GmtTime});
39
40 for (int i = 0; i < 20; ++i)
41 {
42 LOG_INFO(logger, "Hello from rotating logger {index}", i);
43 }
44}
SyslogSink¶
The SyslogSink
leverages the syslog API to send messages.
Note
Macro Collision Notice
When including syslog.h
via SyslogSink
, the header defines macros such as LOG_INFO
(and others) that may collide with Quill’s unprefixed LOG_
macros. To resolve this issue, consider one
of the following solutions:
Include SyslogSink in a .cpp file only: Instantiate the SyslogSink in a source file rather than in a header file. This ensures that
syslog.h
is included only in that specific translation unit, allowing the rest of your code to use the unprefixed QuillLOG_
macros without conflict.Define the preprocessor flag ``QUILL_DISABLE_NON_PREFIXED_MACROS``: This flag disables the unprefixed Quill
LOG_
macros and forces the use of the longerQUILL_LOG_
macros instead. This approach allows Quill to work alongsidesyslog.h
in the same translation unit.
Alternatively, you can combine both solutions if you include SyslogSink
in a .cpp file where you
also want to use the unprefixed LOG_
macros. However, the first solution is generally preferred since it
allows for less typing with the concise LOG_
macros.
#define QUILL_DISABLE_NON_PREFIXED_MACROS
#include "quill/Backend.h"
#include "quill/Frontend.h"
#include "quill/LogMacros.h"
#include "quill/Logger.h"
#include "quill/sinks/SyslogSink.h"
#include <string>
#include <utility>
int main()
{
quill::BackendOptions backend_options;
quill::Backend::start(backend_options);
// Frontend
auto sink = quill::Frontend::create_or_get_sink<quill::SyslogSink>(
"app", []()
{
quill::SyslogSinkConfig config;
config.set_identifier("app");
return config;
}());
quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(sink));
QUILL_LOG_INFO(logger, "A {} message with number {}", "log", 1);
QUILL_LOG_WARNING(logger, "test message {}", 123);
}
SystemdSink¶
The SystemdSink
integrates with the systemd journal, allowing messages to be sent directly to systemd. To use this sink, ensure the systemd-devel package is installed. Additionally, link your program against lsystemd
.
find_package(PkgConfig REQUIRED)
pkg_check_modules(SYSTEMD REQUIRED libsystemd)
target_link_libraries(${TARGET} ${SYSTEMD_LIBRARIES})
Note
Macro Collision Notice
When including syslog.h
via SystemdSink
, the header defines macros such as LOG_INFO
(and others) that may collide with Quill’s unprefixed LOG_
macros. To resolve this issue, consider one
of the following solutions:
Include SystemdSink in a .cpp file only: Instantiate the SystemdSink in a source file rather than in a header file. This ensures that
syslog.h
is included only in that specific translation unit, allowing the rest of your code to use the unprefixed QuillLOG_
macros without conflict.Define the preprocessor flag ``QUILL_DISABLE_NON_PREFIXED_MACROS``: This flag disables the unprefixed Quill
LOG_
macros and forces the use of the longerQUILL_LOG_
macros instead. This approach allows Quill to work alongsidesyslog.h
in the same translation unit.
Alternatively, you can combine both solutions if you include SystemdSink
in a .cpp file where you
also want to use the unprefixed LOG_
macros. However, the first solution is generally preferred since it
allows for less typing with the concise LOG_
macros.
#define QUILL_DISABLE_NON_PREFIXED_MACROS
#include "quill/Backend.h"
#include "quill/Frontend.h"
#include "quill/LogMacros.h"
#include "quill/Logger.h"
#include "quill/sinks/SystemdSink.h"
#include <string>
#include <utility>
int main()
{
quill::BackendOptions backend_options;
quill::Backend::start(backend_options);
// Frontend
auto sink = quill::Frontend::create_or_get_sink<quill::SystemdSink>(
"app", []()
{
quill::SystemdSinkConfig config;
config.set_identifier("app");
return config;
}());
quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(sink));
QUILL_LOG_INFO(logger, "A {} message with number {}", "log", 1);
QUILL_LOG_WARNING(logger, "test lol {}", 123);
}