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/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