Skip to content

Commit df683bb

Browse files
authored
docs: provide custom sinks example (#1103)
1 parent 0bad968 commit df683bb

File tree

4 files changed

+166
-1
lines changed

4 files changed

+166
-1
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ include (GetCacheVariables)
3232
include (GNUInstallDirs)
3333

3434
option (BUILD_SHARED_LIBS "Build shared libraries" ON)
35+
option (BUILD_EXAMPLES "Build examples" ON)
3536
option (PRINT_UNSYMBOLIZED_STACK_TRACES
3637
"Print file offsets in traces instead of symbolizing" OFF)
3738
option (WITH_GFLAGS "Use gflags" ON)
@@ -960,6 +961,11 @@ if (BUILD_TESTING)
960961
)
961962
endif (BUILD_TESTING)
962963

964+
if (BUILD_EXAMPLES)
965+
add_executable (custom_sink_example examples/custom_sink.cc)
966+
target_link_libraries (custom_sink_example PRIVATE glog::glog)
967+
endif (BUILD_EXAMPLES)
968+
963969
install (TARGETS glog
964970
EXPORT glog-targets
965971
RUNTIME DESTINATION ${_glog_CMake_BINDIR}

docs/sinks.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Custom Sinks
2+
3+
Under certain circumstances, it is useful to send the log output to a
4+
destination other than a file, `stderr` and/or `stdout`. In case, the library
5+
provides the `#!cpp google::LogSink` interface whose implementations can be used
6+
to write the log output to arbitrary locations.
7+
8+
## Basic Interface
9+
10+
The sink interface is defined as follows:
11+
12+
``` cpp
13+
class LogSink {
14+
public:
15+
virtual void send(LogSeverity severity, const char* full_filename,
16+
const char* base_filename, int line,
17+
const LogMessageTime& time, const char* message,
18+
size_t message_len);
19+
};
20+
```
21+
22+
The user must implement `#!cpp google::LogSink::send`, which is called by the
23+
library every time a message is logged.
24+
25+
!!! warning "Possible deadlock due to nested logging"
26+
This method can't use `LOG()` or `CHECK()` as logging system mutex(s) are
27+
held during this call.
28+
29+
## Registering Log Sinks
30+
31+
To use the custom sink and instance of the above interface implementation must
32+
be registered using `google::AddLogSink` which expects a pointer to the
33+
`google::LogSink` instance. To unregister use `google::RemoveLogSink`. Both
34+
functions are thread-safe.
35+
36+
!!! danger "`LogSink` ownership"
37+
The `google::LogSink` instance must not be destroyed until the referencing
38+
pointer is unregistered.
39+
40+
## Direct Logging
41+
42+
Instead of registering the sink, we can directly use to log messages. While `#!
43+
LOG_TO_SINK(sink, severity)` allows to log both to the sink and to a global log
44+
registry, e.g., a file, `#!cpp LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity)`
45+
will avoid the latter.
46+
47+
!!! example "Using a custom sink"
48+
``` cpp title="custom_sink.cc"
49+
-8<- "examples/custom_sink.cc:33:"
50+
```
51+
52+
1. `MySink` implements a custom sink that sends log messages to `std::cout`.
53+
2. The custom sink must be registered to for use with existing logging
54+
macros.
55+
3. Once the custom sink is no longer needed we remove it from the registry.
56+
4. A sink does not need to be registered globally. However, then, messages
57+
must be logged using dedicated macros.
58+
59+
Running the above example as `#!bash GLOG_log_dir=. ./custom_sink_example`
60+
will produce
61+
62+
<div class="annotate" markdown>
63+
64+
``` title="Custom sink output"
65+
INFO custom_sink.cc:63 logging to MySink
66+
INFO custom_sink.cc:68 direct logging
67+
INFO custom_sink.cc:69 direct logging but not to file (1)
68+
```
69+
70+
</div>
71+
72+
1. This line is not present in the log file because we used
73+
`LOG_TO_SINK_BUT_NOT_TO_LOGFILE` to log the message.
74+
75+
and the corresponding log file will contain
76+
77+
``` title="Log file generated with the custom sink"
78+
Log file created at: 2024/06/11 13:24:27
79+
Running on machine: pc
80+
Running duration (h:mm:ss): 0:00:00
81+
Log line format: [IWEF]yyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg
82+
I20240611 13:24:27.476620 126237946035776 custom_sink.cc:63] logging to MySink
83+
I20240611 13:24:27.476796 126237946035776 custom_sink.cc:68] direct logging
84+
```

examples/custom_sink.cc

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (c) 2024, Google Inc.
2+
// All rights reserved.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are
6+
// met:
7+
//
8+
// * Redistributions of source code must retain the above copyright
9+
// notice, this list of conditions and the following disclaimer.
10+
// * Redistributions in binary form must reproduce the above
11+
// copyright notice, this list of conditions and the following disclaimer
12+
// in the documentation and/or other materials provided with the
13+
// distribution.
14+
// * Neither the name of Google Inc. nor the names of its
15+
// contributors may be used to endorse or promote products derived from
16+
// this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
//
30+
// Author: Sergiu Deitsch
31+
//
32+
33+
#include <glog/logging.h>
34+
35+
#include <algorithm>
36+
#include <cstddef>
37+
#include <iostream>
38+
#include <iterator>
39+
40+
namespace {
41+
42+
struct MyLogSink : google::LogSink { // (1)!
43+
void send(google::LogSeverity severity, const char* /*full_filename*/,
44+
const char* base_filename, int line,
45+
const google::LogMessageTime& /*time*/, const char* message,
46+
std::size_t message_len) override {
47+
std::cout << google::GetLogSeverityName(severity) << ' ' << base_filename
48+
<< ':' << line << ' ';
49+
std::copy_n(message, message_len,
50+
std::ostreambuf_iterator<char>{std::cout});
51+
std::cout << '\n';
52+
}
53+
};
54+
55+
} // namespace
56+
57+
int main(int /*argc*/, char** argv) {
58+
google::InitGoogleLogging(argv[0]);
59+
60+
MyLogSink sink;
61+
google::AddLogSink(&sink); // (2)!
62+
63+
LOG(INFO) << "logging to MySink";
64+
65+
google::RemoveLogSink(&sink); // (3)!
66+
67+
// We can directly log to a sink without registering it
68+
LOG_TO_SINK(&sink, INFO) << "direct logging"; // (4)!
69+
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, INFO)
70+
<< "direct logging but not to file";
71+
}

mkdocs.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ edit_uri: edit/0.7.x/docs/
77
copyright: Copyright &copy; 2024 Google Inc. &amp; contributors - <a href="#__consent">Change cookie settings</a>
88
markdown_extensions:
99
- admonition
10+
- attr_list
1011
- def_list
12+
- md_in_html
1113
- pymdownx.details
1214
- pymdownx.highlight:
1315
anchor_linenums: true
@@ -26,8 +28,9 @@ theme:
2628
name: material
2729
custom_dir: docs/overrides
2830
icon:
29-
repo: fontawesome/brands/git-alt
31+
annotation: material/chevron-right-circle
3032
edit: material/pencil
33+
repo: fontawesome/brands/git-alt
3134
view: material/eye
3235
language: en
3336
features:
@@ -107,6 +110,7 @@ nav:
107110
- Installation using Package Managers: packages.md
108111
- User Guide:
109112
- Logging: logging.md
113+
- Custom Sinks: sinks.md
110114
- Failure Handler: failures.md
111115
- Log Removal: log_cleaner.md
112116
- Stripping Log Messages: log_stripping.md

0 commit comments

Comments
 (0)