Skip to content

Commit

Permalink
OpenTelemetry: fix the Redis instrumenter in case of a tainted connec…
Browse files Browse the repository at this point in the history
…tion

The Vert.x Redis client does not always report the database instance number,
because sometimes, it simply isn't known. Specifically, that occurs when
the connection is tainted; for example, when a custom database is selected
using the `SELECT` command.

In this case, the trace simply will not include the dabatase instance number.
  • Loading branch information
Ladicek committed Jan 8, 2025
1 parent 757a4d4 commit 5589020
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,9 @@ public String peerAddress() {
return attributes.get(PEER_ADDRESS);
}

public long dbIndex() {
return Long.parseLong(attributes.get(DB_INSTANCE));
public Long dbIndex() {
String dbInstance = attributes.get(DB_INSTANCE);
return dbInstance != null ? Long.valueOf(dbInstance) : null;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,14 @@ public Uni<Void> getReactiveInvalidOperation() {
.replaceWithVoid();
}

// tainted
@GET
@Path("/tainted")
public String getTainted() {
ds.withConnection(conn -> {
conn.select(7); // taints the connection
conn.value(String.class).get("foobar");
});
return "OK";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.time.Duration;
import java.util.List;
Expand Down Expand Up @@ -195,6 +197,24 @@ public void reactiveInvalidOperation() {
checkForException(exception);
}

@Test
public void taintedConnection() {
RestAssured.get("redis/tainted")
.then()
.statusCode(200)
.body(CoreMatchers.is("OK"));

Awaitility.await().atMost(Duration.ofSeconds(10)).until(() -> getSpans().size() == 3);

Map<String, Object> span = findSpan(getSpans(), m -> SpanKind.CLIENT.name().equals(m.get("kind"))
&& "get".equals(m.get("name")));
Map<String, Object> attributes = (Map<String, Object>) span.get("attributes");

assertEquals("redis", attributes.get("db.system"));
assertEquals("get", attributes.get("db.operation"));
assertFalse(span.containsKey("db.redis.database_index"));
}

private List<Map<String, Object>> getSpans() {
return get("/opentelemetry/export").body().as(new TypeRef<>() {
});
Expand Down

0 comments on commit 5589020

Please sign in to comment.