Github   Telegram
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/internal_tag_fwd.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace tracing {
18
19/// @brief Measures the execution time of the current code block, links it with
20/// the parent tracing::Spans and stores that info in the log.
21///
22/// See @ref md_en_userver_logging for usage examples and more descriptions.
23///
24/// @warning Shall be created only as a local variable. Do not use it as a
25/// class member!
26class Span final {
27 public:
28 class Impl;
29
30 explicit Span(TracerPtr tracer, std::string name, const Span* parent,
31 ReferenceType reference_type,
32 logging::Level log_level = logging::Level::kInfo);
33
34 /* Use default tracer and implicit coro local storage for parent
35 * identification */
36 explicit Span(std::string name,
37 ReferenceType reference_type = ReferenceType::kChild,
38 logging::Level log_level = logging::Level::kInfo);
39
40 /// @cond
41 // For internal use only
42 explicit Span(Span::Impl& impl);
43 /// @endcond
44
45 Span(Span&& other) noexcept;
46
47 ~Span();
48
49 Span& operator=(const Span&) = delete;
50
51 Span& operator=(Span&&) = delete;
52
53 /// @brief Returns the Span of the current task.
54 ///
55 /// Should not be called in non-coroutine
56 /// context. Should not be called from a task with no alive Span.
57 ///
58 /// Rule of thumb: it is safe to call it from a task created by
59 /// utils::Async/utils::CriticalAsync/utils::PeriodicTask. If current task was
60 /// created with an explicit engine::impl::*Async(), you have to create a Span
61 /// beforehand.
62 static Span& CurrentSpan();
63
64 /// @brief Returns nullptr if called in non-coroutine context or from a task
65 /// with no alive Stan; otherwise returns the Span of the current task.
66 static Span* CurrentSpanUnchecked();
67
68 /// @return A new Span attached to current Span (if any).
69 static Span MakeSpan(std::string name, std::string_view trace_id,
70 std::string_view parent_span_id);
71
72 /// @return A new Span attached to current Span (if any), sets `link`.
73 static Span MakeSpan(std::string name, std::string_view trace_id,
74 std::string_view parent_span_id, std::string link);
75
76 /// Create a child which can be used independently from the parent.
77 ///
78 /// The child shares no state with its parent. If you need to run code in
79 /// parallel, create a child span and use the child in a separate task.
80 Span CreateChild(std::string name) const;
81
82 Span CreateFollower(std::string name) const;
83
84 /// @brief Creates a tracing::ScopeTime attached to the span.
85 ///
86 /// Note that
87 ///
88 /// @code
89 /// auto scope = tracing::Span::CurrentSpan().CreateScopeTime();
90 /// @endcode
91 ///
92 /// is equivalent to
93 ///
94 /// @code
95 /// tracing::Span scope;
96 /// @endcode
98
99 /// @brief Creates a tracing::ScopeTime attached to the Span and starts
100 /// measuring execution time.
101 ///
102 /// Note that
103 ///
104 /// @code
105 /// auto scope = tracing::Span::CurrentSpan().CreateScopeTime(name);
106 /// @endcode
107 ///
108 /// is equivalent to
109 ///
110 /// @code
111 /// tracing::Span scope{name};
112 /// @endcode
113 ScopeTime CreateScopeTime(std::string name);
114
115 /// Returns total time elapsed for a certain scope of this span.
116 /// If there is no record for the scope, returns 0.
117 ScopeTime::Duration GetTotalDuration(const std::string& scope_name) const;
118
119 /// Returns total time elapsed for a certain scope of this span.
120 /// If there is no record for the scope, returns 0.
121 ///
122 /// Prefer using Span::GetTotalDuration()
124 const std::string& scope_name) const;
125
126 /// Add a tag that is used on each logging in this Span and all
127 /// future children.
128 void AddTag(std::string key, logging::LogExtra::Value value);
129
130 /// Add a tag that is used on each logging in this Span and all
131 /// future children. It will not be possible to change its value.
132 void AddTagFrozen(std::string key, logging::LogExtra::Value value);
133
134 /// Add a tag that is local to the Span (IOW, it is not propagated to
135 /// future children) and logged only once in the destructor of the Span.
136 void AddNonInheritableTag(std::string key, logging::LogExtra::Value value);
137
138 /// @brief Sets level for tags logging
139 void SetLogLevel(logging::Level log_level);
140
141 /// @brief Returns level for tags logging
143
144 /// @brief Sets the local log level that disables logging of this span if
145 /// the local log level set and greater than the main log level of the Span.
146 void SetLocalLogLevel(std::optional<logging::Level> log_level);
147
148 /// @brief Returns the local log level that disables logging of this span if
149 /// it is set and greater than the main log level of the Span.
150 std::optional<logging::Level> GetLocalLogLevel() const;
151
152 /// Set link. Can be called only once.
153 void SetLink(std::string link);
154
155 /// Set parent_link. Can be called only once.
156 void SetParentLink(std::string parent_link);
157
158 std::string GetLink() const;
159
160 std::string GetParentLink() const;
161
162 const std::string& GetTraceId() const;
163 const std::string& GetSpanId() const;
164 const std::string& GetParentId() const;
165
166 void LogTo(logging::LogHelper& log_helper) const&;
167
168 /// @returns true if this span would be logged with the current local and
169 /// global log levels to the default logger.
170 bool ShouldLogDefault() const noexcept;
171
172 /// Detach the Span from current engine::Task so it is not
173 /// returned by CurrentSpan() any more.
175
176 /// Attach the Span to current engine::Task so it is returned
177 /// by CurrentSpan().
179
180 /// @cond
181 void AddTags(const logging::LogExtra&, utils::InternalTag);
182
183 impl::TimeStorage& GetTimeStorage();
184 /// @endcond
185
186 private:
187 std::string GetTag(std::string_view tag) const;
188
189 struct OptionalDeleter {
190 void operator()(Impl*) const noexcept;
191
192 static OptionalDeleter ShouldDelete() noexcept;
193
194 static OptionalDeleter DoNotDelete() noexcept;
195
196 private:
197 explicit OptionalDeleter(bool do_delete) : do_delete(do_delete) {}
198
199 const bool do_delete;
200 };
201
202 std::unique_ptr<Impl, OptionalDeleter> pimpl_;
203};
204
205logging::LogHelper& operator<<(logging::LogHelper& lh, const Span& span);
206
207} // namespace tracing
208
209USERVER_NAMESPACE_END