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 /// Create a child which can be used independently from the parent.
102 ///
103 /// The child shares no state with its parent. If you need to run code in
104 /// parallel, create a child span and use the child in a separate task.
105 Span CreateChild(std::string name) const;
106
107 Span CreateFollower(std::string name) const;
108
109 /// @brief Creates a tracing::ScopeTime attached to the span.
111
112 /// @brief Creates a tracing::ScopeTime attached to the Span and starts
113 /// measuring execution time.
114 ScopeTime CreateScopeTime(std::string name);
115
116 /// Returns total time elapsed for a certain scope of this span.
117 /// If there is no record for the scope, returns 0.
118 ScopeTime::Duration GetTotalDuration(const std::string& scope_name) const;
119
120 /// Returns total time elapsed for a certain scope of this span.
121 /// If there is no record for the scope, returns 0.
122 ///
123 /// Prefer using Span::GetTotalDuration()
125 const std::string& scope_name) const;
126
127 /// Add a tag that is used on each logging in this Span and all
128 /// future children.
129 void AddTag(std::string key, logging::LogExtra::Value value);
130
131 /// Add a tag that is used on each logging in this Span and all
132 /// future children. It will not be possible to change its value.
133 void AddTagFrozen(std::string key, logging::LogExtra::Value value);
134
135 /// Add a tag that is local to the Span (IOW, it is not propagated to
136 /// future children) and logged only once in the destructor of the Span.
137 void AddNonInheritableTag(std::string key, logging::LogExtra::Value value);
138
139 /// @brief Sets level for tags logging
140 void SetLogLevel(logging::Level log_level);
141
142 /// @brief Returns level for tags logging
144
145 /// @brief Sets the local log level that disables logging of this span if
146 /// the local log level set and greater than the main log level of the Span.
147 void SetLocalLogLevel(std::optional<logging::Level> log_level);
148
149 /// @brief Returns the local log level that disables logging of this span if
150 /// it is set and greater than the main log level of the Span.
151 std::optional<logging::Level> GetLocalLogLevel() const;
152
153 /// Set link - a request ID within a service. Can be called only once.
154 ///
155 /// Propagates within a single service, but not from client to server. A new
156 /// link is generated for the "root" request handling task
157 void SetLink(std::string link);
158
159 /// Set parent_link - an ID . Can be called only once.
160 void SetParentLink(std::string parent_link);
161
162 /// Get link - a request ID within the service.
163 ///
164 /// Propagates within a single service, but not from client to server. A new
165 /// link is generated for the "root" request handling task
166 std::string GetLink() const;
167
168 std::string GetParentLink() const;
169
170 /// An ID of the request that does not change from service to service.
171 ///
172 /// Propagates both to sub-spans within a single service, and from client
173 /// to server
174 const std::string& GetTraceId() const;
175
176 /// Identifies a specific span. It does not propagate
177 const std::string& GetSpanId() const;
178 const std::string& GetParentId() const;
179
180 /// @returns true if this span would be logged with the current local and
181 /// global log levels to the default logger.
182 bool ShouldLogDefault() const noexcept;
183
184 /// Detach the Span from current engine::Task so it is not
185 /// returned by CurrentSpan() any more.
187
188 /// Attach the Span to current engine::Task so it is returned
189 /// by CurrentSpan().
191
192 std::chrono::system_clock::time_point GetStartSystemTime() const;
193
194 /// @cond
195 void AddTags(const logging::LogExtra&, utils::InternalTag);
196
197 void AddNonInheritableTags(const logging::LogExtra&, utils::InternalTag);
198
199 impl::TimeStorage& GetTimeStorage();
200
201 // For internal use only.
202 void LogTo(logging::impl::TagWriter writer) const&;
203 /// @endcond
204
205 private:
206 struct OptionalDeleter {
207 void operator()(Impl*) const noexcept;
208
209 static OptionalDeleter ShouldDelete() noexcept;
210
211 static OptionalDeleter DoNotDelete() noexcept;
212
213 private:
214 explicit OptionalDeleter(bool do_delete) : do_delete(do_delete) {}
215
216 const bool do_delete;
217 };
218
219 friend class SpanBuilder;
220
221 explicit Span(std::unique_ptr<Impl, OptionalDeleter>&& pimpl);
222
223 std::string GetTag(std::string_view tag) const;
224
225 std::unique_ptr<Impl, OptionalDeleter> pimpl_;
226};
227
228namespace impl {
229
230struct LogSpanAsLastNonCoro final {
231 const Span& span;
232};
233
234logging::LogHelper& operator<<(logging::LogHelper& lh,
235 LogSpanAsLastNonCoro span);
236
237} // namespace impl
238
239} // namespace tracing
240
241USERVER_NAMESPACE_END