Skip to content

Commit 003b358

Browse files
Add documentation for the OpenTelemetry instrumentation (#658)
Signed-off-by: Alexander Wert <alexander.wert@elastic.co> Co-authored-by: Sylvain Wallez <sylvain@elastic.co>
1 parent 858f8b3 commit 003b358

File tree

6 files changed

+111
-0
lines changed

6 files changed

+111
-0
lines changed
Loading
185 KB
Loading
131 KB
Loading

docs/setup/index.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
* <<installation>>
44
* <<connecting>>
55
* <<migrate-hlrc>>
6+
* <<opentelemetry>>
67
* <<java-rest-low>>
78
89
include::installation.asciidoc[]
910
include::connecting.asciidoc[]
1011
include::migrate-hlrc.asciidoc[]
12+
include::open-telemetry.asciidoc[]
1113

1214
// include::low-level.asciidoc[leveloffset=+2]

docs/setup/open-telemetry.asciidoc

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
[[opentelemetry]]
2+
=== Using OpenTelemetry
3+
4+
You can use https://opentelemetry.io/[OpenTelemetry] to monitor the performance and behavior of your Elasticsearch requests through the Java API Client.
5+
The Java API Client comes with built-in OpenTelemetry instrumentation that emits https://www.elastic.co/guide/en/apm/guide/current/apm-distributed-tracing.html[distributed tracing spans] by default.
6+
With that, applications https://opentelemetry.io/docs/instrumentation/java/manual/[instrumented with OpenTelemetry] or running the https://opentelemetry.io/docs/instrumentation/java/automatic/[OpenTelemetry Java Agent] are inherently enriched with additional spans that contain insightful information about the execution of the Elasticsearch requests.
7+
8+
The native instrumentation in the Java API Client follows the https://opentelemetry.io/docs/specs/semconv/database/elasticsearch/[OpenTelemetry Semantic Conventions for Elasticsearch]. In particular, the instrumentation in the client covers the logical Elasticsearch request layer, thus, creates a single span per request the service executes against the Java API Client. The following image shows a resulting trace in which three different Elasticsearch requests are executed, i.e. an `index`, `get` and a search `request`:
9+
10+
[role="screenshot"]
11+
image::images/otel-waterfall-instrumented-without-http.jpg[alt="Distributed trace with Elasticsearch spans",align="center"]
12+
13+
Usually, OpenTelemetry agents and auto-instrumentation modules come with instrumentation support for HTTP-level communication. In this case, in addition to the logical Elasticsearch client requests, spans will be captured for the physical HTTP requests emitted by the client. The following image shows a trace with both, Elasticsearch spans (in blue) and the corresponding HTTP-level spans (in red):
14+
15+
[role="screenshot"]
16+
image::images/otel-waterfall-instrumented.jpg[alt="Distributed trace with Elasticsearch and HTTP spans",align="center"]
17+
18+
Advanced Java API Client behavior such as nodes round-robin and request retries are revealed through the combination of logical Elasticsearch spans and the physical HTTP spans. The following example shows an `index` request in a scenario with two Elasticsearch nodes:
19+
20+
[role="screenshot"]
21+
image::images/otel-waterfall-retries.jpg[alt="Distributed trace with request retries",align="center"]
22+
23+
The first node is unavailable and results in an HTTP error, while the retry to the second node succeeds. Both HTTP requests are subsumed by the logical Elasticsearch request span (in blue).
24+
25+
[discrete]
26+
==== Setup the OpenTelemetry instrumentation
27+
When using the https://opentelemetry.io/docs/instrumentation/java/manual[OpenTelemetry Java SDK manually] or using the https://opentelemetry.io/docs/instrumentation/java/automatic/[OpenTelemetry Java Agent], the Java API Client's OpenTelemetry instrumentation is enabled by default and uses the _globally_ registered OpenTelemetry SDK instance (i.e. `GlobalOpenTelemetry`). So, if you don't use a custom, local OpenTelemetry SDK instance, there is no explicit setup required to use the Java API Client's OpenTelemetry instrumentation.
28+
29+
[discrete]
30+
===== Using a custom OpenTelemetry instance
31+
In case you are using https://opentelemetry.io/docs/instrumentation/java/manual/#example[manual OpenTelemetry instrumentation] with a custom OpenTelemetry SDK instance that is _not registered globally_, you can create the Java API Client using a custom OpenTelemetry instance. The following code snippet shows an example of using a custom OpenTelemetry instance.
32+
33+
["source","java"]
34+
--------------------------------------------------
35+
include-tagged::{doc-tests-src}/getting_started/ConnectingTest.java[create-client-otel]
36+
--------------------------------------------------
37+
38+
[discrete]
39+
==== Configuring the OpenTelemetry instrumentation
40+
41+
You can configure the OpenTelemetry instrumentation either through Java System properties or Environment Variables.
42+
The following configuration options are available.
43+
44+
[discrete]
45+
[[opentelemetry-config-enable]]
46+
===== Enable / Disable the OpenTelemetry instrumentation
47+
48+
With this configuration option you can enable (default) or disable the built-in OpenTelemetry instrumentation.
49+
50+
**Default:** `true`
51+
52+
|============
53+
| Java System Property | `otel.instrumentation.elasticsearch.enabled`
54+
| Environment Variable | `OTEL_INSTRUMENTATION_ELASTICSEARCH_ENABLED`
55+
|============
56+
57+
[discrete]
58+
===== Capture search request bodies
59+
60+
Per default, the built-in OpenTelemetry instrumentation does not capture request bodies because of data privacy reasons. You can use this option to enable capturing of search queries from the the request bodies of Elasticsearch search requests in case you wish to capture this information, regardless.
61+
62+
**Default:** `false`
63+
64+
|============
65+
| Java System Property | `otel.instrumentation.elasticsearch.capture-search-query`
66+
| Environment Variable | `OTEL_INSTRUMENTATION_ELASTICSEARCH_CAPTURE_SEARCH_QUERY`
67+
|============
68+
69+
[discrete]
70+
==== Overhead
71+
The OpenTelemetry instrumentation (as any other monitoring approach) may come with a little overhead on CPU, memory and/or latency. The overhead may only occur when the instrumentation is enabled (default) and an OpenTelemetry SDK (or an OpenTelemetry Agent) is active in the target application. In case that either the instrumentation is disabled or no OpenTelemetry SDK (or OpenTelemetry Agent) is active with the target application, there is no monitoring overhead expected when using the client.
72+
73+
Even when the instrumentation is enabled and is being actively used (by an OpenTelemetry SDK), in the vast majority of cases the overhead is very small and negligible. In edge cases in which there is a noticable overhead the <<opentelemetry-config-enable,instrumentation can be explicitly disabled>> to eliminate any potential overhead effect of the instrumentation.

java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
2727
import co.elastic.clients.transport.ElasticsearchTransport;
2828
import co.elastic.clients.transport.TransportUtils;
29+
import co.elastic.clients.transport.instrumentation.OpenTelemetryForElasticsearch;
2930
import co.elastic.clients.transport.rest_client.RestClientTransport;
31+
import io.opentelemetry.api.OpenTelemetry;
32+
import io.opentelemetry.sdk.OpenTelemetrySdk;
3033
import org.apache.http.Header;
3134
import org.apache.http.HttpHost;
3235
import org.apache.http.auth.AuthScope;
@@ -82,6 +85,39 @@ public void createClient() throws Exception {
8285
//end::first-request
8386
}
8487

88+
@Disabled // we don't have a running ES
89+
@Test
90+
public void createClientWithOpenTelemetry() throws Exception {
91+
//tag::create-client-otel
92+
// URL and API key
93+
String serverUrl = "https://localhost:9200";
94+
String apiKey = "VnVhQ2ZHY0JDZGJrU...";
95+
96+
// Create the low-level client
97+
RestClient restClient = RestClient
98+
.builder(HttpHost.create(serverUrl))
99+
.setDefaultHeaders(new Header[]{
100+
new BasicHeader("Authorization", "ApiKey " + apiKey)
101+
})
102+
.build();
103+
// Create and configure custom OpenTelemetry instance
104+
OpenTelemetry customOtel = OpenTelemetrySdk.builder().build();
105+
106+
// Create Instrumentation instance using the custom OpenTelemetry instance
107+
// Second constructor argument allows to enable/disable search body capturing
108+
OpenTelemetryForElasticsearch esOtelInstrumentation =
109+
new OpenTelemetryForElasticsearch(customOtel, false);
110+
111+
// Create the transport with the custom Instrumentation instance
112+
ElasticsearchTransport transport = new RestClientTransport(
113+
restClient, new JacksonJsonpMapper(), null, esOtelInstrumentation
114+
);
115+
116+
// And create the API client
117+
ElasticsearchClient esClient = new ElasticsearchClient(transport);
118+
//end::create-client-otel
119+
}
120+
85121
@Disabled // we don't have a running ES
86122
@Test
87123
public void createSecureClientCert() throws Exception {

0 commit comments

Comments
 (0)