From 3cc2c69dc8f38ee9eab8704bd4f093c18a327f72 Mon Sep 17 00:00:00 2001 From: easy Date: Tue, 25 Feb 2020 11:25:55 +1100 Subject: [PATCH] Add Span API. (#35) --- .../opentelemetry/trace/canonical_code.h | 137 ++++++++++++++++++ api/include/opentelemetry/trace/noop.h | 25 +++- api/include/opentelemetry/trace/span.h | 89 +++++++++++- 3 files changed, 240 insertions(+), 11 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 00000000000..7e9c0f907cf --- /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 00e43774d3f..60deddbf93d 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,26 @@ 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) noexcept 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) noexcept override {} + + void UpdateName(nostd::string_view name) noexcept override {} + + void End() noexcept override {} + + bool IsRecording() const noexcept override { return false; } + Tracer &tracer() const noexcept override { return *tracer_; } private: @@ -24,7 +43,7 @@ class NoopSpan final : public Span }; /** - * Noop implementation of Tracer + * 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 a08d9017ad1..300ec0478d9 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -1,38 +1,111 @@ #pragma once +#include + #include "opentelemetry/core/timestamp.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/trace/canonical_code.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. */ class Span { public: + // Note that Spans should be created using the Tracer class. Please refer to + // tracer.h for documentation. + Span() = default; + + // The Span destructor End()s the Span, if it hasn't been ended already. 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) noexcept = 0; + + // Adds an event to the Span, with a custom timestamp. + 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) 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) noexcept = 0; + + // Updates the name of the Span. If used, this will override the name provided + // 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 Span will + // be recorded, and implementations are free to ignore all further calls. + virtual void End() noexcept = 0; + + // TODO + // virtual void End(EndSpanOptions&& opts) noexcept = 0; + + // TODO + // SpanContext context() const noexcept = 0; + + // Returns true if this Span is recording tracing events (e.g. SetAttribute, + // AddEvent). + virtual bool IsRecording() const noexcept = 0; + virtual Tracer &tracer() const noexcept = 0; }; } // namespace trace