// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 #include #include #include "opentelemetry/nostd/function_ref.h" #include "opentelemetry/sdk/trace/processor.h" #include "opentelemetry/sdk/trace/recordable.h" #include "opentelemetry/trace/span_id.h" #include "opentelemetry/trace/span_metadata.h" #include "opentelemetry/trace/trace_flags.h" #include "opentelemetry/version.h" #include "src/trace/span.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace sdk { namespace trace { using opentelemetry::common::SteadyTimestamp; using opentelemetry::common::SystemTimestamp; namespace common = opentelemetry::common; namespace { SystemTimestamp NowOr(const SystemTimestamp &system) { if (system == SystemTimestamp()) { return SystemTimestamp(std::chrono::system_clock::now()); } else { return system; } } SteadyTimestamp NowOr(const SteadyTimestamp &steady) { if (steady == SteadyTimestamp()) { return SteadyTimestamp(std::chrono::steady_clock::now()); } else { return steady; } } } // namespace Span::Span(std::shared_ptr &&tracer, nostd::string_view name, const common::KeyValueIterable &attributes, const opentelemetry::trace::SpanContextKeyValueIterable &links, const opentelemetry::trace::StartSpanOptions &options, const opentelemetry::trace::SpanContext &parent_span_context, std::unique_ptr span_context) noexcept : tracer_{std::move(tracer)}, recordable_{tracer_->GetProcessor().MakeRecordable()}, start_steady_time{options.start_steady_time}, span_context_(std::move(span_context)), has_ended_{false} { if (recordable_ == nullptr) { return; } recordable_->SetName(name); recordable_->SetInstrumentationScope(tracer_->GetInstrumentationScope()); recordable_->SetIdentity(*span_context_, parent_span_context.IsValid() ? parent_span_context.span_id() : opentelemetry::trace::SpanId()); recordable_->SetTraceFlags(span_context_->trace_flags()); attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { recordable_->SetAttribute(key, value); return true; }); links.ForEachKeyValue([&](const opentelemetry::trace::SpanContext &span_context, const common::KeyValueIterable &attributes) { recordable_->AddLink(span_context, attributes); return true; }); recordable_->SetSpanKind(options.kind); recordable_->SetStartTime(NowOr(options.start_system_time)); start_steady_time = NowOr(options.start_steady_time); recordable_->SetResource(tracer_->GetResource()); tracer_->GetProcessor().OnStart(*recordable_, parent_span_context); } Span::~Span() { End(); } void Span::SetAttribute(nostd::string_view key, const common::AttributeValue &value) noexcept { std::lock_guard lock_guard{mu_}; if (recordable_ == nullptr) { return; } recordable_->SetAttribute(key, value); } void Span::AddEvent(nostd::string_view name) noexcept { std::lock_guard lock_guard{mu_}; if (recordable_ == nullptr) { return; } recordable_->AddEvent(name); } void Span::AddEvent(nostd::string_view name, SystemTimestamp timestamp) noexcept { std::lock_guard lock_guard{mu_}; if (recordable_ == nullptr) { return; } recordable_->AddEvent(name, timestamp); } void Span::AddEvent(nostd::string_view name, const common::KeyValueIterable &attributes) noexcept { std::lock_guard lock_guard{mu_}; if (recordable_ == nullptr) { return; } recordable_->AddEvent(name, attributes); } void Span::AddEvent(nostd::string_view name, SystemTimestamp timestamp, const common::KeyValueIterable &attributes) noexcept { std::lock_guard lock_guard{mu_}; if (recordable_ == nullptr) { return; } recordable_->AddEvent(name, timestamp, attributes); } #if OPENTELEMETRY_ABI_VERSION_NO >= 2 void Span::AddLink(const opentelemetry::trace::SpanContext &target, const opentelemetry::common::KeyValueIterable &attrs) noexcept { std::lock_guard lock_guard{mu_}; if (recordable_ == nullptr) { return; } recordable_->AddLink(target, attrs); } void Span::AddLinks(const opentelemetry::trace::SpanContextKeyValueIterable &links) noexcept { std::lock_guard lock_guard{mu_}; if (recordable_ == nullptr) { return; } links.ForEachKeyValue([&](const opentelemetry::trace::SpanContext &span_context, const common::KeyValueIterable &attributes) { recordable_->AddLink(span_context, attributes); return true; }); } #endif void Span::SetStatus(opentelemetry::trace::StatusCode code, nostd::string_view description) noexcept { std::lock_guard lock_guard{mu_}; if (recordable_ == nullptr) { return; } recordable_->SetStatus(code, description); } void Span::UpdateName(nostd::string_view name) noexcept { std::lock_guard lock_guard{mu_}; if (recordable_ == nullptr) { return; } recordable_->SetName(name); } void Span::End(const opentelemetry::trace::EndSpanOptions &options) noexcept { std::lock_guard lock_guard{mu_}; if (has_ended_ == true) { return; } has_ended_ = true; if (recordable_ == nullptr) { return; } auto end_steady_time = NowOr(options.end_steady_time); recordable_->SetDuration(std::chrono::steady_clock::time_point(end_steady_time) - std::chrono::steady_clock::time_point(start_steady_time)); tracer_->GetProcessor().OnEnd(std::move(recordable_)); recordable_.reset(); } bool Span::IsRecording() const noexcept { std::lock_guard lock_guard{mu_}; return recordable_ != nullptr; } } // namespace trace } // namespace sdk OPENTELEMETRY_END_NAMESPACE