Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@

package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v5_0;

import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableDatabaseSemconv;
import static io.opentelemetry.instrumentation.testing.junit.db.DbClientMetricsTestUtil.assertDurationMetric;
import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable;
import static io.opentelemetry.instrumentation.testing.junit.service.SemconvServiceStabilityUtil.maybeStablePeerService;
import static io.opentelemetry.instrumentation.testing.util.TestLatestDeps.testLatestDeps;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.semconv.DbAttributes.DB_OPERATION_NAME;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_RESPONSE_STATUS_CODE;
import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_PROTOCOL_VERSION;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT;
import static io.opentelemetry.semconv.UrlAttributes.URL_FULL;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM_NAME;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.ELASTICSEARCH;
Expand Down Expand Up @@ -99,11 +102,14 @@ void elasticsearchStatus() throws IOException {
trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName("GET")
span.hasName(emitStableDatabaseSemconv() ? "cluster.health" : "GET")
.hasKind(SpanKind.CLIENT)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), ELASTICSEARCH),
equalTo(
maybeStable(DB_OPERATION),
emitStableDatabaseSemconv() ? "cluster.health" : null),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_ADDRESS, httpHost.getHostName()),
equalTo(SERVER_PORT, httpHost.getPort()),
Expand All @@ -125,6 +131,7 @@ void elasticsearchStatus() throws IOException {
testing,
"io.opentelemetry.elasticsearch-rest-5.0",
DB_SYSTEM_NAME,
DB_OPERATION_NAME,
SERVER_ADDRESS,
SERVER_PORT);
}
Expand Down Expand Up @@ -174,11 +181,14 @@ public void onFailure(Exception e) {
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
span.hasName("GET")
span.hasName(emitStableDatabaseSemconv() ? "cluster.health" : "GET")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), ELASTICSEARCH),
equalTo(
maybeStable(DB_OPERATION),
emitStableDatabaseSemconv() ? "cluster.health" : null),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_ADDRESS, httpHost.getHostName()),
equalTo(SERVER_PORT, httpHost.getPort()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@

package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v6_4;

import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableDatabaseSemconv;
import static io.opentelemetry.instrumentation.testing.junit.db.DbClientMetricsTestUtil.assertDurationMetric;
import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable;
import static io.opentelemetry.instrumentation.testing.junit.service.SemconvServiceStabilityUtil.maybeStablePeerService;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.semconv.DbAttributes.DB_OPERATION_NAME;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_RESPONSE_STATUS_CODE;
import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_PROTOCOL_VERSION;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT;
import static io.opentelemetry.semconv.UrlAttributes.URL_FULL;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM_NAME;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.ELASTICSEARCH;
Expand Down Expand Up @@ -93,11 +96,14 @@ void elasticsearchStatus() throws IOException {
trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName("GET")
span.hasName(emitStableDatabaseSemconv() ? "cluster.health" : "GET")
.hasKind(SpanKind.CLIENT)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), ELASTICSEARCH),
equalTo(
maybeStable(DB_OPERATION),
emitStableDatabaseSemconv() ? "cluster.health" : null),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_ADDRESS, httpHost.getHostName()),
equalTo(SERVER_PORT, httpHost.getPort()),
Expand All @@ -119,6 +125,7 @@ void elasticsearchStatus() throws IOException {
testing,
"io.opentelemetry.elasticsearch-rest-6.4",
DB_SYSTEM_NAME,
DB_OPERATION_NAME,
SERVER_ADDRESS,
SERVER_PORT);
}
Expand Down Expand Up @@ -168,11 +175,14 @@ public void onFailure(Exception e) {
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
span.hasName("GET")
span.hasName(emitStableDatabaseSemconv() ? "cluster.health" : "GET")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), ELASTICSEARCH),
equalTo(
maybeStable(DB_OPERATION),
emitStableDatabaseSemconv() ? "cluster.health" : null),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_ADDRESS, httpHost.getHostName()),
equalTo(SERVER_PORT, httpHost.getPort()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@

package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v7_0;

import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableDatabaseSemconv;
import static io.opentelemetry.instrumentation.testing.GlobalTraceUtil.runWithSpan;
import static io.opentelemetry.instrumentation.testing.junit.db.DbClientMetricsTestUtil.assertDurationMetric;
import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable;
import static io.opentelemetry.instrumentation.testing.junit.service.SemconvServiceStabilityUtil.maybeStablePeerService;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.semconv.DbAttributes.DB_OPERATION_NAME;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_RESPONSE_STATUS_CODE;
import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_PROTOCOL_VERSION;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT;
import static io.opentelemetry.semconv.UrlAttributes.URL_FULL;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM_NAME;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.ELASTICSEARCH;
Expand Down Expand Up @@ -90,11 +93,14 @@ void elasticsearchStatus() throws IOException {
trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName("GET")
span.hasName(emitStableDatabaseSemconv() ? "cluster.health" : "GET")
.hasKind(SpanKind.CLIENT)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), ELASTICSEARCH),
equalTo(
maybeStable(DB_OPERATION),
emitStableDatabaseSemconv() ? "cluster.health" : null),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_ADDRESS, httpHost.getHostName()),
equalTo(SERVER_PORT, httpHost.getPort()),
Expand All @@ -116,6 +122,7 @@ void elasticsearchStatus() throws IOException {
testing,
"io.opentelemetry.elasticsearch-rest-7.0",
DB_SYSTEM_NAME,
DB_OPERATION_NAME,
SERVER_ADDRESS,
SERVER_PORT);
}
Expand Down Expand Up @@ -166,11 +173,14 @@ public void onFailure(Exception e) {
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
span.hasName("GET")
span.hasName(emitStableDatabaseSemconv() ? "cluster.health" : "GET")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), ELASTICSEARCH),
equalTo(
maybeStable(DB_OPERATION),
emitStableDatabaseSemconv() ? "cluster.health" : null),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_ADDRESS, httpHost.getHostName()),
equalTo(SERVER_PORT, httpHost.getPort()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@

package io.opentelemetry.instrumentation.elasticsearch.rest.v7_0;

import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableDatabaseSemconv;
import static io.opentelemetry.instrumentation.testing.GlobalTraceUtil.runWithSpan;
import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT;
import static io.opentelemetry.semconv.UrlAttributes.URL_FULL;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.ELASTICSEARCH;
import static java.util.concurrent.TimeUnit.SECONDS;
Expand Down Expand Up @@ -87,11 +89,14 @@ void elasticsearchStatus() throws IOException {
trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName("GET")
span.hasName(emitStableDatabaseSemconv() ? "cluster.health" : "GET")
.hasKind(SpanKind.CLIENT)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), ELASTICSEARCH),
equalTo(
maybeStable(DB_OPERATION),
emitStableDatabaseSemconv() ? "cluster.health" : null),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_ADDRESS, httpHost.getHostName()),
equalTo(SERVER_PORT, httpHost.getPort()),
Expand Down Expand Up @@ -143,11 +148,14 @@ public void onFailure(Exception e) {
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span ->
span.hasName("GET")
span.hasName(emitStableDatabaseSemconv() ? "cluster.health" : "GET")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
equalTo(maybeStable(DB_SYSTEM), ELASTICSEARCH),
equalTo(
maybeStable(DB_OPERATION),
emitStableDatabaseSemconv() ? "cluster.health" : null),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_ADDRESS, httpHost.getHostName()),
equalTo(SERVER_PORT, httpHost.getPort()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,139 @@ public String getDbQueryText(ElasticsearchRestRequest request) {
@Override
@Nullable
public String getDbOperationName(ElasticsearchRestRequest request) {
ElasticsearchEndpointDefinition endpointDefinition = request.getEndpointDefinition();
if (endpointDefinition != null) {
return endpointDefinition.getEndpointName();
}
return inferOperationName(request.getMethod(), request.getEndpoint());
}

@Deprecated // to be removed in 3.0
@Override
@Nullable
public String getDbOperation(ElasticsearchRestRequest request) {
ElasticsearchEndpointDefinition endpointDefinition = request.getEndpointDefinition();
return endpointDefinition != null ? endpointDefinition.getEndpointName() : null;
}

@Nullable
static String inferOperationName(String method, String endpoint) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

closing this PR, this is still not aligned with https://github.com/open-telemetry/semantic-conventions/blob/main/docs/db/elasticsearch.md, I think better not to emit than to make up heuristic here

int end = endpoint.indexOf('?');
if (end < 0) {
end = endpoint.length();
}

int start = 0;
if (start < end && endpoint.charAt(start) == '/') {
// low-level REST client endpoints conventionally start with a single leading slash
start++;
}

// Only the first three path segments are needed to infer the operation name, so extract them
// in a single pass instead of allocating an array for the whole path on this hot path.
String segment0 = null;
String segment1 = null;
String segment2 = null;
int segmentStart = start;
int found = 0;
for (int i = start; i <= end && found < 3; i++) {
if (i == end || endpoint.charAt(i) == '/') {
String segment = endpoint.substring(segmentStart, i);
switch (found++) {
case 0:
segment0 = segment;
break;
case 1:
segment1 = segment;
break;
default:
segment2 = segment;
break;
}
segmentStart = i + 1;
}
}

if (segment0 == null || segment0.isEmpty()) {
return null;
}
if (segment0.startsWith("_")) {
return inferOperationNameFromApiSegments(method, segment0, segment1);
}
if (segment1 != null && segment1.startsWith("_")) {
return inferOperationNameFromApiSegments(method, segment1, segment2);
}
return null;
}

@Nullable
private static String inferOperationNameFromApiSegments(
String method, String apiSegmentRaw, @Nullable String nextSegment) {
String apiSegment = stripLeadingUnderscores(apiSegmentRaw);
if (apiSegment.isEmpty()) {
return null;
}
String documentOperation = inferDocumentOperationName(method, apiSegment);
if (documentOperation != null) {
return documentOperation;
}
if (isGroupedApi(apiSegment)
&& nextSegment != null
&& !nextSegment.isEmpty()
&& !nextSegment.startsWith("_")) {
return apiSegment + "." + nextSegment;
}
return apiSegment;
}

@Nullable
private static String inferDocumentOperationName(String method, String apiSegment) {
switch (apiSegment) {
case "create":
case "update":
return apiSegment;
case "doc":
return inferDocOperationName(method);
default:
return null;
}
}

@Nullable
private static String inferDocOperationName(String method) {
switch (method) {
case "DELETE":
return "delete";
case "GET":
return "get";
case "POST":
case "PUT":
return "index";
default:
return null;
}
}

private static boolean isGroupedApi(String apiSegment) {
switch (apiSegment) {
case "cat":
case "cluster":
case "nodes":
case "snapshot":
case "tasks":
return true;
default:
return false;
}
}

private static String stripLeadingUnderscores(String value) {
while (value.startsWith("_")) {
value = value.substring(1);
}
return value;
}

@Override
@Nullable
public String getErrorType(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package io.opentelemetry.instrumentation.elasticsearch.rest.common.v5_0.internal;

import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableDatabaseSemconv;

import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;

/**
Expand All @@ -19,9 +21,13 @@ final class ElasticsearchSpanNameExtractor implements SpanNameExtractor<Elastics
this.dbAttributesGetter = dbAttributesGetter;
}

@SuppressWarnings("deprecation") // getDbOperation is used for old semconv span names
@Override
public String extract(ElasticsearchRestRequest elasticsearchRestRequest) {
String name = dbAttributesGetter.getDbOperationName(elasticsearchRestRequest);
String name =
emitStableDatabaseSemconv()
? dbAttributesGetter.getDbOperationName(elasticsearchRestRequest)
: dbAttributesGetter.getDbOperation(elasticsearchRestRequest);
return name != null ? name : elasticsearchRestRequest.getMethod();
}
}
Loading
Loading