85 lines
3.0 KiB
Markdown
85 lines
3.0 KiB
Markdown
# Custom Sinks
|
|
|
|
Under certain circumstances, it is useful to send the log output to a
|
|
destination other than a file, `stderr` and/or `stdout`. In case, the library
|
|
provides the `#!cpp google::LogSink` interface whose implementations can be used
|
|
to write the log output to arbitrary locations.
|
|
|
|
## Basic Interface
|
|
|
|
The sink interface is defined as follows:
|
|
|
|
``` cpp
|
|
class LogSink {
|
|
public:
|
|
virtual void send(LogSeverity severity, const char* full_filename,
|
|
const char* base_filename, int line,
|
|
const LogMessageTime& time, const char* message,
|
|
size_t message_len);
|
|
};
|
|
```
|
|
|
|
The user must implement `#!cpp google::LogSink::send`, which is called by the
|
|
library every time a message is logged.
|
|
|
|
!!! warning "Possible deadlock due to nested logging"
|
|
This method can't use `LOG()` or `CHECK()` as logging system mutex(s) are
|
|
held during this call.
|
|
|
|
## Registering Log Sinks
|
|
|
|
To use the custom sink and instance of the above interface implementation must
|
|
be registered using `google::AddLogSink` which expects a pointer to the
|
|
`google::LogSink` instance. To unregister use `google::RemoveLogSink`. Both
|
|
functions are thread-safe.
|
|
|
|
!!! danger "`LogSink` ownership"
|
|
The `google::LogSink` instance must not be destroyed until the referencing
|
|
pointer is unregistered.
|
|
|
|
## Direct Logging
|
|
|
|
Instead of registering the sink, we can directly use to log messages. While `#!
|
|
LOG_TO_SINK(sink, severity)` allows to log both to the sink and to a global log
|
|
registry, e.g., a file, `#!cpp LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity)`
|
|
will avoid the latter.
|
|
|
|
!!! example "Using a custom sink"
|
|
``` cpp title="custom_sink.cc"
|
|
-8<- "examples/custom_sink.cc:33:"
|
|
```
|
|
|
|
1. `MySink` implements a custom sink that sends log messages to `std::cout`.
|
|
2. The custom sink must be registered to for use with existing logging
|
|
macros.
|
|
3. Once the custom sink is no longer needed we remove it from the registry.
|
|
4. A sink does not need to be registered globally. However, then, messages
|
|
must be logged using dedicated macros.
|
|
|
|
Running the above example as `#!bash GLOG_log_dir=. ./custom_sink_example`
|
|
will produce
|
|
|
|
<div class="annotate" markdown>
|
|
|
|
``` title="Custom sink output"
|
|
INFO custom_sink.cc:63 logging to MySink
|
|
INFO custom_sink.cc:68 direct logging
|
|
INFO custom_sink.cc:69 direct logging but not to file (1)
|
|
```
|
|
|
|
</div>
|
|
|
|
1. This line is not present in the log file because we used
|
|
`LOG_TO_SINK_BUT_NOT_TO_LOGFILE` to log the message.
|
|
|
|
and the corresponding log file will contain
|
|
|
|
``` title="Log file generated with the custom sink"
|
|
Log file created at: 2024/06/11 13:24:27
|
|
Running on machine: pc
|
|
Running duration (h:mm:ss): 0:00:00
|
|
Log line format: [IWEF]yyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg
|
|
I20240611 13:24:27.476620 126237946035776 custom_sink.cc:63] logging to MySink
|
|
I20240611 13:24:27.476796 126237946035776 custom_sink.cc:68] direct logging
|
|
```
|