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