diff --git a/system/jlib/jtrace.cpp b/system/jlib/jtrace.cpp index 807612337b0..618139aacb8 100644 --- a/system/jlib/jtrace.cpp +++ b/system/jlib/jtrace.cpp @@ -171,6 +171,7 @@ class CTraceManager : implements ITraceManager, public CInterface CTraceManager(); IMPLEMENT_IINTERFACE + virtual ISpan * createServerSpan(const char * name, const IProperties * httpHeaders, SpanFlags flags, std::chrono::nanoseconds spanStartTime) const override; virtual ISpan * createServerSpan(const char * name, StringArray & httpHeaders, SpanFlags flags) const override; virtual ISpan * createServerSpan(const char * name, const IProperties * httpHeaders, SpanFlags flags) const override; @@ -737,6 +738,16 @@ class CServerSpan : public CSpan } public: + CServerSpan(const char * spanName, const IProperties * httpHeaders, SpanFlags flags, std::chrono::nanoseconds spanStartTime) + : CSpan(spanName) + { + opts.start_system_time = opentelemetry::common::SystemTimestamp(std::chrono::duration_cast(spanStartTime)); + opts.kind = opentelemetry::trace::SpanKind::kServer; + setSpanContext(httpHeaders, flags); + init(flags); + setContextAttributes(); + } + CServerSpan(const char * spanName, const IProperties * httpHeaders, SpanFlags flags) : CSpan(spanName) { @@ -808,6 +819,11 @@ class CServerSpan : public CSpan //--------------------------------------------------------------------------------------------------------------------- +std::chrono::nanoseconds nowTimesStampInNanos() +{ + return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()); +} + IProperties * getClientHeaders(const ISpan * span) { Owned headers = createProperties(true); @@ -1062,6 +1078,10 @@ ISpan * CTraceManager::createServerSpan(const char * name, const IProperties * h return new CServerSpan(name, httpHeaders, flags); } +ISpan * CTraceManager::createServerSpan(const char * name, const IProperties * httpHeaders, SpanFlags flags, std::chrono::nanoseconds spanStartTime) const +{ + return new CServerSpan(name, httpHeaders, flags, spanStartTime); +} //--------------------------------------------------------------------------------------------------------------------- diff --git a/system/jlib/jtrace.hpp b/system/jlib/jtrace.hpp index 7998ffd5c3c..9c3e25d1ba5 100644 --- a/system/jlib/jtrace.hpp +++ b/system/jlib/jtrace.hpp @@ -17,6 +17,7 @@ #ifndef JTRACE_HPP #define JTRACE_HPP +#include /** * @brief This follows open telemetry's span attribute naming conventions @@ -62,6 +63,7 @@ extern jlib_decl IProperties * getSpanContext(const ISpan * span); interface ITraceManager : extends IInterface { + virtual ISpan * createServerSpan(const char * name, const IProperties * httpHeaders, SpanFlags flags, std::chrono::nanoseconds spanStartTime) const = 0; virtual ISpan * createServerSpan(const char * name, StringArray & httpHeaders, SpanFlags flags = SpanFlags::None) const = 0; virtual ISpan * createServerSpan(const char * name, const IProperties * httpHeaders, SpanFlags flags = SpanFlags::None) const = 0; virtual bool isTracingEnabled() const = 0; @@ -70,6 +72,15 @@ interface ITraceManager : extends IInterface extern jlib_decl ISpan * getNullSpan(); extern jlib_decl void initTraceManager(const char * componentName, const IPropertyTree * componentConfig, const IPropertyTree * globalConfig); extern jlib_decl ITraceManager & queryTraceManager(); +extern jlib_decl std::chrono::nanoseconds nowTimesStampInNanos(); + +#ifdef _USE_CPPUNIT +#include "opentelemetry/sdk/common/attribute_utils.h" +#include "opentelemetry/sdk/resource/resource.h" + +extern jlib_decl void testJLogExporterPrintResources(StringBuffer & out, const opentelemetry::sdk::resource::Resource &resources); +extern jlib_decl void testJLogExporterPrintAttributes(StringBuffer & out, const std::unordered_map & map, const char * attsContainerName); +#endif //The following class is responsible for ensuring that the active span is restored in a context when the scope is exited //Use a template class so it can be reused for IContextLogger and IEspContext diff --git a/testing/unittests/jlibtests.cpp b/testing/unittests/jlibtests.cpp index 9918b77c5ef..be7d37375d6 100644 --- a/testing/unittests/jlibtests.cpp +++ b/testing/unittests/jlibtests.cpp @@ -60,6 +60,7 @@ class JlibTraceTest : public CppUnit::TestFixture CPPUNIT_TEST(testNullSpan); CPPUNIT_TEST(testClientSpanGlobalID); CPPUNIT_TEST(testEnsureTraceID); + CPPUNIT_TEST(testDeclaredSpanStartTime); CPPUNIT_TEST_SUITE_END(); const char * simulatedGlobalYaml = R"!!(global: @@ -104,6 +105,18 @@ class JlibTraceTest : public CppUnit::TestFixture protected: + void testDeclaredSpanStartTime() + { + std::chrono::nanoseconds nownanos = nowTimesStampInNanos(); + Owned emptyMockHTTPHeaders = createProperties(); + + Owned serverSpan = queryTraceManager().createServerSpan("declaredSpanStartSpan", emptyMockHTTPHeaders, SpanFlags::None, nownanos); + + Owned retrievedSpanCtxAttributes = createProperties(); + bool getSpanCtxSuccess = serverSpan->getSpanContext(retrievedSpanCtxAttributes, false); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected getSpanContext failure detected", true, getSpanCtxSuccess); + } + void testTraceDisableConfig() { Owned testTree = createPTreeFromYAMLString(disableTracingYaml, ipt_none, ptr_ignoreWhiteSpace, nullptr); @@ -207,7 +220,6 @@ class JlibTraceTest : public CppUnit::TestFixture const char * serverSpanID = retrievedSpanCtxAttributes->queryProp("spanID"); CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected empty traceID detected", true, retrievedSpanCtxAttributes->hasProp("traceID")); const char * serverTraceID = retrievedSpanCtxAttributes->queryProp("traceID"); - { Owned internalSpan = serverSpan->createClientSpan("clientSpan");