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