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