From 6556bf11df95072d37b4e9314639003ad5af29f6 Mon Sep 17 00:00:00 2001 From: easy Date: Mon, 3 Feb 2020 15:48:17 +1100 Subject: [PATCH 1/6] Add Span API. --- api/include/opentelemetry/trace/noop.h | 23 ++++++- api/include/opentelemetry/trace/span.h | 90 +++++++++++++++++++++++--- 2 files changed, 102 insertions(+), 11 deletions(-) diff --git a/api/include/opentelemetry/trace/noop.h b/api/include/opentelemetry/trace/noop.h index 00e43774d3..7d31c422df 100644 --- a/api/include/opentelemetry/trace/noop.h +++ b/api/include/opentelemetry/trace/noop.h @@ -1,5 +1,12 @@ #pragma once +// Please refer to provider.h for documentation on how to obtain a Tracer object. +// +// This file is part of the internal implementation of OpenTelemetry. Nothing in this file should be +// used directly. Please refer to span.h and tracer.h for documentation on these interfaces. +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/unique_ptr.h" +#include "opentelemetry/trace/span.h" #include "opentelemetry/trace/tracer.h" #include @@ -9,14 +16,24 @@ namespace opentelemetry namespace trace { /** - * Noop implementation of Span. + * No-op implementation of Span. This class should not be used directly. */ class NoopSpan final : public Span { public: explicit NoopSpan(const std::shared_ptr &tracer) noexcept : tracer_{tracer} {} - // Span + void AddEvent(nostd::string_view name) override {} + + void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) override {} + void AddEvent(nostd::string_view name, core::SteadyTimestamp timestamp) override {} + + void UpdateName(nostd::string_view name) override {} + + void End() override {} + + bool IsRecording() const override { return false; } + Tracer &tracer() const noexcept override { return *tracer_; } private: @@ -24,7 +41,7 @@ class NoopSpan final : public Span }; /** - * Noop implementation of Tracer + * No-op implementation of Tracer. This class should not be used directly. */ class NoopTracer final : public Tracer, public std::enable_shared_from_this { diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index a08d9017ad..bd7405a225 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -1,38 +1,112 @@ #pragma once +#include + #include "opentelemetry/core/timestamp.h" +#include "opentelemetry/nostd/string_view.h" namespace opentelemetry { namespace trace { +enum class SpanKind +{ + kInternal, + kServer, + kClient, + kProducer, + kConsumer, +}; /** - * StartSpanOptions provides options to set properties of span at the time of starting a new span. + * StartSpanOptions provides options to set properties of a Span at the time of its creation */ struct StartSpanOptions { - // Sets the start time of a span. + // Optionally sets the start time of a Span. // - // If the start time of a span is set, timestamps from both the system clock and steady clock - // should be provided. + // If the start time of a Span is set, timestamps from both the system clock and steady clock + // must be provided. // - // Timestamps from the steady clock can be used to most accurately measure a span's - // duration, while timestamps from the system clock can be used to most accurately place a span's - // time point relative to other spans collected across a distributed system. + // Timestamps from the steady clock can be used to most accurately measure a Span's + // duration, while timestamps from the system clock can be used to most accurately place a Span's + // time point relative to other Spans collected across a distributed system. core::SystemTimestamp start_system_time; core::SteadyTimestamp start_steady_time; + + // TODO: + // Span(Context?) parent; + // SpanContext remote_parent; + // Links + // Attributes + SpanKind kind = SpanKind::kInternal; }; class Tracer; /** - * A span represents a single operation within a trace. + * A Span represents a single operation within a Trace. + * + * Spans *must* be ended by calling End(). Merely deleting a Span does not end + * it. */ class Span { public: + // Note that Spans should be created using the Tracer class. Please refer to + // tracer.h for documentation. + Span() = default; virtual ~Span() = default; + // Not copiable or movable. + Span(const Span &) = delete; + Span(Span &&) = delete; + Span &operator=(const Span &) = delete; + Span &operator=(Span &&) = delete; + + // TODO + // Sets an attribute on the Span. If the Span previously contained a mapping for + // the key, the old value is replaced. + // + // If an empty string is used as the value, the attribute will be silently + // dropped. Note: this behavior could change in the future. + // virtual void SetAttribute(nostd::string_view key, AttributeValue&& value) = 0; + + // Adds an event to the Span. + virtual void AddEvent(nostd::string_view name) = 0; + + // Adds an event to the Span, with a custom timestamp. + virtual void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) = 0; + virtual void AddEvent(nostd::string_view name, core::SteadyTimestamp timestamp) = 0; + + // TODO + // Adds an event to the Span, with a custom timestamp, and attributes. + // virtual void AddEvent(nostd::string_view name, core::SteadyTimestamp + // timestamp, nostd::span> attributes); + + // TODO + // Sets the status of the span. The default status is OK. Only the value of the last call will be + // recorded, and implementations are free to ignore previous calls. + // virtual void SetStatus(Status status) = 0; + + // Updates the name of the Span. If used, this will override the name provided + // during construction. + virtual void UpdateName(nostd::string_view name) = 0; + + // Mark the end of the Span. Only the timing of the first end call for a given {@code Span} will + // be recorded, and implementations are free to ignore all further calls. + virtual void End() = 0; + + // TODO + // virtual void End(EndSpanOptions&& opts) = 0; + + // TODO + // SpanContext GetContext() const = 0; + + // Returns true if this Span is recording tracing events (e.g. SetAttribute, + // AddEvent). + virtual bool IsRecording() const = 0; + virtual Tracer &tracer() const noexcept = 0; }; } // namespace trace From 814306914e202e16f0a947bca3e129788a4436a7 Mon Sep 17 00:00:00 2001 From: easy Date: Tue, 11 Feb 2020 14:24:44 -0800 Subject: [PATCH 2/6] Add enum CanonicalCode. --- .../opentelemetry/trace/canonical_code.h | 137 ++++++++++++++++++ api/include/opentelemetry/trace/noop.h | 2 + api/include/opentelemetry/trace/span.h | 4 +- 3 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 api/include/opentelemetry/trace/canonical_code.h diff --git a/api/include/opentelemetry/trace/canonical_code.h b/api/include/opentelemetry/trace/canonical_code.h new file mode 100644 index 0000000000..7e9c0f907c --- /dev/null +++ b/api/include/opentelemetry/trace/canonical_code.h @@ -0,0 +1,137 @@ +#pragma once + +#include + +namespace opentelemetry +{ +namespace trace +{ +enum class CanonicalCode : uint8_t +{ + /** + * The operation completed successfully. + */ + OK = 0, + + /** + * The operation was cancelled (typically by the caller). + */ + CANCELLED = 1, + + /** + * Unknown error. An example of where this error may be returned is if a Status value received + * from another address space belongs to an error-space that is not known in this address space. + * Also errors raised by APIs that do not return enough error information may be converted to + * this error. + */ + UNKNOWN = 2, + + /** + * Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. + * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the + * system (e.g., a malformed file name). + */ + INVALID_ARGUMENT = 3, + + /** + * Deadline expired before operation could complete. For operations that change the state of the + * system, this error may be returned even if the operation has completed successfully. For + * example, a successful response from a server could have been delayed long enough for the + * deadline to expire. + */ + DEADLINE_EXCEEDED = 4, + + /** + * Some requested entity (e.g., file or directory) was not found. + */ + NOT_FOUND = 5, + + /** + * Some entity that we attempted to create (e.g., file or directory) already exists. + */ + ALREADY_EXISTS = 6, + + /** + * The caller does not have permission to execute the specified operation. PERMISSION_DENIED + * must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED + * instead for those errors). PERMISSION_DENIED must not be used if the caller cannot be + * identified (use UNAUTHENTICATED instead for those errors). + */ + PERMISSION_DENIED = 7, + + /** + * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system + * is out of space. + */ + RESOURCE_EXHAUSTED = 8, + + /** + * Operation was rejected because the system is not in a state required for the operation's + * execution. For example, directory to be deleted may be non-empty, an rmdir operation is + * applied to a non-directory, etc. + * + * A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION, + * ABORTED, and UNAVAILABLE: (a) Use UNAVAILABLE if the client can retry just the failing call. + * (b) Use ABORTED if the client should retry at a higher-level (e.g., restarting a + * read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client should not retry until + * the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory + * is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless + * they have first fixed up the directory by deleting files from it. + */ + FAILED_PRECONDITION = 9, + + /** + * The operation was aborted, typically due to a concurrency issue like sequencer check + * failures, transaction aborts, etc. + * + * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + */ + ABORTED = 10, + + /** + * Operation was attempted past the valid range. E.g., seeking or reading past end of file. + * + * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system + * state changes. For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to + * read at an offset that is not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if + * asked to read from an offset past the current file size. + * + * There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend + * using OUT_OF_RANGE (the more specific error) when it applies so that callers who are + * iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are + * done. + */ + OUT_OF_RANGE = 11, + + /** + * Operation is not implemented or not supported/enabled in this service. + */ + UNIMPLEMENTED = 12, + + /** + * Internal errors. Means some invariants expected by underlying system has been broken. If you + * see one of these errors, something is very broken. + */ + INTERNAL = 13, + + /** + * The service is currently unavailable. This is a most likely a transient condition and may be + * corrected by retrying with a backoff. + * + * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + */ + UNAVAILABLE = 14, + + /** + * Unrecoverable data loss or corruption. + */ + DATA_LOSS = 15, + + /** + * The request does not have valid authentication credentials for the operation. + */ + UNAUTHENTICATED = 16, +}; + +} // namespace trace +} // namespace opentelemetry diff --git a/api/include/opentelemetry/trace/noop.h b/api/include/opentelemetry/trace/noop.h index 7d31c422df..7b4b03a9c8 100644 --- a/api/include/opentelemetry/trace/noop.h +++ b/api/include/opentelemetry/trace/noop.h @@ -28,6 +28,8 @@ class NoopSpan final : public Span void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) override {} void AddEvent(nostd::string_view name, core::SteadyTimestamp timestamp) override {} + void SetStatus(CanonicalCode code, nostd::string_view description) override {} + void UpdateName(nostd::string_view name) override {} void End() override {} diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index bd7405a225..171607f1a1 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -4,6 +4,7 @@ #include "opentelemetry/core/timestamp.h" #include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/trace/canonical_code.h" namespace opentelemetry { @@ -84,10 +85,9 @@ class Span // timestamp, nostd::span> attributes); - // TODO // Sets the status of the span. The default status is OK. Only the value of the last call will be // recorded, and implementations are free to ignore previous calls. - // virtual void SetStatus(Status status) = 0; + virtual void SetStatus(CanonicalCode code, nostd::string_view description) = 0; // Updates the name of the Span. If used, this will override the name provided // during construction. From 9d2b3bf70d7fcdea92677fe6d98bef3fbbbba0e3 Mon Sep 17 00:00:00 2001 From: easy Date: Tue, 11 Feb 2020 14:43:49 -0800 Subject: [PATCH 3/6] Changes from code review. --- api/include/opentelemetry/trace/noop.h | 16 ++++++++-------- api/include/opentelemetry/trace/span.h | 24 ++++++++++++------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/api/include/opentelemetry/trace/noop.h b/api/include/opentelemetry/trace/noop.h index 7b4b03a9c8..60deddbf93 100644 --- a/api/include/opentelemetry/trace/noop.h +++ b/api/include/opentelemetry/trace/noop.h @@ -23,18 +23,18 @@ class NoopSpan final : public Span public: explicit NoopSpan(const std::shared_ptr &tracer) noexcept : tracer_{tracer} {} - void AddEvent(nostd::string_view name) override {} + void AddEvent(nostd::string_view name) noexcept override {} - void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) override {} - void AddEvent(nostd::string_view name, core::SteadyTimestamp timestamp) override {} + void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) noexcept override {} + void AddEvent(nostd::string_view name, core::SteadyTimestamp timestamp) noexcept override {} - void SetStatus(CanonicalCode code, nostd::string_view description) override {} + void SetStatus(CanonicalCode code, nostd::string_view description) noexcept override {} - void UpdateName(nostd::string_view name) override {} + void UpdateName(nostd::string_view name) noexcept override {} - void End() override {} + void End() noexcept override {} - bool IsRecording() const override { return false; } + bool IsRecording() const noexcept override { return false; } Tracer &tracer() const noexcept override { return *tracer_; } @@ -43,7 +43,7 @@ class NoopSpan final : public Span }; /** - * No-op implementation of Tracer. This class should not be used directly. + * No-op implementation of Tracer. */ class NoopTracer final : public Tracer, public std::enable_shared_from_this { diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index 171607f1a1..dffefbeceb 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -73,39 +73,39 @@ class Span // virtual void SetAttribute(nostd::string_view key, AttributeValue&& value) = 0; // Adds an event to the Span. - virtual void AddEvent(nostd::string_view name) = 0; + virtual void AddEvent(nostd::string_view name) noexcept = 0; // Adds an event to the Span, with a custom timestamp. - virtual void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) = 0; - virtual void AddEvent(nostd::string_view name, core::SteadyTimestamp timestamp) = 0; + virtual void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) noexcept = 0; + virtual void AddEvent(nostd::string_view name, core::SteadyTimestamp timestamp) noexcept = 0; // TODO // Adds an event to the Span, with a custom timestamp, and attributes. // virtual void AddEvent(nostd::string_view name, core::SteadyTimestamp - // timestamp, nostd::span> attributes); + // timestamp, nostd::span> attributes) noexcept = 0; // Sets the status of the span. The default status is OK. Only the value of the last call will be // recorded, and implementations are free to ignore previous calls. - virtual void SetStatus(CanonicalCode code, nostd::string_view description) = 0; + virtual void SetStatus(CanonicalCode code, nostd::string_view description) noexcept = 0; // Updates the name of the Span. If used, this will override the name provided - // during construction. - virtual void UpdateName(nostd::string_view name) = 0; + // during creation. + virtual void UpdateName(nostd::string_view name) noexcept = 0; // Mark the end of the Span. Only the timing of the first end call for a given {@code Span} will // be recorded, and implementations are free to ignore all further calls. - virtual void End() = 0; + virtual void End() noexcept = 0; // TODO - // virtual void End(EndSpanOptions&& opts) = 0; + // virtual void End(EndSpanOptions&& opts) noexcept = 0; // TODO - // SpanContext GetContext() const = 0; + // SpanContext GetContext() const noexcept = 0; // Returns true if this Span is recording tracing events (e.g. SetAttribute, // AddEvent). - virtual bool IsRecording() const = 0; + virtual bool IsRecording() const noexcept = 0; virtual Tracer &tracer() const noexcept = 0; }; From b19e55e9eeeeba2edd25fe7af682cfdb4d256338 Mon Sep 17 00:00:00 2001 From: easy Date: Wed, 19 Feb 2020 18:15:21 +1100 Subject: [PATCH 4/6] Follow style guide for accessor. --- api/include/opentelemetry/trace/span.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index dffefbeceb..144182eedb 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -101,7 +101,7 @@ class Span // virtual void End(EndSpanOptions&& opts) noexcept = 0; // TODO - // SpanContext GetContext() const noexcept = 0; + // SpanContext context() const noexcept = 0; // Returns true if this Span is recording tracing events (e.g. SetAttribute, // AddEvent). From 8f5552bbbadcefe86a46d52a32dad268eb74c927 Mon Sep 17 00:00:00 2001 From: easy Date: Thu, 20 Feb 2020 15:19:45 +1100 Subject: [PATCH 5/6] constify --- api/include/opentelemetry/trace/span.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index 144182eedb..3dfaaba3d1 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -82,7 +82,7 @@ class Span // TODO // Adds an event to the Span, with a custom timestamp, and attributes. // virtual void AddEvent(nostd::string_view name, core::SteadyTimestamp - // timestamp, nostd::span> attributes) noexcept = 0; // Sets the status of the span. The default status is OK. Only the value of the last call will be From df102b479e859abde4fae4cbf8571fbcc0e690df Mon Sep 17 00:00:00 2001 From: easy Date: Tue, 25 Feb 2020 11:19:08 +1100 Subject: [PATCH 6/6] Update docs: spans don't have to be explicitly ended. --- api/include/opentelemetry/trace/span.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index 3dfaaba3d1..300ec0478d 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -46,16 +46,15 @@ class Tracer; /** * A Span represents a single operation within a Trace. - * - * Spans *must* be ended by calling End(). Merely deleting a Span does not end - * it. */ class Span { public: // Note that Spans should be created using the Tracer class. Please refer to // tracer.h for documentation. - Span() = default; + Span() = default; + + // The Span destructor End()s the Span, if it hasn't been ended already. virtual ~Span() = default; // Not copiable or movable. @@ -93,7 +92,7 @@ class Span // during creation. virtual void UpdateName(nostd::string_view name) noexcept = 0; - // Mark the end of the Span. Only the timing of the first end call for a given {@code Span} will + // Mark the end of the Span. Only the timing of the first End call for a given Span will // be recorded, and implementations are free to ignore all further calls. virtual void End() noexcept = 0;