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