summaryrefslogtreecommitdiffstats
path: root/include/opentracing/tracer.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/opentracing/tracer.h')
-rw-r--r--include/opentracing/tracer.h277
1 files changed, 277 insertions, 0 deletions
diff --git a/include/opentracing/tracer.h b/include/opentracing/tracer.h
new file mode 100644
index 0000000..a4a125a
--- /dev/null
+++ b/include/opentracing/tracer.h
@@ -0,0 +1,277 @@
+#ifndef OPENTRACING_TRACER_H
+#define OPENTRACING_TRACER_H
+
+#include <opentracing/propagation.h>
+#include <opentracing/span.h>
+#include <opentracing/string_view.h>
+#include <opentracing/symbols.h>
+#include <opentracing/util.h>
+#include <opentracing/version.h>
+#include <chrono>
+#include <initializer_list>
+#include <iosfwd>
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace opentracing {
+BEGIN_OPENTRACING_ABI_NAMESPACE
+// StartSpanOptions allows Tracer.StartSpan() callers a mechanism to override
+// the start timestamp, specify Span References, and make a single Tag or
+// multiple Tags available at Span start time.
+//
+// StartSpan() callers should look at the StartSpanOption interface and
+// implementations available in this library.
+struct StartSpanOptions {
+ // start_system_timestamp and start_steady_timestamp override the Span's start
+ // time, or implicitly become std::chrono::system_clock::now() and
+ // std::chrono::steady_clock::now() if both are equal to the epoch (default
+ // behavior).
+ //
+ // If one of the timestamps is set but not the other, the set timestamp is
+ // used to estimate the corresponding timestamp of the other.
+ SystemTime start_system_timestamp;
+ SteadyTime start_steady_timestamp;
+
+ // Zero or more causal references to other Spans (via their SpanContext).
+ // If empty, start a "root" Span (i.e., start a new trace).
+ //
+ // Any nullptrs provided will be ignored.
+ std::vector<std::pair<SpanReferenceType, const SpanContext*>> references;
+
+ // Zero or more tags to apply to the newly created span.
+ std::vector<std::pair<std::string, Value>> tags;
+};
+
+// StartSpanOption instances (zero or more) may be passed to Tracer.StartSpan.
+class StartSpanOption {
+ public:
+ StartSpanOption(const StartSpanOption&) = delete;
+
+ virtual ~StartSpanOption() = default;
+
+ virtual void Apply(StartSpanOptions& options) const noexcept = 0;
+
+ protected:
+ StartSpanOption() = default;
+};
+
+// Tracer is a simple, thin interface for Span creation and SpanContext
+// propagation.
+class OPENTRACING_API Tracer {
+ public:
+ virtual ~Tracer() = default;
+
+ // Create, start, and return a new Span with the given `operationName` and
+ // incorporate the given StartSpanOption `option_list`.
+ //
+ // A Span with no SpanReference options (e.g., opentracing::ChildOf() or
+ // opentracing::FollowsFrom()) becomes the root of its own trace.
+ //
+ // Examples:
+ //
+ // opentracing::Tracer& tracer = ...
+ //
+ // // The root-span case:
+ // auto span = tracer.StartSpan("GetFeed")
+ //
+ // // The vanilla child span case:
+ // auto span = tracer.StartSpan(
+ // "GetFeed",
+ // {opentracing::ChildOf(&parentSpan.context())})
+ //
+ // // All the bells and whistles:
+ // auto span = tracer.StartSpan(
+ // "GetFeed",
+ // {opentracing::ChildOf(&parentSpan.context()),
+ // opentracing::Tag{"user_agent", loggedReq.UserAgent},
+ // opentracing::StartTimestamp(loggedReq.timestamp())})
+ //
+ // If StartSpan is called after Close, it leaves the Tracer in a valid
+ // state, but its behavior is unspecified.
+ std::unique_ptr<Span> StartSpan(
+ string_view operation_name,
+ std::initializer_list<option_wrapper<StartSpanOption>> option_list = {})
+ const noexcept {
+ StartSpanOptions options;
+ for (const auto& option : option_list) option.get().Apply(options);
+ return StartSpanWithOptions(operation_name, options);
+ }
+
+ virtual std::unique_ptr<Span> StartSpanWithOptions(
+ string_view operation_name, const StartSpanOptions& options) const
+ noexcept = 0;
+
+ // Inject() takes the `sc` SpanContext instance and injects it for propagation
+ // within `carrier`.
+ //
+ // OpenTracing defines a common set of `carrier` interfaces.
+ //
+ // Throws only if `writer` does.
+ //
+ // If `writer` is an `std::ostream`, then Inject() propagates `sc` as a blob
+ // of binary data.
+ virtual expected<void> Inject(const SpanContext& sc,
+ std::ostream& writer) const = 0;
+
+ virtual expected<void> Inject(const SpanContext& sc,
+ const TextMapWriter& writer) const = 0;
+
+ virtual expected<void> Inject(const SpanContext& sc,
+ const HTTPHeadersWriter& writer) const = 0;
+
+ virtual expected<void> Inject(const SpanContext& sc,
+ const CustomCarrierWriter& writer) const {
+ return writer.Inject(*this, sc);
+ }
+
+ // Extract() returns a SpanContext instance given `carrier`.
+ //
+ // OpenTracing defines a common set of `carrier` interfaces.
+ //
+ // Returns a `SpanContext` that is `non-null` on success or nullptr if no span
+ // is found; otherwise an std::error_code.
+ //
+ // Throws only if `reader` does.
+ virtual expected<std::unique_ptr<SpanContext>> Extract(
+ std::istream& reader) const = 0;
+
+ virtual expected<std::unique_ptr<SpanContext>> Extract(
+ const TextMapReader& reader) const = 0;
+
+ virtual expected<std::unique_ptr<SpanContext>> Extract(
+ const HTTPHeadersReader& reader) const = 0;
+
+ virtual expected<std::unique_ptr<SpanContext>> Extract(
+ const CustomCarrierReader& reader) const {
+ return reader.Extract(*this);
+ }
+
+ // Close is called when a tracer is finished processing spans. It is not
+ // required to be called and its effect is unspecified. For example, an
+ // implementation might use this function to flush buffered spans to its
+ // recording system and failing to call it could result in some spans being
+ // dropped.
+ virtual void Close() noexcept {}
+
+ // GlobalTracer returns the global tracer.
+ static std::shared_ptr<Tracer> Global() noexcept;
+
+ // InitGlobalTracer sets the global tracer pointer, returns the
+ // former global tracer value.
+ static std::shared_ptr<Tracer> InitGlobal(
+ std::shared_ptr<Tracer> tracer) noexcept;
+
+ static bool IsGlobalTracerRegistered() noexcept;
+};
+
+// StartTimestamp is a StartSpanOption that sets an explicit start timestamp for
+// the new Span.
+class StartTimestamp : public StartSpanOption {
+ public:
+ StartTimestamp(SystemTime system_when, SteadyTime steady_when) noexcept
+ : system_when_(system_when), steady_when_(steady_when) {}
+
+ StartTimestamp(SystemTime system_when) noexcept
+ : system_when_(system_when),
+ steady_when_(convert_time_point<SteadyClock>(system_when_)) {}
+
+ // Construct a timestamp using a duration from the epoch of std::time_t.
+ // From the documentation on std::time_t's epoch:
+ // Although not defined, this is almost always an integral value holding
+ // the number of seconds (not counting leap seconds) since 00:00, Jan 1
+ // 1970 UTC, corresponding to POSIX time
+ // See http://en.cppreference.com/w/cpp/chrono/c/time_t
+ template <class Rep, class Period>
+ explicit StartTimestamp(
+ const std::chrono::duration<Rep, Period>& time_since_epoch) noexcept
+ : StartTimestamp(SystemClock::from_time_t(std::time_t(0)) +
+ std::chrono::duration_cast<SystemClock::duration>(
+ time_since_epoch)) {}
+
+ StartTimestamp(const StartTimestamp& other) noexcept
+ : StartSpanOption(),
+ system_when_(other.system_when_),
+ steady_when_(other.steady_when_) {}
+
+ void Apply(StartSpanOptions& options) const noexcept override {
+ options.start_system_timestamp = system_when_;
+ options.start_steady_timestamp = steady_when_;
+ }
+
+ private:
+ SystemTime system_when_;
+ SteadyTime steady_when_;
+};
+
+// SpanReference is a StartSpanOption that pairs a SpanReferenceType and a
+// referenced SpanContext. See the SpanReferenceType documentation for
+// supported relationships.
+//
+// If the referenced SpanContext is a nullptr, it is ignored. The passed
+// SpanContext is copied during Span construction and the pointer is not
+// retained.
+class SpanReference : public StartSpanOption {
+ public:
+ SpanReference(SpanReferenceType type, const SpanContext* referenced) noexcept
+ : type_(type), referenced_(referenced) {}
+
+ SpanReference(const SpanReference& other) noexcept
+ : StartSpanOption(), type_(other.type_), referenced_(other.referenced_) {}
+
+ void Apply(StartSpanOptions& options) const noexcept override {
+ try {
+ if (referenced_) options.references.emplace_back(type_, referenced_);
+ } catch (const std::bad_alloc&) {
+ // Ignore reference if memory can't be allocated for it.
+ }
+ }
+
+ private:
+ SpanReferenceType type_;
+ const SpanContext* referenced_;
+};
+
+// ChildOf returns a StartSpanOption pointing to a dependent parent span.
+//
+// See ChildOfRef, SpanReference
+inline SpanReference ChildOf(const SpanContext* span_context) noexcept {
+ return {SpanReferenceType::ChildOfRef, span_context};
+}
+
+// FollowsFrom returns a StartSpanOption pointing to a parent Span that caused
+// the child Span but does not directly depend on its result in any way.
+//
+// See FollowsFromRef, SpanReference
+inline SpanReference FollowsFrom(const SpanContext* span_context) noexcept {
+ return {SpanReferenceType::FollowsFromRef, span_context};
+}
+
+// SetTag may be passed as a StartSpanOption to add a tag to new spans,
+// for example:
+//
+// tracer.StartSpan("opName", SetTag{"Key", value})
+class SetTag : public StartSpanOption {
+ public:
+ SetTag(string_view key, const Value& value) noexcept
+ : key_(key), value_(value) {}
+
+ SetTag(const SetTag& other) noexcept
+ : StartSpanOption(), key_(other.key_), value_(other.value_) {}
+
+ void Apply(StartSpanOptions& options) const noexcept override {
+ try {
+ options.tags.emplace_back(key_, value_);
+ } catch (const std::bad_alloc&) {
+ // Ignore tag if memory can't be allocated for it.
+ }
+ }
+
+ private:
+ const string_view key_;
+ const Value& value_;
+};
+END_OPENTRACING_ABI_NAMESPACE
+} // namespace opentracing
+
+#endif // OPENTRACING_TRACER_H