Filters¶
Filters are used to selectively control which log statements are sent to specific Sinks
based on defined criteria.
Each Sink
can be associated with one or multiple Filter
objects. These filters allow customization of log statement handling, such as filtering by log level or other criteria.
By default, a logger sends all log messages to its Sinks
. Filters provide a way to intercept and selectively process log records before they are outputted.
A filter is implemented as a callable object that evaluates each log statement and returns a boolean value. This boolean value determines whether the log statement should be forwarded to the Sink
or filtered out.
Filtering Logs with the Built-In Filter¶
1#include "quill/Backend.h"
2#include "quill/Frontend.h"
3#include "quill/LogMacros.h"
4#include "quill/Logger.h"
5#include "quill/sinks/ConsoleSink.h"
6
7int main()
8{
9 quill::Backend::start();
10
11 quill::Logger* logger = quill::Frontend::create_or_get_logger(
12 "root", quill::Frontend::create_or_get_sink<quill::ConsoleSink>("sink_id_1"));
13
14 LOG_INFO(logger, "This is a log info example {}", 123);
15
16 // Apply filter to the sink. This is thread-safe but to avoid setting the filter before the
17 // backend has processed the earlier log message we flush first
18 logger->flush_log();
19 quill::Frontend::get_sink("sink_id_1")->set_log_level_filter(quill::LogLevel::Error);
20 LOG_INFO(logger, "This message is filtered");
21
22 logger->flush_log();
23 quill::Frontend::get_sink("sink_id_1")->set_log_level_filter(quill::LogLevel::TraceL3);
24 LOG_INFO(logger, "This is a log info example {}", 456);
25}
Creating a Custom Log Filter¶
1#include "quill/Backend.h"
2#include "quill/Frontend.h"
3#include "quill/LogMacros.h"
4#include "quill/Logger.h"
5#include "quill/filters/Filter.h"
6#include "quill/sinks/ConsoleSink.h"
7
8#include <cstdint>
9#include <string>
10#include <string_view>
11#include <utility>
12
13/**
14 * This example demonstrates the creation usage of a user defined filter.
15 * When a filter is applied, log messages are still enqueued from the frontend to the backend.
16 * Subsequently, the backend dynamically filters them based on a given condition.
17 */
18
19class UserFilter : public quill::Filter
20{
21public:
22 UserFilter() : quill::Filter("filter_1") {};
23
24 bool filter(quill::MacroMetadata const* /** log_metadata **/, uint64_t /** log_timestamp **/,
25 std::string_view /** thread_id **/, std::string_view /** thread_name **/,
26 std::string_view /** logger_name **/, quill::LogLevel log_level,
27 std::string_view log_message, std::string_view /** log_statement **/) noexcept override
28 {
29 // for example filter out duplicate log files
30 bool is_different = true;
31
32 if ((last_log_level == log_level) && (log_message == last_message))
33 {
34 is_different = false;
35 }
36
37 last_message = log_message;
38 last_log_level = log_level;
39
40 // return true to log the message, false otherwise
41 return is_different;
42 }
43
44private:
45 std::string last_message;
46 quill::LogLevel last_log_level{quill::LogLevel::None};
47};
48
49int main()
50{
51 // Start the backend thread
52 quill::BackendOptions backend_options;
53 quill::Backend::start(backend_options);
54
55 // Frontend
56 auto console_sink = quill::Frontend::create_or_get_sink<quill::ConsoleSink>("sink_id_1");
57
58 // Add the filter - adding filters is thread safe and can be called anytime
59 console_sink->add_filter(std::make_unique<UserFilter>());
60
61 quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(console_sink));
62
63 // Change the LogLevel to send everything
64 logger->set_log_level(quill::LogLevel::TraceL3);
65
66 LOG_INFO(logger, "This is a log info example {}", 123);
67 LOG_INFO(logger, "This is a log info example {}", 123);
68 LOG_INFO(logger, "This is a log info example {}", 123);
69 LOG_INFO(logger, "This is a log info example {}", 123);
70 LOG_INFO(logger, "This is a log info example {}", 456);
71 LOG_INFO(logger, "This is a log info example {}", 123);
72}