Merge pull request #508 from artursouza/tracing_example_validate

Auto-validation for tracing sample.
This commit is contained in:
Artur Souza 2021-03-11 15:08:51 -08:00 committed by GitHub
commit dcaffe8932
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 143 additions and 13 deletions

View File

@ -112,6 +112,10 @@ jobs:
working-directory: ./examples
run: |
mm.py ./src/main/java/io/dapr/examples/invoke/grpc/README.md
- name: Validate tracing example
working-directory: ./examples
run: |
mm.py ./src/main/java/io/dapr/examples/tracing/README.md
- name: Validate expection handling example
working-directory: ./examples
run: |

View File

@ -74,6 +74,11 @@
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>

View File

@ -66,18 +66,15 @@ public class InvokeClient {
}).subscriberContext(getReactorContext()).block();
}
}
// This is an example, so for simplicity we are just exiting here.
// Normally a dapr app would be a web service and not exit main.
System.out.println("Done");
}
span.end();
shutdown();
System.out.println("Done");
}
private static void shutdown() {
private static void shutdown() throws Exception {
OpenTelemetrySdk.getGlobalTracerManagement().shutdown();
Validation.validate();
}
}

View File

@ -126,10 +126,19 @@ The instrumentation for the service happens via the `OpenTelemetryIterceptor` cl
Use the follow command to execute the service:
```sh
<!-- STEP
name: Run demo service
expected_stdout_lines:
background: true
sleep: 20
-->
```bash
dapr run --app-id tracingdemo --app-port 3000 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.tracing.TracingDemoService -p 3000
```
<!-- END_STEP -->
Once running, the TracingDemoService is now ready to be invoked by Dapr.
### Running the Demo middle service app
@ -208,10 +217,19 @@ public class OpenTelemetryConfig {
Use the follow command to execute the service:
```sh
<!-- STEP
name: Run proxy service
expected_stdout_lines:
background: true
sleep: 20
-->
```bash
dapr run --app-id tracingdemoproxy --app-port 3001 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.tracing.TracingDemoService -p 3001
```
<!-- END_STEP -->
### Running the InvokeClient app
This sample code uses the Dapr SDK for invoking two remote methods (`proxy_echo` and `proxy_sleep`). It is also instrumented with OpenTelemetry. See the code snippet below:
@ -247,13 +265,10 @@ private static final String SERVICE_APP_ID = "tracingdemoproxy";
}).subscriberContext(getReactorContext()).block();
}
}
// This is an example, so for simplicity we are just exiting here.
// Normally a dapr app would be a web service and not exit main.
System.out.println("Done");
}
span.end();
shutdown();
System.out.println("Done");
}
///...
}
@ -262,9 +277,21 @@ private static final String SERVICE_APP_ID = "tracingdemoproxy";
The class knows the app id for the remote application. It uses `invokeMethod` method to invoke API calls on the service endpoint. The request object includes an instance of `io.opentelemetry.context.Context` for the proper tracing headers to be propagated.
Execute the follow script in order to run the InvokeClient example, passing two messages for the remote method:
```sh
<!-- STEP
name: Run demo client
expected_stdout_lines:
- '== APP == Done'
background: true
sleep: 20
-->
```bash
dapr run -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.tracing.InvokeClient "message one" "message two"
```
<!-- END_STEP -->
Open the `tracingdemo` console and check the output as follows:
```txt

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) Microsoft Corporation and Dapr Contributors.
* Licensed under the MIT License.
*/
package io.dapr.examples.tracing;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import net.minidev.json.JSONArray;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* Class used to verify that traces are present as expected.
*/
final class Validation {
private static final OkHttpClient HTTP_CLIENT = new OkHttpClient();
public static final String JSONPATH_PROXY_ECHO_SPAN_ID =
"$..[?(@.parentId=='%s' && @.name=='calllocal/tracingdemoproxy/proxy_echo')]['id']";
public static final String JSONPATH_ECHO_SPAN_ID =
"$..[?(@.parentId=='%s' && @.name=='calllocal/tracingdemo/echo')]['id']";
public static final String JSONPATH_PROXY_SLEEP_SPAN_ID =
"$..[?(@.parentId=='%s' && @.duration > 1000000 && @.name=='calllocal/tracingdemoproxy/proxy_sleep')]['id']";
public static final String JSONPATH_SLEEP_SPAN_ID =
"$..[?(@.parentId=='%s' && @.duration > 1000000 && @.name=='calllocal/tracingdemo/sleep')]['id']";
static void validate() throws Exception {
// Must wait for some time to make sure Zipkin receives all spans.
Thread.sleep(5000);
HttpUrl.Builder urlBuilder = new HttpUrl.Builder();
urlBuilder.scheme("http")
.host("localhost")
.port(9411);
urlBuilder.addPathSegments("api/v2/traces");
Request.Builder requestBuilder = new Request.Builder()
.url(urlBuilder.build());
requestBuilder.method("GET", null);
Request request = requestBuilder.build();
Response response = HTTP_CLIENT.newCall(request).execute();
DocumentContext documentContext = JsonPath.parse(response.body().string());
String mainSpanId = readOne(documentContext, "$..[?(@.name == \"example's main\")]['id']").toString();
// Validate echo
assertCount(documentContext,
String.format(JSONPATH_PROXY_ECHO_SPAN_ID, mainSpanId),
2);
String proxyEchoSpanId = readOne(documentContext,
String.format(JSONPATH_PROXY_ECHO_SPAN_ID, mainSpanId))
.toString();
String proxyEchoSpanId2 = readOne(documentContext,
String.format(JSONPATH_PROXY_ECHO_SPAN_ID, proxyEchoSpanId))
.toString();
readOne(documentContext,
String.format(JSONPATH_ECHO_SPAN_ID, proxyEchoSpanId2));
// Validate sleep
assertCount(documentContext,
String.format(JSONPATH_PROXY_SLEEP_SPAN_ID, mainSpanId),
2);
String proxySleepSpanId = readOne(documentContext,
String.format(JSONPATH_PROXY_SLEEP_SPAN_ID, mainSpanId))
.toString();
String proxySleepSpanId2 = readOne(documentContext,
String.format(JSONPATH_PROXY_SLEEP_SPAN_ID, proxySleepSpanId))
.toString();
readOne(documentContext,
String.format(JSONPATH_SLEEP_SPAN_ID, proxySleepSpanId2));
}
private static Object readOne(DocumentContext documentContext, String path) {
JSONArray arr = documentContext.read(path);
if (arr.size() == 0) {
throw new RuntimeException("No record found for " + path);
}
return arr.get(0);
}
private static void assertCount(DocumentContext documentContext, String path, int expectedCount) {
JSONArray arr = documentContext.read(path);
if (arr.size() != expectedCount) {
throw new RuntimeException(
String.format("Unexpected count %d vs expected %d for %s", arr.size(), expectedCount, path));
}
}
}