Updated OpenTelemetry tests to use their own SpanExporter rather than depend on the InMemorySpanExporter. (#4042)
* Removed version override for opentelemetry * Disable deprecation warnings for open telemety tests to guard against future deprecations * Added explanation for 4996 error; removed InMemoryExporter from documentation * Checkpoint adding manual telemetry exporter * Switch from using OpenTelemetry's InMemoryExporter (which is an internal-to-opentelemetry test hook) to our own SpanExporter * removed unused variables because gcc doesn't like them * Fixed doxygen comments * Removed a bunch of unnecessary headers * Update sdk/core/azure-core-tracing-opentelemetry/test/ut/test_exporter.hpp Co-authored-by: Rick Winter <rick.winter@microsoft.com> Co-authored-by: Rick Winter <rick.winter@microsoft.com>
This commit is contained in:
parent
6c225cd6c9
commit
66fd7dabb9
@ -1,36 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#define USE_MEMORY_EXPORTER 1
|
||||
#include "azure/core/internal/tracing/service_tracing.hpp"
|
||||
#include "azure/core/tracing/opentelemetry/opentelemetry.hpp"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <regex>
|
||||
|
||||
#include <azure/core/internal/http/pipeline.hpp>
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/core/internal/tracing/service_tracing.hpp>
|
||||
#include <azure/core/test/test_base.hpp>
|
||||
#include <azure/core/tracing/opentelemetry/opentelemetry.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// The OpenTelemetry headers generate a couple of warnings on MSVC in the OTel 1.2 package, suppress
|
||||
// the warnings across the includes.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4100)
|
||||
#pragma warning(disable : 4244)
|
||||
#pragma warning(disable : 6323) // Disable "Use of arithmetic operator on Boolean type" warning.
|
||||
#endif
|
||||
#include <opentelemetry/exporters/memory/in_memory_span_data.h>
|
||||
#include <opentelemetry/exporters/memory/in_memory_span_exporter.h>
|
||||
#include <opentelemetry/exporters/ostream/span_exporter.h>
|
||||
#include "test_exporter.hpp" // Span Exporter used for OpenTelemetry tests.
|
||||
#include <opentelemetry/sdk/common/global_log_handler.h>
|
||||
#include <opentelemetry/sdk/trace/exporter.h>
|
||||
#include <opentelemetry/sdk/trace/processor.h>
|
||||
#include <opentelemetry/sdk/trace/simple_processor.h>
|
||||
#include <opentelemetry/sdk/trace/tracer_provider.h>
|
||||
#include <opentelemetry/trace/propagation/http_trace_context.h>
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#include <chrono>
|
||||
#include <gtest/gtest.h>
|
||||
#include <regex>
|
||||
|
||||
using namespace Azure::Core::Http::Policies;
|
||||
using namespace Azure::Core::Http::Policies::_internal;
|
||||
@ -95,18 +81,13 @@ class CustomLogHandler : public opentelemetry::sdk::common::internal_log::LogHan
|
||||
class OpenTelemetryServiceTests : public Azure::Core::Test::TestBase {
|
||||
private:
|
||||
protected:
|
||||
std::shared_ptr<opentelemetry::exporter::memory::InMemorySpanData> m_spanData;
|
||||
std::shared_ptr<TestExporter::TestData> m_spanData;
|
||||
|
||||
opentelemetry::nostd::shared_ptr<opentelemetry::trace::TracerProvider>
|
||||
CreateOpenTelemetryProvider()
|
||||
{
|
||||
#if USE_MEMORY_EXPORTER
|
||||
auto exporter = std::make_unique<opentelemetry::exporter::memory::InMemorySpanExporter>();
|
||||
m_spanData = exporter->GetData();
|
||||
#else
|
||||
// logging exporter
|
||||
auto exporter = std::make_unique<opentelemetry::exporter::trace::OStreamSpanExporter>();
|
||||
#endif
|
||||
auto exporter = std::make_unique<TestExporter>();
|
||||
m_spanData = exporter->GetTestData();
|
||||
|
||||
// simple processor
|
||||
auto simple_processor = std::unique_ptr<opentelemetry::sdk::trace::SpanProcessor>(
|
||||
@ -143,7 +124,7 @@ protected:
|
||||
}
|
||||
|
||||
bool VerifySpan(
|
||||
std::unique_ptr<opentelemetry::sdk::trace::SpanData> const& span,
|
||||
std::unique_ptr<RecordedSpan> const& span,
|
||||
std::string const& expectedSpanContentsJson)
|
||||
{
|
||||
Azure::Core::Json::_internal::json expectedSpanContents(
|
||||
@ -199,7 +180,7 @@ protected:
|
||||
|
||||
EXPECT_EQ(expectedAttributes.size(), attributes.size());
|
||||
|
||||
for (const auto& foundAttribute : attributes)
|
||||
for (auto const& foundAttribute : attributes)
|
||||
{
|
||||
EXPECT_TRUE(expectedAttributes.contains(foundAttribute.first));
|
||||
switch (foundAttribute.second.index())
|
||||
@ -219,7 +200,7 @@ protected:
|
||||
std::regex expectedRegex(expectedVal);
|
||||
GTEST_LOG_(INFO) << "expected Regex: " << expectedVal << std::endl;
|
||||
GTEST_LOG_(INFO) << "actual val: " << actualVal << std::endl;
|
||||
EXPECT_TRUE(std::regex_match(actualVal, expectedRegex));
|
||||
EXPECT_TRUE(std::regex_match(std::string(actualVal), expectedRegex));
|
||||
break;
|
||||
}
|
||||
case opentelemetry::common::kTypeDouble: {
|
||||
@ -327,7 +308,7 @@ TEST_F(OpenTelemetryServiceTests, CreateWithExplicitProvider)
|
||||
EXPECT_FALSE(contextAndSpan.Context.IsCancelled());
|
||||
}
|
||||
// Now let's verify what was logged via OpenTelemetry.
|
||||
auto spans = m_spanData->GetSpans();
|
||||
auto const& spans = m_spanData->ExtractSpans();
|
||||
EXPECT_EQ(1ul, spans.size());
|
||||
|
||||
VerifySpan(spans[0], R"(
|
||||
@ -367,7 +348,7 @@ TEST_F(OpenTelemetryServiceTests, CreateWithImplicitProvider)
|
||||
}
|
||||
|
||||
// Now let's verify what was logged via OpenTelemetry.
|
||||
auto spans = m_spanData->GetSpans();
|
||||
auto const& spans = m_spanData->ExtractSpans();
|
||||
EXPECT_EQ(1ul, spans.size());
|
||||
|
||||
VerifySpan(spans[0], R"(
|
||||
@ -415,7 +396,7 @@ TEST_F(OpenTelemetryServiceTests, CreateSpanWithOptions)
|
||||
}
|
||||
|
||||
// Now let's verify what was logged via OpenTelemetry.
|
||||
auto spans = m_spanData->GetSpans();
|
||||
auto const& spans = m_spanData->ExtractSpans();
|
||||
EXPECT_EQ(1ul, spans.size());
|
||||
|
||||
VerifySpan(spans[0], R"(
|
||||
@ -476,7 +457,7 @@ TEST_F(OpenTelemetryServiceTests, NestSpans)
|
||||
}
|
||||
}
|
||||
// Now let's verify what was logged via OpenTelemetry.
|
||||
auto spans = m_spanData->GetSpans();
|
||||
auto const& spans = m_spanData->ExtractSpans();
|
||||
EXPECT_EQ(2ul, spans.size());
|
||||
|
||||
// Because Nested API goes out of scope before My API, it will be logged first in the
|
||||
@ -676,7 +657,7 @@ TEST_F(OpenTelemetryServiceTests, ServiceApiImplementation)
|
||||
myServiceClient.GetConfigurationString("Fred");
|
||||
}
|
||||
// Now let's verify what was logged via OpenTelemetry.
|
||||
auto spans = m_spanData->GetSpans();
|
||||
auto const& spans = m_spanData->ExtractSpans();
|
||||
EXPECT_EQ(2ul, spans.size());
|
||||
|
||||
VerifySpan(spans[0], R"(
|
||||
@ -722,7 +703,7 @@ TEST_F(OpenTelemetryServiceTests, ServiceApiImplementation)
|
||||
myServiceClient.GetConfigurationString("George");
|
||||
}
|
||||
// Now let's verify what was logged via OpenTelemetry.
|
||||
auto spans = m_spanData->GetSpans();
|
||||
auto const& spans = m_spanData->ExtractSpans();
|
||||
EXPECT_EQ(0ul, spans.size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,224 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <opentelemetry/sdk/trace/exporter.h>
|
||||
|
||||
class RecordedSpan : public opentelemetry::sdk::trace::Recordable {
|
||||
struct Event
|
||||
{
|
||||
std::string Name;
|
||||
std::chrono::system_clock::time_point Timestamp;
|
||||
opentelemetry::sdk::common::AttributeMap Attributes;
|
||||
};
|
||||
opentelemetry::trace::SpanId m_parentSpan;
|
||||
opentelemetry::trace::SpanId m_spanId;
|
||||
opentelemetry::sdk::common::AttributeMap m_attributes;
|
||||
std::vector<Event> m_events;
|
||||
opentelemetry::trace::StatusCode m_statusCode{};
|
||||
std::string m_statusDescription;
|
||||
std::string m_name;
|
||||
opentelemetry::trace::SpanKind m_spanKind{};
|
||||
std::chrono::system_clock::time_point m_startTime;
|
||||
std::chrono::nanoseconds m_duration{};
|
||||
std::unique_ptr<opentelemetry::sdk::instrumentationscope::InstrumentationScope> m_scope;
|
||||
std::unique_ptr<opentelemetry::sdk::resource::Resource> m_resource;
|
||||
|
||||
public:
|
||||
~RecordedSpan() = default;
|
||||
|
||||
/**
|
||||
* Set the span context and parent span id
|
||||
* @param span_context the span context to set
|
||||
* @param parent_span_id the parent span id to set
|
||||
*/
|
||||
void SetIdentity(
|
||||
const opentelemetry::trace::SpanContext& span_context,
|
||||
opentelemetry::trace::SpanId parent_span_id) noexcept override
|
||||
{
|
||||
m_parentSpan = parent_span_id;
|
||||
m_spanId = span_context.span_id();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set an attribute of a span.
|
||||
* @param key the name of the attribute
|
||||
* @param value the attribute value
|
||||
*/
|
||||
void SetAttribute(
|
||||
opentelemetry::nostd::string_view key,
|
||||
const opentelemetry::common::AttributeValue& value) noexcept override
|
||||
{
|
||||
m_attributes.SetAttribute(key, value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add an event to a span.
|
||||
* @param name the name of the event
|
||||
* @param timestamp the timestamp of the event
|
||||
* @param attributes the attributes associated with the event
|
||||
*/
|
||||
void AddEvent(
|
||||
opentelemetry::nostd::string_view name,
|
||||
opentelemetry::common::SystemTimestamp timestamp,
|
||||
const opentelemetry::common::KeyValueIterable& attributes) noexcept override
|
||||
{
|
||||
Event event;
|
||||
event.Name = std::string(name);
|
||||
event.Timestamp = timestamp;
|
||||
|
||||
attributes.ForEachKeyValue(
|
||||
[&event](
|
||||
opentelemetry::nostd::string_view name, opentelemetry::common::AttributeValue value) {
|
||||
event.Attributes.SetAttribute(name, value);
|
||||
return true;
|
||||
});
|
||||
m_events.push_back(event);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a link to a span.
|
||||
*/
|
||||
void AddLink(
|
||||
const opentelemetry::trace::SpanContext&,
|
||||
const opentelemetry::common::KeyValueIterable&) noexcept override{
|
||||
// TODO, when we use this, we need to test this.
|
||||
// NO-OP since this exporter silences link data.
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the status of the span.
|
||||
* @param code the status code
|
||||
* @param description a description of the status
|
||||
*/
|
||||
void SetStatus(
|
||||
opentelemetry::trace::StatusCode code,
|
||||
opentelemetry::nostd::string_view description) noexcept override
|
||||
{
|
||||
m_statusCode = code;
|
||||
m_statusDescription = std::string(description);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the name of the span.
|
||||
* @param name the name to set
|
||||
*/
|
||||
void SetName(opentelemetry::nostd::string_view name) noexcept override
|
||||
{
|
||||
m_name = std::string(name);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the spankind of the span.
|
||||
* @param span_kind the spankind to set
|
||||
*/
|
||||
void SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept override
|
||||
{
|
||||
m_spanKind = span_kind;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set Resource of the span
|
||||
* @param resource the resource to set
|
||||
*/
|
||||
void SetResource(const opentelemetry::sdk::resource::Resource& resource) noexcept override
|
||||
{
|
||||
m_resource = std::make_unique<opentelemetry::sdk::resource::Resource>(resource);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the start time of the span.
|
||||
* @param start_time the start time to set
|
||||
*/
|
||||
void SetStartTime(opentelemetry::common::SystemTimestamp start_time) noexcept override
|
||||
{
|
||||
m_startTime = start_time;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the duration of the span.
|
||||
* @param duration the duration to set
|
||||
*/
|
||||
void SetDuration(std::chrono::nanoseconds duration) noexcept override { m_duration = duration; }
|
||||
|
||||
/**
|
||||
* Set the instrumentation scope of the span.
|
||||
* @param instrumentation_scope the instrumentation scope to set
|
||||
*/
|
||||
void SetInstrumentationScope(const opentelemetry::sdk::instrumentationscope::InstrumentationScope&
|
||||
instrumentation_scope) noexcept override
|
||||
{
|
||||
m_scope = std::make_unique<opentelemetry::sdk::instrumentationscope::InstrumentationScope>(
|
||||
instrumentation_scope);
|
||||
};
|
||||
|
||||
std::string GetName() { return m_name; }
|
||||
opentelemetry::trace::StatusCode GetStatus() { return m_statusCode; }
|
||||
opentelemetry::trace::SpanId GetParentSpanId() { return m_parentSpan; }
|
||||
opentelemetry::trace::SpanKind GetSpanKind() { return m_spanKind; }
|
||||
opentelemetry::trace::SpanId GetSpanId() { return m_spanId; }
|
||||
opentelemetry::sdk::common::AttributeMap const& GetAttributes() { return m_attributes; }
|
||||
opentelemetry::sdk::instrumentationscope::InstrumentationScope& GetInstrumentationScope()
|
||||
{
|
||||
return *m_scope;
|
||||
}
|
||||
};
|
||||
|
||||
class TestExporter final : public opentelemetry::sdk::trace::SpanExporter {
|
||||
|
||||
public:
|
||||
class TestData {
|
||||
std::vector<std::unique_ptr<RecordedSpan>> m_spans;
|
||||
|
||||
public:
|
||||
// Returns a copy of the recorded spans and clears the set of recorded spans.
|
||||
std::vector<std::unique_ptr<RecordedSpan>> const ExtractSpans() { return std::move(m_spans); }
|
||||
void AddSpan(std::unique_ptr<RecordedSpan>&& span) { m_spans.push_back(std::move(span)); }
|
||||
};
|
||||
std::shared_ptr<TestData> const& GetTestData() { return m_testData; }
|
||||
|
||||
TestExporter() : m_testData{std::make_shared<TestData>()} {}
|
||||
virtual ~TestExporter() = default;
|
||||
|
||||
/**
|
||||
* Create a span recordable. This object will be used to record span data and
|
||||
* will subsequently be passed to SpanExporter::Export. Vendors can implement
|
||||
* custom recordables or use the default SpanData recordable provided by the
|
||||
* SDK.
|
||||
* @return a newly initialized Recordable object
|
||||
*
|
||||
* Note: This method must be callable from multiple threads.
|
||||
*/
|
||||
std::unique_ptr<opentelemetry::sdk::trace::Recordable> MakeRecordable() noexcept override
|
||||
{
|
||||
return std::unique_ptr<opentelemetry::sdk::trace::Recordable>(new (std::nothrow) RecordedSpan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports a batch of span recordables. This method must not be called
|
||||
* concurrently for the same exporter instance.
|
||||
* @param spans a span of unique pointers to span recordables
|
||||
*/
|
||||
opentelemetry::sdk::common::ExportResult Export(
|
||||
const opentelemetry::nostd::span<std::unique_ptr<opentelemetry::sdk::trace::Recordable>>&
|
||||
spans) noexcept override
|
||||
{
|
||||
for (auto& recordable : spans)
|
||||
{
|
||||
auto span = std::unique_ptr<RecordedSpan>(static_cast<RecordedSpan*>(recordable.release()));
|
||||
m_testData->AddSpan(std::move(span));
|
||||
}
|
||||
return opentelemetry::sdk::common::ExportResult::kSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shut down the exporter.
|
||||
* @return return the status of the operation.
|
||||
*/
|
||||
bool Shutdown(std::chrono::microseconds) noexcept override { return true; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<TestData> m_testData;
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user