Skip to content

Commit 2e63d2c

Browse files
committed
Merge remote-tracking branch 'origin/candidate-9.6.x'
Signed-off-by: Gavin Halliday <[email protected]> # Conflicts: # commons-hpcc/pom.xml # dfsclient/pom.xml # pom.xml # wsclient/pom.xml
2 parents a16004e + ce6160c commit 2e63d2c

File tree

9 files changed

+541
-247
lines changed

9 files changed

+541
-247
lines changed

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;

wsclient/src/main/java/org/hpccsystems/ws/client/utils/Connection.java

Lines changed: 83 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,20 @@
1212
import java.util.Base64;
1313
import java.util.Base64.Decoder;
1414
import java.util.Base64.Encoder;
15+
import java.util.regex.Matcher;
16+
import java.util.regex.Pattern;
1517

1618
import org.apache.logging.log4j.LogManager;
1719
import org.apache.logging.log4j.Logger;
20+
import org.hpccsystems.ws.client.BaseHPCCWsClient;
21+
22+
import io.opentelemetry.api.GlobalOpenTelemetry;
23+
import io.opentelemetry.api.trace.Span;
24+
import io.opentelemetry.api.trace.SpanKind;
25+
import io.opentelemetry.api.trace.StatusCode;
26+
import io.opentelemetry.context.Scope;
27+
import io.opentelemetry.semconv.HttpAttributes;
28+
import io.opentelemetry.semconv.ServerAttributes;
1829

1930
/**
2031
* Represents and structures connection information.
@@ -205,6 +216,9 @@ public int hashCode()
205216
private StringBuffer baseUrl;
206217
private StringBuffer uriAndParams;
207218

219+
// Note: this pattern is very basic and is only meant to extract hostnames from URLs
220+
public final static Pattern URL_HOSTNAME_PATTERN = Pattern.compile("((https?|ftp|file):\\/\\/)?(?<hostname>([\\da-z\\.\\-_]+)(\\.[a-z\\.]{2,6})?)(:\\d{2,6})?.*");
221+
208222
/** Constant <code>CONNECT_TIMEOUT_PARAM="connecttimeoutmillis"</code> */
209223
final static public String CONNECT_TIMEOUT_PARAM = "connecttimeoutmillis";
210224
/** Constant <code>READ_TIMEOUT_PARAM="readtimeoutmillis"</code> */
@@ -287,7 +301,27 @@ public static boolean isSslProtocol(String protocol)
287301
*/
288302
public Connection(String connectionstring) throws MalformedURLException
289303
{
290-
URL theurl = new URL(connectionstring);
304+
URL theurl = null;
305+
try
306+
{
307+
theurl = new URL(connectionstring);
308+
}
309+
catch (MalformedURLException e)
310+
{
311+
Matcher matcher = URL_HOSTNAME_PATTERN.matcher(connectionstring);
312+
if (matcher.matches())
313+
{
314+
String hostName = matcher.group("hostname");
315+
if (hostName.contains("_"))
316+
{
317+
throw new MalformedURLException("Invalid URL: Hostname contains invalid underscores: '" + connectionstring + "': " + e.getMessage());
318+
}
319+
}
320+
else
321+
{
322+
throw e;
323+
}
324+
}
291325

292326
setProtocol(theurl.getProtocol());
293327

@@ -1028,39 +1062,61 @@ public String sendHTTPRequest(String uri, String method) throws Exception
10281062

10291063
URL url = new URL (getBaseUrl() + (uri != null && uri.startsWith("/") ? "" : "/") + uri);
10301064

1031-
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); //throws IOException
1032-
1033-
Connection.log.info("Sending HTTP " + method + "Request to:" + url.toString());
1065+
Span sendHTTPReqSpan = GlobalOpenTelemetry.get().getTracer(BaseHPCCWsClient.PROJECT_NAME)
1066+
.spanBuilder(method.toUpperCase() + " " + url.toExternalForm())
1067+
.setAttribute(ServerAttributes.SERVER_ADDRESS, getHost())
1068+
.setAttribute(ServerAttributes.SERVER_PORT, Long.getLong(getPort()))
1069+
.setAttribute(HttpAttributes.HTTP_REQUEST_METHOD, method)
1070+
.setSpanKind(SpanKind.CLIENT)
1071+
.startSpan();
10341072

1035-
if (hasCredentials())
1036-
{
1037-
httpURLConnection.setRequestProperty("Authorization", getBasicAuthString());
1038-
}
1073+
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); //throws IOException
10391074

1040-
httpURLConnection.setRequestMethod(method); //throws ProtocolException
1075+
Connection.log.info("Sending HTTP " + method + "Request to:" + url.toString());
10411076

1042-
int responseCode = httpURLConnection.getResponseCode(); //throws IOException
1077+
if (hasCredentials())
1078+
{
1079+
httpURLConnection.setRequestProperty("Authorization", getBasicAuthString());
1080+
sendHTTPReqSpan.setAttribute("hasCredentials", true);
1081+
}
1082+
else
1083+
{
1084+
sendHTTPReqSpan.setAttribute("hasCredentials", false);
1085+
}
10431086

1044-
Connection.log.info("HTTP Response code: " + responseCode);
1087+
try (Scope scope = sendHTTPReqSpan.makeCurrent())
1088+
{
1089+
httpURLConnection.setRequestProperty("traceparent", Utils.getCurrentSpanTraceParentHeader());
1090+
httpURLConnection.setRequestMethod(method); //throws ProtocolException
10451091

1046-
if (responseCode == HttpURLConnection.HTTP_OK) //success
1047-
{
1048-
BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())); //throws IOException
1049-
String inputLine;
1050-
StringBuffer response = new StringBuffer();
1092+
int responseCode = httpURLConnection.getResponseCode(); //throws IOException
1093+
sendHTTPReqSpan.setAttribute("http.response.status_code", responseCode);
1094+
Connection.log.info("HTTP Response code: " + responseCode);
10511095

1052-
while ((inputLine = in.readLine()) != null) // throws IOException
1053-
{
1054-
response.append(inputLine);
1055-
}
1096+
if (responseCode == HttpURLConnection.HTTP_OK) //success
1097+
{
1098+
BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())); //throws IOException
1099+
String inputLine;
1100+
StringBuffer response = new StringBuffer();
10561101

1057-
in.close(); //throws IOException
1102+
while ((inputLine = in.readLine()) != null) // throws IOException
1103+
{
1104+
response.append(inputLine);
1105+
}
10581106

1059-
return response.toString();
1060-
}
1061-
else
1062-
{
1063-
throw new IOException("HTTP request failed! Code (" + responseCode + ") " + httpURLConnection.getResponseMessage() );
1064-
}
1107+
in.close(); //throws IOException
1108+
sendHTTPReqSpan.setStatus(StatusCode.OK);
1109+
return response.toString();
1110+
}
1111+
else
1112+
{
1113+
sendHTTPReqSpan.setStatus(StatusCode.ERROR);
1114+
throw new IOException("HTTP request failed! Code (" + responseCode + ") " + httpURLConnection.getResponseMessage() );
1115+
}
1116+
}
1117+
finally
1118+
{
1119+
sendHTTPReqSpan.end();
1120+
}
10651121
}
10661122
}

0 commit comments

Comments
 (0)