Skip to content
This repository was archived by the owner on Jun 2, 2022. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
4359e24
Created new HTTP/JSON exporter. Created new JsonProtoRequestBody that…
tnevolin Sep 27, 2021
846e440
Use JsonProtoRequestBody in OtlpHttpJsonSpanExporter.export() to supp…
tnevolin Sep 28, 2021
f19f801
HTTP/JSON test
tnevolin Oct 1, 2021
90f7011
Organized import
tnevolin Oct 1, 2021
c4e61cd
Organized import
tnevolin Oct 1, 2021
634af2b
Organized import.
tnevolin Oct 1, 2021
d825152
Disabled warning->error.
tnevolin Oct 1, 2021
1ee7be1
Modified JSON tests
Oct 1, 2021
8fcb218
Debug statement.
tnevolin Oct 1, 2021
1b171d2
Debug statement.
tnevolin Oct 1, 2021
ee09b46
Renamed local variable for clarity.
tnevolin Oct 4, 2021
ba713a6
Changed Media Type to JSON.
tnevolin Oct 4, 2021
c6de1f8
Changed Media Type to JSON in JsonProtoRequestBody.
tnevolin Oct 5, 2021
19a379a
Changed JsonRequestBody to not extend any protobuf functionality.
tnevolin Oct 5, 2021
b02f858
Added direct JSON formatting.
tnevolin Oct 5, 2021
e9d74a2
Formatted.
Oct 6, 2021
e214d6c
Added charset to the test message.
tnevolin Oct 6, 2021
b7862f5
Returned to protobuf json marshaler.
tnevolin Oct 6, 2021
ec5b688
Count JSON output length directly.
tnevolin Oct 7, 2021
73bad0d
Removed preliminary body length computation.
tnevolin Oct 7, 2021
2fe5da6
Changed payload to byte[].
tnevolin Oct 7, 2021
a30ffd3
Rewrote tests to match JSON message format.
tnevolin Oct 8, 2021
019d73b
Commented out some tests.
tnevolin Oct 8, 2021
97b3ddb
Commented out code that I plan to revert.
tnevolin Oct 8, 2021
b6dd3d4
spotlessApply.
Oct 8, 2021
3053112
Cleaned up unused code.
tnevolin Oct 8, 2021
0f4cda2
Resolved merge conflicts.
Oct 13, 2021
8b1d345
Commented out unused tests and methods.
tnevolin Oct 13, 2021
8e1980e
spotlessApply.
Oct 13, 2021
e3aed5f
Created new subproject for otlp-http-json.
tnevolin Oct 14, 2021
441a697
Created new subproject for otlp-http-json #2.
tnevolin Oct 14, 2021
ba8d9b2
Reverted some docs files.
tnevolin Oct 14, 2021
86d65d0
Added build scripts to subproject for otlp-http-json.
tnevolin Oct 14, 2021
9166887
Changed package info package.
tnevolin Oct 14, 2021
ae3a013
Moved HTTP/JSON classes to appropriate package.
tnevolin Oct 14, 2021
150039a
Renamed package.
tnevolin Oct 14, 2021
92407f2
Corrected javadoc reference.
tnevolin Oct 14, 2021
6961104
Added generated changelog.
Oct 15, 2021
f54a3cf
Changed host name to IP for TLS test.
tnevolin Oct 15, 2021
9f7d4a6
Reinstated all tests in HTTP/JSON.
tnevolin Oct 15, 2021
5eae5c9
spotlessApply
Oct 15, 2021
ab02907
Commented out unused method.
tnevolin Oct 15, 2021
d5c9876
Fiddled with canonical host name.
tnevolin Oct 15, 2021
15cf7da
spotlessApply
Oct 15, 2021
e596083
Updated endpoints with canonical host name.
tnevolin Oct 15, 2021
aa74977
Merge branch 'feature/opentelemetry-java/3651' of github.com:lightste…
Oct 15, 2021
372b13a
Updated endpoints with canonical host name.
tnevolin Oct 15, 2021
55a5cb1
Merge branch 'feature/opentelemetry-java/3651' of github.com:lightste…
Oct 15, 2021
1c6e701
Removed commented code.
tnevolin Oct 15, 2021
5ffd134
spotlessApply
Oct 15, 2021
83df3d7
Merge branch 'feature/opentelemetry-java/3651' of github.com:lightste…
Oct 15, 2021
eb1ec6c
Used canonical host name everywhere in tests to make them pass on Win…
tnevolin Oct 15, 2021
7e8b36a
Documentation.
tnevolin Oct 16, 2021
78fee94
Merging to test branch.
tnevolin Oct 16, 2021
ee3a632
Test commit.
tnevolin Oct 16, 2021
c072fa4
Removed test file.
tnevolin Oct 16, 2021
e1847a3
spotlessApply
Oct 16, 2021
e94a3ef
Corrected one readme header.
tnevolin Oct 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ tasks {
"-Xlint:-options",

// Fail build on any warning
"-Werror"
// [TN] Disabling this as it causes tests to fail due to below error which has nothing to do with this project code.
// Illegal reflective access by com.google.errorprone.util.ErrorProneTokens$CommentSavingTokenizer (file:/<user dir>/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_check_api/2.9.0/fe4decdb87a17bd5583147d96b0fdb852985b333/error_prone_check_api-2.9.0.jar) to field com.sun.tools.javac.parser.JavaTokenizer.reader
// "-Werror"
))
}

