userver: userver/logging/log_extra.hpp Source File
Loading...
Searching...
No Matches
log_extra.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/logging/log_extra.hpp
4/// @brief @copybrief logging::LogExtra
5
6#include <initializer_list>
7#include <string>
8#include <utility>
9#include <variant>
10
11#include <boost/container/container_fwd.hpp>
12
13#include <userver/compiler/select.hpp>
14#include <userver/logging/fwd.hpp>
15#include <userver/logging/json_string.hpp>
16#include <userver/utils/fast_pimpl.hpp>
17
18USERVER_NAMESPACE_BEGIN
19
20namespace tracing {
21
22class TagScope;
23
24class Span;
25
26} // namespace tracing
27
28namespace logging {
29
30class LogHelper;
31
32namespace impl {
33class TagWriter;
34class LogExtraTskvFormatter;
35} // namespace impl
36
37/// Extra tskv fields storage
38class LogExtra final {
39public:
40 using Value = std::variant<
41 std::string,
42 int,
43 bool,
44 long,
45 long long,
46 unsigned int,
47 unsigned long,
48 unsigned long long,
49 float,
50 double,
52 using Key = std::string;
53 using Pair = std::pair<Key, Value>;
54
55 /// Specifies replacement policy for newly added values
56 enum class ExtendType {
57 kNormal, ///< Added value can be replaced
58 kFrozen, ///< Attempts to replace this value will be ignored
59 };
60
61 LogExtra() noexcept;
62
63 LogExtra(const LogExtra&);
64
65 // NOLINTNEXTLINE(performance-noexcept-move-constructor)
66 LogExtra(LogExtra&&);
67
68 ~LogExtra();
69
70 // NOLINTNEXTLINE(performance-noexcept-move-constructor)
71 LogExtra& operator=(LogExtra&&);
72
73 LogExtra& operator=(const LogExtra&);
74
75 /// Constructs LogExtra containing an initial batch of key-value pairs
76 LogExtra(std::initializer_list<Pair> initial, ExtendType extend_type = ExtendType::kNormal);
77
78 /// Adds a single key-value pair
79 void Extend(std::string key, Value value, ExtendType extend_type = ExtendType::kNormal);
80
81 /// Adds a single key-value pair
82 void Extend(Pair extra, ExtendType extend_type = ExtendType::kNormal);
83
84 /// Adds a batch of key-value pairs
85 void Extend(std::initializer_list<Pair> extra, ExtendType extend_type = ExtendType::kNormal);
86
87 /// @brief Merges contents of other LogExtra with existing key-value pairs
88 /// preserving freeze states
89 void Extend(const LogExtra& extra);
90
91 /// @brief Merges contents of other LogExtra with existing key-value pairs
92 /// preserving freeze states
93 void Extend(LogExtra&& extra);
94
95 /// @brief Creates a LogExtra with current thread's stacktrace if the default
96 /// log level is less or equal to DEBUG
97 static LogExtra StacktraceNocache() noexcept;
98
99 /// @brief Creates a LogExtra with current thread's stacktrace if the logger
100 /// log level is less or equal to DEBUG
101 static LogExtra StacktraceNocache(logging::LoggerRef logger) noexcept;
102
103 /// @brief Creates a LogExtra with current thread's stacktrace if the logger
104 /// log level is less or equal to DEBUG. Uses cache for
105 /// faster stacktrace symbolization.
106 static LogExtra Stacktrace() noexcept;
107
108 /// @brief Creates a LogExtra with current thread's stacktrace if the logger
109 /// log level is less or equal to DEBUG. Uses cache for
110 /// faster stacktrace symbolization.
111 static LogExtra Stacktrace(logging::LoggerRef logger) noexcept;
112
113 /// @brief Adds a range of key-value pairs
114 template <typename Iterator>
115 void ExtendRange(Iterator first, Iterator last, ExtendType extend_type = ExtendType::kNormal) {
116 // NOTE: must replace existing rewritable values
117 for (Iterator it = first; it != last; ++it) Extend(*it, extend_type);
118 }
119
120 /// @brief Marks specified value as frozen, all attempts to overwrite it will
121 /// be silently ignored.
122 void SetFrozen(const std::string& key);
123
124 friend class LogHelper;
125 friend class impl::LogExtraTskvFormatter;
126 friend class impl::TagWriter;
127 friend class tracing::Span;
128 friend class tracing::TagScope;
129
130private:
131 const Value& GetValue(std::string_view key) const;
132
133 class ProtectedValue final {
134 public:
135 ProtectedValue() = default;
136 ProtectedValue(Value value, bool frozen);
137 ProtectedValue(const ProtectedValue& other) = default;
138 ProtectedValue(ProtectedValue&& other) = default;
139
140 ProtectedValue& operator=(const ProtectedValue& other);
141 ProtectedValue& operator=(ProtectedValue&& other) noexcept;
142
143 bool IsFrozen() const;
144 void SetFrozen();
145 Value& GetValue() { return value_; }
146 const Value& GetValue() const { return value_; }
147 void AssignIgnoringFrozenness(ProtectedValue other);
148
149 private:
150 Value value_;
151 bool frozen_ = false;
152 };
153
154 static constexpr std::size_t kSmallVectorSize = 24;
155 static constexpr std::size_t kPimplSize =
156 compiler::SelectSize().ForLibCpp32(1168).ForLibCpp64(1560).ForLibStdCpp64(1944).ForLibStdCpp32(1356);
157 using MapItem = std::pair<Key, ProtectedValue>;
158 using Map = boost::container::small_vector<MapItem, kSmallVectorSize>;
159
160 void Extend(std::string key, ProtectedValue protected_value, ExtendType extend_type = ExtendType::kNormal);
161
162 void Extend(MapItem extra, ExtendType extend_type = ExtendType::kNormal);
163
164 std::pair<Key, ProtectedValue>* Find(std::string_view);
165
166 const std::pair<Key, ProtectedValue>* Find(std::string_view) const;
167
168 utils::FastPimpl<Map, kPimplSize, alignof(void*)> extra_;
169};
170
171extern const LogExtra kEmptyLogExtra;
172
173} // namespace logging
174
175USERVER_NAMESPACE_END