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