userver: userver/utest/log_capture_fixture.hpp Source File
Loading...
Searching...
No Matches
log_capture_fixture.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utest/log_capture_fixture.hpp
4/// @brief @copybrief utest::LogCaptureFixture
5/// @ingroup userver_universal
6
7#include <iosfwd>
8#include <optional>
9#include <string>
10#include <string_view>
11#include <utility>
12#include <vector>
13
14#include <gtest/gtest.h>
15
16#include <userver/logging/impl/logger_base.hpp>
17#include <userver/logging/level.hpp>
18#include <userver/logging/log.hpp>
19#include <userver/utest/default_logger_fixture.hpp>
20#include <userver/utils/function_ref.hpp>
21#include <userver/utils/impl/internal_tag.hpp>
22#include <userver/utils/impl/source_location.hpp>
23#include <userver/utils/not_null.hpp>
24#include <userver/utils/span.hpp>
25
26USERVER_NAMESPACE_BEGIN
27
28namespace utest {
29
30namespace impl {
31class ToStringLogger;
32} // namespace impl
33
34/// @ingroup userver_utest
35///
36/// @brief Represents single log record, typically written via `LOG_*` macros.
37///
38/// @see @ref utest::LogCaptureLogger
39/// @see @ref utest::LogCaptureFixture
40class LogRecord final {
41public:
42 /// @returns decoded text of the log record
43 /// @throws if no 'text' tag in the log
44 const std::string& GetText() const;
45
46 /// @returns decoded value of the tag in the log record
47 /// @throws if no such tag in the log
48 const std::string& GetTag(std::string_view key) const;
49
50 /// @returns decoded value of the tag in the log record, or `std::nullopt`
51 std::optional<std::string> GetTagOptional(std::string_view key) const;
52
53 /// @returns decoded value of the tag in the log record, or `nullptr`
54 const std::string* GetTagOrNullptr(std::string_view key) const;
55
56 /// @returns serialized log record
57 const std::string& GetLogRaw() const;
58
59 /// @returns the log level of the record
60 logging::Level GetLevel() const;
61
62 /// @cond
63 // For internal use only.
64 LogRecord(utils::impl::InternalTag, logging::Level level, std::string&& log_raw);
65 /// @endcond
66
67private:
68 logging::Level level_;
69 std::string log_raw_;
70 std::vector<std::pair<std::string, std::string>> tags_;
71};
72
73std::ostream& operator<<(std::ostream&, const LogRecord& data);
74
75std::ostream& operator<<(std::ostream&, const std::vector<LogRecord>& data);
76
77/// Thrown by @ref GetSingleLog.
78class NotSingleLogError final : public std::runtime_error {
79public:
80 using std::runtime_error::runtime_error;
81};
82
83/// @returns the only log record from `log`.
84/// @throws NotSingleLogError if there are zero or multiple log records.
85LogRecord GetSingleLog(
86 utils::span<const LogRecord> log,
87 const utils::impl::SourceLocation& source_location = utils::impl::SourceLocation::Current()
88);
89
90/// @returns log records parsed from TSKV file contents.
91/// Each line must be a complete TSKV record ending with `\n`.
93
94/// @ingroup userver_utest
95///
96/// @brief A mocked logger that stores the log records in memory.
97///
98/// @snippet grpc/tests/cancel_test.cpp Sample of LogCaptureFixture
99///
100/// @see @ref utest::LogCaptureFixture
101class LogCaptureLogger final {
102public:
103 explicit LogCaptureLogger(logging::Format format = logging::Format::kRaw);
104
105 /// @returns the mocked logger.
106 logging::TextLoggerPtr GetLogger() const;
107
108 /// @returns all collected logs.
109 /// @see @ref GetSingleLog
111
112 /// @returns logs filtered by (optional) text substring and (optional) tags substrings.
113 /// @see @ref GetSingleLog
117 ) const;
118
119 /// @returns logs filtered by an arbitrary predicate.
120 /// @see @ref GetSingleLog
122
123 /// @brief Discards the collected logs.
124 void Clear() noexcept;
125
126 /// @brief Logs @a value as-if using `LOG_*`, then extracts the log text.
127 template <typename T>
128 std::string ToStringViaLogging(const T& value) {
129 Clear();
130 LOG_CRITICAL() << value;
131 auto text = GetSingleLog(GetAll()).GetText();
132 Clear();
133 return text;
134 }
135
136private:
137 utils::SharedRef<impl::ToStringLogger> logger_;
138};
139
140/// @ingroup userver_utest
141///
142/// @brief Fixture that allows to capture and extract log written into the default logger.
143///
144/// @snippet grpc/tests/cancel_test.cpp Sample of LogCaptureFixture
145///
146/// @see @ref utest::LogCaptureLogger
147template <typename Base = ::testing::Test>
149protected:
150 LogCaptureFixture() { DefaultLoggerFixture<Base>::SetDefaultLogger(logger_.GetLogger()); }
151
152 /// @returns logger that holds the log records of the unit test
153 LogCaptureLogger& GetLogCapture() { return logger_; }
154
155private:
156 LogCaptureLogger logger_;
157};
158
159} // namespace utest
160
161USERVER_NAMESPACE_END