Skip to content

Commit ce6160c

Browse files
authored
HPCC-586 Add Otel Tracing support (hpcc-systems#714)
Signed-off-by: Rodrigo Pastrana <[email protected]>
1 parent 422ee47 commit ce6160c

File tree

9 files changed

+530
-247
lines changed

9 files changed

+530
-247
lines changed

pom.xml

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
<groups>org.hpccsystems.commons.annotations.BaseTests</groups>
6464
<codehaus.template.version>1.0.0</codehaus.template.version>
6565
<project.benchmarking>false</project.benchmarking>
66+
<opentelemetry.bom.version>1.38.0</opentelemetry.bom.version>
67+
<opentelemetry.semconv.version>1.25.0-alpha</opentelemetry.semconv.version>
6668
</properties>
6769

6870
<scm>
@@ -98,8 +100,44 @@
98100
</snapshots>
99101
</repository>
100102
</repositories>
101-
103+
<dependencyManagement>
104+
<dependencies>
105+
<dependency>
106+
<groupId>io.opentelemetry</groupId>
107+
<artifactId>opentelemetry-bom</artifactId>
108+
<version>${opentelemetry.bom.version}</version>
109+
<type>pom</type>
110+
<scope>import</scope>
111+
</dependency>
112+
</dependencies>
113+
</dependencyManagement>
102114
<dependencies>
115+
<dependency>
116+
<groupId>io.opentelemetry</groupId>
117+
<artifactId>opentelemetry-api</artifactId>
118+
</dependency>
119+
<dependency>
120+
<groupId>io.opentelemetry</groupId>
121+
<artifactId>opentelemetry-sdk</artifactId>
122+
</dependency>
123+
<dependency>
124+
<groupId>io.opentelemetry</groupId>
125+
<artifactId>opentelemetry-exporter-logging</artifactId>
126+
</dependency>
127+
<dependency>
128+
<groupId>io.opentelemetry</groupId>
129+
<artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
130+
</dependency>
131+
<dependency>
132+
<groupId>io.opentelemetry</groupId>
133+
<artifactId>opentelemetry-sdk-extension-autoconfigure-spi</artifactId>
134+
</dependency>
135+
<dependency>
136+
<!-- Not managed by opentelemetry-bom -->
137+
<groupId>io.opentelemetry.semconv</groupId>
138+
<artifactId>opentelemetry-semconv</artifactId>
139+
<version>1.25.0-alpha</version>
140+
</dependency>
103141
<dependency>
104142
<groupId>junit</groupId>
105143
<artifactId>junit</artifactId>

wsclient/src/main/java/org/hpccsystems/ws/client/BaseHPCCWsClient.java

Lines changed: 102 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,28 @@
4040
import org.w3c.dom.Node;
4141
import org.w3c.dom.NodeList;
4242

43+
import io.opentelemetry.api.GlobalOpenTelemetry;
44+
import io.opentelemetry.api.OpenTelemetry;
45+
import io.opentelemetry.api.trace.Span;
46+
import io.opentelemetry.api.trace.SpanBuilder;
47+
import io.opentelemetry.api.trace.SpanKind;
48+
import io.opentelemetry.api.trace.StatusCode;
49+
import io.opentelemetry.api.trace.Tracer;
50+
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
51+
import io.opentelemetry.context.Context;
52+
import io.opentelemetry.context.Scope;
53+
import io.opentelemetry.semconv.HttpAttributes;
54+
import io.opentelemetry.semconv.ServerAttributes;
55+
4356
/**
44-
* Defines functionality common to all HPCC Systmes web service clients.
57+
* Defines functionality common to all HPCC Systems web service clients.
4558
*
4659
* Typically implemented by specialized HPCC Web service clients.
4760
*/
4861
public abstract class BaseHPCCWsClient extends DataSingleton
4962
{
63+
public static final String PROJECT_NAME = "WsClient";
64+
private static OpenTelemetry globalOTel = null;
5065
/** Constant <code>log</code> */
5166
protected static final Logger log = LogManager.getLogger(BaseHPCCWsClient.class);
5267
/** Constant <code>DEAFULTECLWATCHPORT="8010"</code> */
@@ -164,6 +179,53 @@ private String getTargetHPCCBuildVersionString() throws Exception
164179

165180
}
166181

182+
public SpanBuilder getWsClientSpanBuilder(String spanName)
183+
{
184+
SpanBuilder spanBuilder = getWsClientTracer().spanBuilder(spanName)
185+
.setAttribute(ServerAttributes.SERVER_ADDRESS, wsconn.getHost())
186+
.setAttribute(ServerAttributes.SERVER_PORT, Long.getLong(wsconn.getPort()))
187+
.setAttribute(HttpAttributes.HTTP_REQUEST_METHOD, HttpAttributes.HttpRequestMethodValues.GET)
188+
.setSpanKind(SpanKind.CLIENT);
189+
190+
return spanBuilder;
191+
}
192+
193+
static public void injectCurrentSpanTraceParentHeader(Stub clientStub)
194+
{
195+
if (clientStub != null)
196+
{
197+
injectCurrentSpanTraceParentHeader(clientStub._getServiceClient().getOptions());
198+
}
199+
}
200+
201+
static public void injectCurrentSpanTraceParentHeader(Options options)
202+
{
203+
if (options != null)
204+
{
205+
W3CTraceContextPropagator.getInstance().inject(Context.current(), options, Options::setProperty);
206+
}
207+
}
208+
209+
/**
210+
* Performs all Otel initialization
211+
*/
212+
private void initOTel()
213+
{
214+
/*
215+
* If using the OpenTelemetry SDK, you may want to instantiate the OpenTelemetry toprovide configuration, for example of Resource or Sampler. See OpenTelemetrySdk and OpenTelemetrySdk.builder for information on how to construct theSDK's OpenTelemetry implementation.
216+
* WARNING: Due to the inherent complications around initialization order involving this classand its single global instance, we strongly recommend *not* using GlobalOpenTelemetry unless youhave a use-case that absolutely requires it. Please favor using instances of OpenTelemetrywherever possible.
217+
* If you are using the OpenTelemetry javaagent, it is generally best to only callGlobalOpenTelemetry.get() once, and then pass the resulting reference where you need to use it.
218+
*/
219+
globalOTel = GlobalOpenTelemetry.get();
220+
}
221+
222+
public Tracer getWsClientTracer()
223+
{
224+
if (globalOTel == null)
225+
initOTel();
226+
227+
return globalOTel.getTracer(PROJECT_NAME);
228+
}
167229
/**
168230
* All instances of HPCCWsXYZClient should utilize this init function
169231
* Attempts to establish the target HPCC build version and its container mode
@@ -175,36 +237,55 @@ private String getTargetHPCCBuildVersionString() throws Exception
175237
*/
176238
protected boolean initBaseWsClient(Connection connection, boolean fetchVersionAndContainerMode)
177239
{
240+
initOTel();
241+
178242
boolean success = true;
179243
initErrMessage = "";
180244
setActiveConnectionInfo(connection);
181245

182246
if (fetchVersionAndContainerMode)
183247
{
184-
try
248+
Span fetchHPCCVerSpan = getWsClientSpanBuilder("FetchHPCCVersion").setSpanKind(SpanKind.INTERNAL).startSpan();
249+
try (Scope scope = fetchHPCCVerSpan.makeCurrent())
185250
{
186-
targetHPCCBuildVersion = new Version(getTargetHPCCBuildVersionString());
251+
try
252+
{
253+
targetHPCCBuildVersion = new Version(getTargetHPCCBuildVersionString());
254+
}
255+
catch (Exception e)
256+
{
257+
initErrMessage = "BaseHPCCWsClient: Could not stablish target HPCC bulid version, review all HPCC connection values";
258+
if (!e.getLocalizedMessage().isEmpty())
259+
initErrMessage = initErrMessage + "\n" + e.getLocalizedMessage();
260+
success = false;
261+
}
187262
}
188-
catch (Exception e)
263+
finally
189264
{
190-
initErrMessage = "BaseHPCCWsClient: Could not stablish target HPCC bulid version, review all HPCC connection values";
191-
if (!e.getLocalizedMessage().isEmpty())
192-
initErrMessage = initErrMessage + "\n" + e.getLocalizedMessage();
193-
194-
success = false;
265+
fetchHPCCVerSpan.setStatus(success ? StatusCode.OK : StatusCode.ERROR, initErrMessage);
266+
fetchHPCCVerSpan.end();
195267
}
196268

197-
try
269+
Span fetchHPCCContainerMode = getWsClientSpanBuilder("FetchHPCCContainerMode").startSpan();
270+
try (Scope scope = fetchHPCCContainerMode.makeCurrent())
198271
{
199-
targetsContainerizedHPCC = getTargetHPCCIsContainerized(wsconn);
272+
try
273+
{
274+
targetsContainerizedHPCC = getTargetHPCCIsContainerized(wsconn);
275+
}
276+
catch (Exception e)
277+
{
278+
initErrMessage = initErrMessage + "\nBaseHPCCWsClient: Could not determine target HPCC Containerization mode, review all HPCC connection values";
279+
if (!e.getLocalizedMessage().isEmpty())
280+
initErrMessage = initErrMessage + "\n" + e.getLocalizedMessage();
281+
282+
success = false;
283+
}
200284
}
201-
catch (Exception e)
285+
finally
202286
{
203-
initErrMessage = initErrMessage + "\nBaseHPCCWsClient: Could not determine target HPCC Containerization mode, review all HPCC connection values";
204-
if (!e.getLocalizedMessage().isEmpty())
205-
initErrMessage = initErrMessage + "\n" + e.getLocalizedMessage();
206-
207-
success = false;
287+
fetchHPCCContainerMode.setStatus(success ? StatusCode.OK : StatusCode.ERROR, initErrMessage);
288+
fetchHPCCContainerMode.end();
208289
}
209290
}
210291
if (!initErrMessage.isEmpty())
@@ -401,7 +482,10 @@ public String getInitError()
401482
protected Stub verifyStub() throws Exception
402483
{
403484
if (stub != null)
485+
{
486+
injectCurrentSpanTraceParentHeader(stub);
404487
return stub;
488+
}
405489
else
406490
throw new Exception("WS Client Stub not available." + (hasInitError() ? "\n" + initErrMessage : ""));
407491
}
@@ -687,6 +771,7 @@ protected void handleEspExceptions(ArrayOfEspExceptionWrapper exp, String messag
687771
if (message != null && !message.isEmpty()) exp.setWsClientMessage(message);
688772

689773
log.error(exp.toString());
774+
690775
throw exp;
691776
}
692777

wsclient/src/main/java/org/hpccsystems/ws/client/HPCCWsClient.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import org.hpccsystems.ws.client.utils.Utils;
2020
import org.hpccsystems.ws.client.wrappers.ArrayOfECLExceptionWrapper;
2121
import org.hpccsystems.ws.client.wrappers.gen.filespray.ProgressResponseWrapper;
22-
import org.hpccsystems.ws.client.wrappers.gen.wstopology.TpGroupQueryResponseWrapper;
2322
import org.hpccsystems.ws.client.wrappers.gen.wstopology.TpGroupWrapper;
2423
import org.hpccsystems.ws.client.wrappers.wsworkunits.WorkunitWrapper;
2524

wsclient/src/main/java/org/hpccsystems/ws/client/HPCCWsWorkUnitsClient.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@
100100
import org.hpccsystems.ws.client.wrappers.wsworkunits.WorkunitWrapper;
101101
import org.hpccsystems.ws.client.wrappers.wsworkunits.WsWorkunitsClientStubWrapper;
102102

103+
import io.opentelemetry.api.trace.Span;
104+
import io.opentelemetry.api.trace.StatusCode;
105+
import io.opentelemetry.context.Scope;
106+
103107
/**
104108
* Facilitates ECL WorkUnit related actions.
105109
*
@@ -303,7 +307,6 @@ public void fastWURefresh(WorkunitWrapper wu) throws Exception, ArrayOfEspExcept
303307
request.setCount(1);
304308

305309
WUQueryResponse response = null;
306-
307310
try
308311
{
309312
response = ((WsWorkunits) stub).wUQuery(request);
@@ -326,7 +329,8 @@ public void fastWURefresh(WorkunitWrapper wu) throws Exception, ArrayOfEspExcept
326329
{
327330
ECLWorkunit[] eclWorkunit = response.getWorkunits().getECLWorkunit();
328331

329-
if (eclWorkunit != null && eclWorkunit.length == 1) wu.update(eclWorkunit[0]);
332+
if (eclWorkunit != null && eclWorkunit.length == 1)
333+
wu.update(eclWorkunit[0]);
330334
}
331335

332336
if (previousState != getStateID(wu))
@@ -2551,18 +2555,27 @@ public List<QueryResultWrapper> deleteQueries(Set<String> querynames, String clu
25512555
*/
25522556
public boolean ping() throws Exception
25532557
{
2554-
verifyStub();
2555-
2556-
Ping request = new Ping();
2557-
2558-
try
2558+
Span span = getWsClientSpanBuilder("WsWUClient_Ping").startSpan();
2559+
try (Scope scope = span.makeCurrent())
25592560
{
2560-
((WsWorkunitsStub) stub).ping(request);
2561+
verifyStub(); // must be called within span scope for proper context propagation
2562+
2563+
Ping request = new Ping();
2564+
try
2565+
{
2566+
((WsWorkunitsStub) stub).ping(request);
2567+
span.setStatus(StatusCode.OK);
2568+
}
2569+
catch (Exception e)
2570+
{
2571+
span.recordException(e);
2572+
log.error(e.getLocalizedMessage());
2573+
return false;
2574+
}
25612575
}
2562-
catch (Exception e)
2576+
finally
25632577
{
2564-
log.error(e.getLocalizedMessage());
2565-
return false;
2578+
span.end();
25662579
}
25672580

25682581
return true;

0 commit comments

Comments
 (0)