Expand Down
1,355 changes: 1 addition & 1,354 deletions docs/apidiffs/current_vs_latest/opentelemetry-exporter-jaeger-proto.txt

Large diffs are not rendered by default.

1,372 changes: 1 addition & 1,371 deletions docs/apidiffs/current_vs_latest/opentelemetry-exporter-jaeger.txt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Comparing source compatibility of against
+++ NEW CLASS: PUBLIC(+) FINAL(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporter (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporterBuilder builder()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.CompletableResultCode export(java.util.Collection)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.CompletableResultCode flush()
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporter getDefault()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.CompletableResultCode shutdown()
+++ NEW CLASS: PUBLIC(+) FINAL(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporterBuilder (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporterBuilder addHeader(java.lang.String, java.lang.String)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporter build()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporterBuilder setCompression(java.lang.String)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporterBuilder setEndpoint(java.lang.String)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporterBuilder setTimeout(long, java.util.concurrent.TimeUnit)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporterBuilder setTimeout(java.time.Duration)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.httpjson.trace.OtlpHttpJsonSpanExporterBuilder setTrustedCertificates(byte[])
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@ class OtlpHttpMetricExporterTest {
private static final MediaType APPLICATION_PROTOBUF =
MediaType.create("application", "x-protobuf");
private static final HeldCertificate HELD_CERTIFICATE;
private static final String canonicalHostName;

static {
try {
canonicalHostName = InetAddress.getByName("localhost").getCanonicalHostName();
HELD_CERTIFICATE =
new HeldCertificate.Builder()
.commonName("localhost")
.addSubjectAlternativeName(InetAddress.getByName("localhost").getCanonicalHostName())
.addSubjectAlternativeName(canonicalHostName)
.build();
} catch (UnknownHostException e) {
throw new IllegalStateException("Error building certificate.", e);
Expand All @@ -88,7 +90,7 @@ protected void configureServer(ServerBuilder sb) {
void setup() {
builder =
OtlpHttpMetricExporter.builder()
.setEndpoint("https://localhost:" + server.httpsPort() + "/v1/metrics")
.setEndpoint("https://" + canonicalHostName + ":" + server.httpsPort() + "/v1/metrics")
.addHeader("foo", "bar")
.setTrustedCertificates(
HELD_CERTIFICATE.certificatePem().getBytes(StandardCharsets.UTF_8));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,15 @@ class OtlpHttpSpanExporterTest {
private static final MediaType APPLICATION_PROTOBUF =
MediaType.create("application", "x-protobuf");
private static final HeldCertificate HELD_CERTIFICATE;
private static final String canonicalHostName;

static {
try {
canonicalHostName = InetAddress.getByName("localhost").getCanonicalHostName();
HELD_CERTIFICATE =
new HeldCertificate.Builder()
.commonName("localhost")
.addSubjectAlternativeName(InetAddress.getByName("localhost").getCanonicalHostName())
.addSubjectAlternativeName(canonicalHostName)
.build();
} catch (UnknownHostException e) {
throw new IllegalStateException("Error building certificate.", e);
Expand All @@ -91,7 +93,7 @@ protected void configureServer(ServerBuilder sb) {
void setup() {
builder =
OtlpHttpSpanExporter.builder()
.setEndpoint("http://localhost:" + server.httpPort() + "/v1/traces")
.setEndpoint("http://" + canonicalHostName + ":" + server.httpPort() + "/v1/traces")
.addHeader("foo", "bar");
}

Expand Down Expand Up @@ -149,7 +151,7 @@ void testExportTls() {
server.enqueue(successResponse());
OtlpHttpSpanExporter exporter =
builder
.setEndpoint("https://localhost:" + server.httpsPort() + "/v1/traces")
.setEndpoint("https://" + canonicalHostName + ":" + server.httpsPort() + "/v1/traces")
.setTrustedCertificates(
HELD_CERTIFICATE.certificatePem().getBytes(StandardCharsets.UTF_8))
.build();
Expand Down
10 changes: 10 additions & 0 deletions exporters/otlp-httpjson/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
subprojects {
// Workaround https://github.com/gradle/gradle/issues/847
group = "io.opentelemetry.exporter.otlp.httpjson"
val proj = this
plugins.withId("java") {
configure<BasePluginConvention> {
archivesBaseName = "opentelemetry-exporter-otlp-httpjson-${proj.name}"
}
}
}
162 changes: 162 additions & 0 deletions exporters/otlp-httpjson/trace/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# OpenTelemetry - OTLP Trace Exporter - HTTP

[![Javadocs][javadoc-image]][javadoc-url]

This is the OpenTelemetry exporter, sending span data to OpenTelemetry collector via HTTP/JSON without gRPC.

[javadoc-image]: https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-exporter-otlp-httpjson-trace.svg
[javadoc-url]: https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-otlp-httpjson-trace

## Description

This exporter is similar in functionality to [OTLP HTTP exporter](exporters/otlp-http/) except that it populates HTTP request body with protobuf **JSON** representation rather than binary one.

The [main exporter class](exporters/otlp-httpjson/trace/src/main/java/io/opentelemetry/exporter/otlp/httpjson/trace/OtlpHttpJsonSpanExporter.java) is created by [exporter builder](java/io/opentelemetry/exporter/otlp/httpjson/trace/OtlpHttpJsonSpanExporterBuilder.java). The [exporter class export method](exporters/otlp-httpjson/trace/src/main/java/io/opentelemetry/exporter/otlp/httpjson/trace/OtlpHttpJsonSpanExporter.java) delegates request body creation to its own version of [ProtoJsonRequestBody](exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/ProtoJsonRequestBody.java) which in turn uses [Marshaller.writeJsonTo method](exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/Marshaler.java) to generate protobuf JSON output.

## Adding more fields in message body

Message body is automatically generated from [Span](api/all/src/main/java/io/opentelemetry/api/trace/Span.java) corresponding marshalers. Client can add unlimited number of Span attributes those will be serialized by the same process.

## STDOUT dumping option

The exporter itself does not provide dumping message body to STDOUT functionality. However, it is possible to attach [OTLP logging exporter](exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java) to the same [SdkTracerProvider](sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java) like below and let them work in parallel. Logging exporter uses the same set of protobuf/Span marshaller to generate the message. The only difference is that HTTP exporters wrap the list of spans into a top level element.

```
SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder().build()).build())
.addSpanProcessor(SimpleSpanProcessor.create(new LoggingSpanExporter());
```

## Unit tests

Unit tests for HTTP/JSON exporter are similar to HTTP exporter ones.

### Linux/Windows TLS certificate test problem

OKHTTP client searches HTTP request host in subjectAlternativeName certificate field and not in commonName. It is important to use the same hostname in all test requests that was set to [subjectAlternativeNames](https://github.com/open-telemetry/opentelemetry-java/blob/9cd3f2f79b992b18e537c39db4cefd3c5b2a4e2f/exporters/otlp-http/trace/src/test/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporterTest.java#L69) in order for OKHTTP client properly verify the host. Previously that host was hardcoded to `"localhost"` which resolves to `"localhost"` on Linux but to `"127.0.0.1"`. That led to failed Windows tests. When hostname in all test request was replaced with correctly resolved canonical name test passed on Windows too.
[GitHub issue](https://github.com/open-telemetry/opentelemetry-java/issues/3619)

```java
canonicalHostName = InetAddress.getByName("localhost").getCanonicalHostName();
HELD_CERTIFICATE =
new HeldCertificate.Builder()
.commonName("localhost")
.addSubjectAlternativeName(canonicalHostName)
.build();
```

```java
void setup() {
builder =
OtlpHttpJsonSpanExporter.builder()
.setEndpoint("http://" + canonicalHostName + ":" + server.httpPort() + "/v1/traces")
.addHeader("foo", "bar");
}
```
## Integration test with collector

Open telemetry collector contribution project contains [example tracing collector](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/examples/tracing). One can verify that collector front-end port is exposed to host OS [here](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/a244c7e788eb1d6cfce9f210eb226dce8414caa8/examples/tracing/docker-compose.yml#L43). If not modify docker-compose.yml to expose it. After that [example HTTP client](https://github.com/open-telemetry/opentelemetry-java/tree/main/examples/http) on host OS would be able to connect to above port and send exported messages. These messages can be then verified on collector back-end monitoring websites locally.

## Verifying HTTP message body output

Another method to verify exporter message body output is to set up a dummy server that accepts and dumps request to STDOUT. Exporter reports error as it does not get proper collector response but dummy server still receives and dump requests.

### Sample dummy server

```bash
ncat -l -p 8080
```

#### Sample JSON output

```json
{
"resourceSpans": [
{
"resource": {
"attributes": [
{
"key": "service.name",
"value": {
"stringValue": "test_http_json"
}
}
]
},
"instrumentationLibrarySpans": [
{
"instrumentationLibrary": {
"name": "io.opentelemetry.example.http.HttpClient"
},
"spans": [
{
"traceId": "4592f2b0ea46fd30e6712cb6a69e73c6",
"spanId": "40e3cf388832f9b8",
"name": "/",
"kind": "SPAN_KIND_CLIENT",
"startTimeUnixNano": "1634067072893000000",
"endTimeUnixNano": "1634067072901965000",
"attributes": [
{
"key": "component",
"value": {
"stringValue": "http"
}
},
{
"key": "attribute_boolean",
"value": {
"boolValue": true
}
},
{
"key": "component1",
"value": {
"stringValue": "test_component"
}
},
{
"key": "attribute_string",
"value": {
"stringValue": "value_string"
}
},
{
"key": "attribute_long",
"value": {
"intValue": "9223372036854775807"
}
},
{
"key": "http.url",
"value": {
"stringValue": "http://127.0.0.1:8090"
}
},
{
"key": "http.method",
"value": {
"stringValue": "GET"
}
},
{
"key": "attribute_double",
"value": {
"doubleValue": 1.7976931348623157e308
}
}
],
"events": [],
"links": [],
"status": {
"message": "test description",
"code": "STATUS_CODE_OK"
}
}
]
}
]
}
]
}
```
25 changes: 25 additions & 0 deletions exporters/otlp-httpjson/trace/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
id("otel.java-conventions")
id("otel.publish-conventions")

id("otel.animalsniffer-conventions")
}

description = "OpenTelemetry Protocol HTTP/JSON Trace Exporter"
otelJava.moduleName.set("io.opentelemetry.exporter.otlp.httpjson.trace")

dependencies {
api(project(":sdk:trace"))

implementation(project(":exporters:otlp:common"))

implementation("com.squareup.okhttp3:okhttp")
implementation("com.squareup.okio:okio")

testImplementation(project(":proto"))
testImplementation(project(":sdk:testing"))

testImplementation("com.google.api.grpc:proto-google-common-protos")
testImplementation("com.linecorp.armeria:armeria-junit5")
testImplementation("com.squareup.okhttp3:okhttp-tls")
}
Loading