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 Quill LOG_ 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 longer QUILL_LOG_ macros instead. This approach allows Quill to work alongside syslog.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 Quill LOG_ 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 longer QUILL_LOG_ macros instead. This approach allows Quill to work alongside syslog.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);
}