userver: userver/tracing/span.hpp Source File
Loading...
Searching...
No Matches
span.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/tracing/span.hpp
4/// @brief @copybrief tracing::Span
5
6#include <optional>
7#include <string_view>
8
9#include <userver/logging/log.hpp>
10#include <userver/logging/log_extra.hpp>
11#include <userver/tracing/scope_time.hpp>
12#include <userver/tracing/tracer_fwd.hpp>
13#include <userver/utils/impl/internal_tag.hpp>
14#include <userver/utils/impl/source_location.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace tracing {
19
20class SpanBuilder;
21
22/// @brief Measures the execution time of the current code block, links it with
23/// the parent tracing::Spans and stores that info in the log.
24///
25/// Logging of spans can be controlled at runtime via @ref USERVER_NO_LOG_SPANS.
26///
27/// See @ref scripts/docs/en/userver/logging.md for usage examples and more
28/// descriptions.
29///
30/// @warning Shall be created only as a local variable. Do not use it as a
31/// class member!
32class Span final {
33public:
34 class Impl;
35
36 explicit Span(
37 TracerPtr tracer,
38 std::string name,
39 const Span* parent,
40 ReferenceType reference_type,
41 logging::Level log_level = logging::Level::kInfo,
42 utils::impl::SourceLocation source_location = utils::impl::SourceLocation::Current()
43 );
44
45 /// Use default tracer and implicit coro local storage for parent
46 /// identification, takes TraceID from the parent.
47 ///
48 /// For extremely rare cases where a new Trace ID is required use
49 /// tracing::Span::MakeSpan().
50 explicit Span(
51 std::string name,
52 ReferenceType reference_type = ReferenceType::kChild,
53 logging::Level log_level = logging::Level::kInfo,
54 utils::impl::SourceLocation source_location = utils::impl::SourceLocation::Current()
55 );
56
57 /// @cond
58 // For internal use only
59 explicit Span(Span::Impl& impl);
60 /// @endcond
61
62 Span(Span&& other) noexcept;
63
64 ~Span();
65
66 Span& operator=(const Span&) = delete;
67
68 Span& operator=(Span&&) = delete;
69
70 /// @brief Returns the Span of the current task.
71 ///
72 /// Should not be called in non-coroutine
73 /// context. Should not be called from a task with no alive Span.
74 ///
75 /// Rule of thumb: it is safe to call it from a task created by
76 /// utils::Async/utils::CriticalAsync/utils::PeriodicTask. If current task was
77 /// created with an explicit engine::impl::*Async(), you have to create a Span
78 /// beforehand.
79 static Span& CurrentSpan();
80
81 /// @brief Returns nullptr if called in non-coroutine context or from a task
82 /// with no alive Span; otherwise returns the Span of the current task.
83 static Span* CurrentSpanUnchecked();
84
85 /// Factory function for extremely rare cases of creating a Span with custom
86 /// IDs; prefer Span constructor instead.
87 ///
88 /// @return A new Span attached to current Span (if any) but with a new
89 /// Trace ID.
90 /// @param name Name of a new Span
91 /// @param trace_id New Trace ID; if empty then the Trace ID is autogenerated
92 /// @param parent_span_id Id of the parent Span, could be empty.
93 static Span MakeSpan(std::string name, std::string_view trace_id, std::string_view parent_span_id);
94
95 /// Factory function for extremely rare cases of creating a Span with custom
96 /// IDs; prefer Span constructor instead.
97 ///
98 /// @return A new Span attached to current Span (if any), sets `link`.
99 /// @param name Name of a new Span
100 /// @param trace_id New Trace ID; if empty then the Trace ID is autogenerated
101 /// @param parent_span_id Id of the parent Span, could be empty.
102 /// @param link The new link
103 static Span
104 MakeSpan(std::string name, std::string_view trace_id, std::string_view parent_span_id, std::string link);
105
106 /// Factory function for rare cases of creating a root Span that starts
107 /// the trace_id chain, ignoring `CurrentSpan`, if any. Useful
108 /// in background jobs, periodics, distlock tasks, cron tasks, etc.
109 /// The result of such jobs is not directly requested by anything.
110 ///
111 /// @return A new Span that is the root of a new Span hierarchy.
112 /// @param name Name of a new Span
113 /// @param log_level Log level for the span's own log record
114 static Span MakeRootSpan(std::string name, logging::Level log_level = logging::Level::kInfo);
115
116 /// Create a child which can be used independently from the parent.
117 ///
118 /// The child shares no state with its parent. If you need to run code in
119 /// parallel, create a child span and use the child in a separate task.
120 Span CreateChild(std::string name) const;
121
122 Span CreateFollower(std::string name) const;
123
124 /// @brief Creates a tracing::ScopeTime attached to the span.
126
127 /// @brief Creates a tracing::ScopeTime attached to the Span and starts
128 /// measuring execution time.
129 /// Tag `{scope_name}_time` with elapsed time is added to result span.
130 ///
131 /// @note `name` parameter is expected to satisfy snake case.
132 /// Otherwise, it is converted to snake case.
133 ScopeTime CreateScopeTime(std::string name);
134
135 /// Returns total time elapsed for a certain scope of this span.
136 /// If there is no record for the scope, returns 0.
137 ScopeTime::Duration GetTotalDuration(const std::string& scope_name) const;
138
139 /// Returns total time elapsed for a certain scope of this span.
140 /// If there is no record for the scope, returns 0.
141 ///
142 /// Prefer using Span::GetTotalDuration()
143 ScopeTime::DurationMillis GetTotalElapsedTime(const std::string& scope_name) const;
144
145 /// Add a tag that is used on each logging in this Span and all
146 /// future children.
147 void AddTag(std::string key, logging::LogExtra::Value value);
148
149 /// Add a tag that is used on each logging in this Span and all
150 /// future children. It will not be possible to change its value.
151 void AddTagFrozen(std::string key, logging::LogExtra::Value value);
152
153 /// Add a tag that is local to the Span (IOW, it is not propagated to
154 /// future children) and logged only once in the destructor of the Span.
155 void AddNonInheritableTag(std::string key, logging::LogExtra::Value value);
156
157 /// @overload AddNonInheritableTag
158 void AddNonInheritableTags(const logging::LogExtra&);
159
160 /// @brief Sets log level with which the current span itself is written into the tracing
161 /// system.
162 ///
163 /// If `Span`'s log level is less than the global logger's log level, then the span is
164 /// not written out. In that case, nested logs are still written to the logging system
165 /// as usual, inheriting `trace_id`, `link`, `span_id` and inheritable tags of the current
166 /// `Span` object.
167 void SetLogLevel(logging::Level log_level);
168
169 /// @brief Returns level for tags logging
171
172 /// @brief Sets an additional cutoff for the logs written in the scope of this `Span`,
173 /// and in nested scopes recursively.
174 ///
175 /// For example, if the global log level is `info`, and the current `Span` has
176 /// (own or inherited) local log level `warning`, then all `LOG_INFO`s within the current
177 /// scope will be thrown away.
178 ///
179 /// Currently, local log level cannot override the global log level of the logger.
180 /// For example, if the global log level is `info`, and the current `Span` has
181 /// (own or inherited) local log level `debug`, then all `LOG_DEBUG`s within the current
182 /// scope will **still** be thrown away.
183 void SetLocalLogLevel(std::optional<logging::Level> log_level);
184
185 /// @brief Returns the local log level that disables logging of this span if
186 /// it is set and greater than the main log level of the Span.
187 std::optional<logging::Level> GetLocalLogLevel() const;
188
189 /// Set link - a request ID within a service. Can be called only once.
190 ///
191 /// Propagates within a single service, but not from client to server. A new
192 /// link is generated for the "root" request handling task
193 void SetLink(std::string link);
194
195 /// Set parent_link - an ID . Can be called only once.
196 void SetParentLink(std::string parent_link);
197
198 /// Get link - a request ID within the service.
199 ///
200 /// Propagates within a single service, but not from client to server. A new
201 /// link is generated for the "root" request handling task
202 std::string GetLink() const;
203
204 std::string GetParentLink() const;
205
206 /// An ID of the request that does not change from service to service.
207 ///
208 /// Propagates both to sub-spans within a single service, and from client
209 /// to server
210 const std::string& GetTraceId() const;
211
212 /// Identifies a specific span. It does not propagate
213 const std::string& GetSpanId() const;
214 const std::string& GetParentId() const;
215
216 /// @returns true if this span would be logged with the current local and
217 /// global log levels to the default logger.
218 bool ShouldLogDefault() const noexcept;
219
220 /// Detach the Span from current engine::Task so it is not
221 /// returned by CurrentSpan() any more.
223
224 /// Attach the Span to current engine::Task so it is returned
225 /// by CurrentSpan().
227
228 std::chrono::system_clock::time_point GetStartSystemTime() const;
229
230 /// @cond
231 // For internal use only.
232 void AddTags(const logging::LogExtra&, utils::impl::InternalTag);
233
234 // For internal use only.
235 impl::TimeStorage& GetTimeStorage(utils::impl::InternalTag);
236
237 // For internal use only.
238 void LogTo(logging::impl::TagWriter writer) const&;
239 /// @endcond
240
241private:
242 struct OptionalDeleter {
243 void operator()(Impl*) const noexcept;
244
245 static OptionalDeleter ShouldDelete() noexcept;
246
247 static OptionalDeleter DoNotDelete() noexcept;
248
249 private:
250 explicit OptionalDeleter(bool do_delete) : do_delete(do_delete) {}
251
252 const bool do_delete;
253 };
254
255 friend class SpanBuilder;
256 friend class TagScope;
257
258 explicit Span(std::unique_ptr<Impl, OptionalDeleter>&& pimpl);
259
260 std::string GetTag(std::string_view tag) const;
261
262 std::unique_ptr<Impl, OptionalDeleter> pimpl_;
263};
264
265namespace impl {
266
267class DetachLocalSpansScope final {
268public:
269 DetachLocalSpansScope() noexcept;
270 ~DetachLocalSpansScope();
271
272 DetachLocalSpansScope(DetachLocalSpansScope&&) = delete;
273 DetachLocalSpansScope& operator=(DetachLocalSpansScope&&) = delete;
274
275private:
276 struct Impl;
277 utils::FastPimpl<Impl, 16, 8> impl_;
278};
279
280struct LogSpanAsLastNoCurrent final {
281 const Span& span;
282};
283
284logging::LogHelper& operator<<(logging::LogHelper& lh, LogSpanAsLastNoCurrent span);
285
286} // namespace impl
287
288} // namespace tracing
289
290USERVER_NAMESPACE_END