Skip to content

Commit

Permalink
HPCC-30474 Provide JTrace option to declare span start time
Browse files Browse the repository at this point in the history
- Exposes helper method to obtain timestamp in nanos
- Exposes createServerSpan function w/ optional starttime param
- Adds simple cppunit tests excersizing both newly exposed functions

Signed-off-by: Rodrigo Pastrana <[email protected]>
  • Loading branch information
rpastrana committed Dec 8, 2023
1 parent 87db198 commit 7eb52dc
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 39 deletions.
24 changes: 20 additions & 4 deletions system/jlib/jtrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,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;

Expand Down Expand Up @@ -988,13 +989,19 @@ class CServerSpan : public CSpan
}

public:
CServerSpan(const char * spanName, const IProperties * httpHeaders, SpanFlags flags)
CServerSpan(const char * spanName, const IProperties * httpHeaders, SpanFlags flags, std::chrono::nanoseconds spanStartTime)
: CSpan(spanName)
{
std::chrono::_V2::system_clock::time_point time_point = std::chrono::system_clock::now();
opts.start_system_time = opentelemetry::common::SystemTimestamp(std::chrono::duration_cast<std::chrono::nanoseconds>(spanStartTime));
opts.kind = opentelemetry::trace::SpanKind::kServer;
setSpanContext(httpHeaders, flags);
init(flags);
setContextAttributes();
}

opts.start_system_time = opentelemetry::common::SystemTimestamp(time_point);
opts.start_steady_time = opentelemetry::common::SteadyTimestamp(std::chrono::nanoseconds(10));
CServerSpan(const char * spanName, const IProperties * httpHeaders, SpanFlags flags)
: CSpan(spanName)
{
opts.kind = opentelemetry::trace::SpanKind::kServer;
setSpanContext(httpHeaders, flags);
init(flags);
Expand Down Expand Up @@ -1041,6 +1048,11 @@ class CServerSpan : public CSpan

//---------------------------------------------------------------------------------------------------------------------

std::chrono::nanoseconds nowTimesStampInNanos()
{
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch());
}

IProperties * getClientHeaders(const ISpan * span)
{
Owned<IProperties> headers = createProperties(true);
Expand Down Expand Up @@ -1337,6 +1349,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);
}

//---------------------------------------------------------------------------------------------------------------------

Expand Down
6 changes: 5 additions & 1 deletion system/jlib/jtrace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

#ifndef JTRACE_HPP
#define JTRACE_HPP
#include <variant>
#include <chrono>

/**
* @brief This follows open telemetry's span attribute naming conventions
* Known HPCC span Keys could be added here
Expand Down Expand Up @@ -77,6 +78,7 @@ extern jlib_decl IProperties * getClientHeaders(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;
Expand All @@ -85,6 +87,8 @@ 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"
Expand Down
53 changes: 19 additions & 34 deletions testing/unittests/jlibtests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@ class JlibTraceTest : public CppUnit::TestFixture
CPPUNIT_TEST(testInternalSpan);
CPPUNIT_TEST(testMultiNestedSpanTraceOutput);
CPPUNIT_TEST(testNullSpan);
CPPUNIT_TEST(testClientSpan);
CPPUNIT_TEST(testClientSpanGlobalID);
CPPUNIT_TEST(testEnsureTraceID);

CPPUNIT_TEST(testJTraceJLOGExporterprintResources);
CPPUNIT_TEST(testJTraceJLOGExporterprintAttributes);
CPPUNIT_TEST(testDeclaredSpanStartTime);
CPPUNIT_TEST_SUITE_END();

const char * simulatedGlobalYaml = R"!!(global:
Expand Down Expand Up @@ -108,6 +110,18 @@ class JlibTraceTest : public CppUnit::TestFixture

protected:

void testDeclaredSpanStartTime()
{
std::chrono::nanoseconds nownanos = nowTimesStampInNanos();
Owned<IProperties> emptyMockHTTPHeaders = createProperties();

Owned<ISpan> serverSpan = queryTraceManager().createServerSpan("declaredSpanStartSpan", emptyMockHTTPHeaders, SpanFlags::None, nownanos);

Owned<IProperties> retrievedSpanCtxAttributes = createProperties();
bool getSpanCtxSuccess = serverSpan->getSpanContext(retrievedSpanCtxAttributes, false);
CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected getSpanContext failure detected", true, getSpanCtxSuccess);
}

void testJTraceJLOGExporterprintAttributes()
{
StringBuffer out;
Expand Down Expand Up @@ -278,8 +292,10 @@ class JlibTraceTest : public CppUnit::TestFixture

void testClientSpan()
{
{
std::chrono::nanoseconds nownanos = nowTimesStampInNanos();
Owned<IProperties> emptyMockHTTPHeaders = createProperties();
Owned<ISpan> serverSpan = queryTraceManager().createServerSpan("propegatedServerSpan", emptyMockHTTPHeaders);
Owned<ISpan> serverSpan = queryTraceManager().createServerSpan("propegatedServerSpan", emptyMockHTTPHeaders, SpanFlags::None, nownanos);

Owned<IProperties> retrievedSpanCtxAttributes = createProperties();
bool getSpanCtxSuccess = serverSpan->getSpanContext(retrievedSpanCtxAttributes, false);
Expand All @@ -289,40 +305,9 @@ 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<ISpan> internalSpan = serverSpan->createClientSpan("clientSpan");

//retrieve clientSpan context with the intent to propogate otel and HPCC context
{
Owned<IProperties> retrievedSpanCtxAttributes = createProperties();
bool getSpanCtxSuccess = internalSpan->getSpanContext(retrievedSpanCtxAttributes, false);
CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected getSpanContext failure detected", true, getSpanCtxSuccess);

CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected missing localParentSpanID detected", true,
retrievedSpanCtxAttributes->hasProp("localParentSpanID"));

CPPUNIT_ASSERT_MESSAGE("Mismatched localParentSpanID detected",
strsame(serverSpanID, retrievedSpanCtxAttributes->queryProp("localParentSpanID")));

CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected missing remoteParentID detected", true,
retrievedSpanCtxAttributes->hasProp("remoteParentID"));

CPPUNIT_ASSERT_MESSAGE("Unexpected CallerID detected",
strsame(serverTraceID, retrievedSpanCtxAttributes->queryProp("remoteParentID")));

CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected GlobalID detected", false,
retrievedSpanCtxAttributes->hasProp(kGlobalIdHttpHeaderName));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected CallerID detected", false,
retrievedSpanCtxAttributes->hasProp(kCallerIdHttpHeaderName));

CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected Declared Parent SpanID detected", false,
retrievedSpanCtxAttributes->hasProp("remoteParentSpanID"));

CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected empty TraceID detected", false, isEmptyString(retrievedSpanCtxAttributes->queryProp("traceID")));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected empty SpanID detected", false, isEmptyString(retrievedSpanCtxAttributes->queryProp("spanID")));
}
}

DBGLOG("testClientSpan: createClientSpan");
}

void testInternalSpan()
Expand Down

0 comments on commit 7eb52dc

Please sign in to comment.