Line data Source code
1 : #pragma once 2 : 3 : // This component defines a class, `Span`, that represents an extent of time in 4 : // which some operation of interest occurs, such as an RPC request, database 5 : // query, calculation, etc. 6 : // 7 : // `Span` objects are created by calling member functions on `Tracer` or on 8 : // another `Span` object. They are not instantiated directly. 9 : // 10 : // A `Span` has a start time, an end time, and a name (sometimes called its 11 : // "operation name"). A span is associated with a service, a resource (such as 12 : // the URL endpoint in an HTTP request), and arbitrary key/value string pairs 13 : // known as tags. 14 : // 15 : // A `Span` can have at most one parent and can have zero or more children. The 16 : // operation that a `Span` represents is a subtask of the operation that its 17 : // parent represents, and the children of a `Span` represent subtasks of its 18 : // operation. 19 : // 20 : // For example, an HTTP server might create a `Span` for each request processed. 21 : // The `Span` begins when the server begins reading the request, and ends when 22 : // the server has finished writing the response or reporting an error. The 23 : // first child of the request span might represent the reading and parsing of 24 : // the HTTP request's headers. The second child of the request span might 25 : // represent the dispatch of the request handling to an endpoint-specific 26 : // handler. That child might itself have children, such as a database query or 27 : // a request to an authentication service. 28 : // 29 : // The complete set of spans that are related to each other via the parent/child 30 : // relationship is called a trace. 31 : // 32 : // A trace can extend across processes and networks via trace context 33 : // propagation. A `Span` can be _extracted_ from its external parent via 34 : // `Tracer::extract_span`, and a `Span` can be _injected_ via `Span::inject` 35 : // into an outside context from which its external children might be extracted. 36 : // 37 : // If an error occurs during the operation that a span represents, the error can 38 : // be noted in the span via the `set_error` family of member functions. 39 : // 40 : // A `Span` is finished when it is destroyed. The end time can be overridden 41 : // via the `set_end_time` member function prior to the span's destruction. 42 : 43 : #include <chrono> 44 : #include <cstdint> 45 : #include <functional> 46 : #include <memory> 47 : 48 : #include "clock.h" 49 : #include "error.h" 50 : #include "optional.h" 51 : #include "string_view.h" 52 : #include "trace_id.h" 53 : 54 : namespace datadog { 55 : namespace tracing { 56 : 57 : class DictWriter; 58 : struct SpanConfig; 59 : struct SpanData; 60 : class TraceSegment; 61 : 62 : class Span { 63 : std::shared_ptr<TraceSegment> trace_segment_; 64 : SpanData* data_; 65 : std::function<std::uint64_t()> generate_span_id_; 66 : Clock clock_; 67 : Optional<std::chrono::steady_clock::time_point> end_time_; 68 : 69 : public: 70 : // Create a span whose properties are stored in the specified `data`, that is 71 : // associated with the specified `trace_segment`, that uses the specified 72 : // `generate_span_id` to generate IDs of child spans, and that uses the 73 : // specified `clock` to determine start and end times. 74 : Span(SpanData* data, const std::shared_ptr<TraceSegment>& trace_segment, 75 : const std::function<std::uint64_t()>& generate_span_id, 76 : const Clock& clock); 77 : Span(const Span&) = delete; 78 140 : Span(Span&&) = default; 79 : Span& operator=(Span&&) = delete; 80 : Span& operator=(const Span&) = delete; 81 : 82 : // Finish this span and submit it to the associated trace segment. If 83 : // `set_end_time` has not been called on this span, then set this span's end 84 : // time to the current time. 85 : // If this span was moved-from, then the destructor has no effect aside from 86 : // destroying data members. 87 : ~Span(); 88 : 89 : // Return a span that is a child of this span. Use the optionally specified 90 : // `config` to determine the properties of the child span. If `config` is not 91 : // specified, then the child span's properties are determined by the 92 : // `SpanDefaults` that were used to configure the `Tracer` to which this span 93 : // is related. The child span's start time is the current time unless 94 : // overridden in `config`. 95 : Span create_child(const SpanConfig& config) const; 96 : Span create_child() const; 97 : 98 : // Return this span's ID (span ID). 99 : std::uint64_t id() const; 100 : // Return the ID of the trace of which this span is a part. 101 : TraceID trace_id() const; 102 : // Return the ID of this span's parent span, or return null if this span has 103 : // no parent. 104 : Optional<std::uint64_t> parent_id() const; 105 : // Return the start time of this span. 106 : TimePoint start_time() const; 107 : // Return whether this span has been marked as an error having occurred during 108 : // its extent. 109 : bool error() const; 110 : // Return the name of the service associated with this span, e.g. 111 : // "ingress-nginx-useast1". 112 : const std::string& service_name() const; 113 : // Return the type of the service associated with this span, e.g. "web". 114 : const std::string& service_type() const; 115 : // Return the name of the operation associated with the operation that this 116 : // span represents, e.g. "handle.request", "execute.query", or "healthcheck". 117 : const std::string& name() const; 118 : // Return the name of the resource associated with the operation that this 119 : // span represents, e.g. "/api/v1/info" or "select count(*) from users". 120 : const std::string& resource_name() const; 121 : 122 : // Return the value of the tag having the specified `name`, or return null if 123 : // there is no such tag. 124 : Optional<StringView> lookup_tag(StringView name) const; 125 : // Overwrite the tag having the specified `name` so that it has the specified 126 : // `value`, or create a new tag. 127 : void set_tag(StringView name, StringView value); 128 : // Delete the tag having the specified `name` if it exists. 129 : void remove_tag(StringView name); 130 : 131 : // Set the name of the service associated with this span, e.g. 132 : // "ingress-nginx-useast1". 133 : void set_service_name(StringView); 134 : // Set the type of the service associated with this span, e.g. "web". 135 : void set_service_type(StringView); 136 : // Set the name of the operation that this span represents, e.g. 137 : // "handle.request", "execute.query", or "healthcheck". 138 : void set_name(StringView); 139 : // Set the name of the resource associated with the operation that this span 140 : // represents, e.g. "/api/v1/info" or "select count(*) from users". 141 : void set_resource_name(StringView); 142 : // Set whether an error occurred during the extent of this span. If `false`, 143 : // then error-related tags will be removed from this span as well. 144 : void set_error(bool); 145 : // Associate a message with the error that occurred during the extent of this 146 : // span. This also has the effect of calling `set_error(true)`. 147 : void set_error_message(StringView); 148 : // Associate an error type with the error that occurred during the extent of 149 : // this span. This also has the effect of calling `set_error(true)`. 150 : void set_error_type(StringView); 151 : // Associate a call stack with the error that occurred during the extent of 152 : // this span. This also has the effect of calling `set_error(true)`. 153 : void set_error_stack(StringView); 154 : // Set end time of this span. Doing so will override the default behavior of 155 : // using the current time in the destructor. 156 : void set_end_time(std::chrono::steady_clock::time_point); 157 : 158 : // Write information about this span and its trace into the specified `writer` 159 : // for purposes of trace propagation. 160 : void inject(DictWriter& writer) const; 161 : 162 : // Return a reference to this span's trace segment. The trace segment has 163 : // member functions that affect the trace as a whole, such as 164 : // `TraceSegment::override_sampling_priority`. 165 : TraceSegment& trace_segment(); 166 : const TraceSegment& trace_segment() const; 167 : }; 168 : 169 : } // namespace tracing 170 : } // namespace datadog