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