Skip to content

Use configured Redis targets for Jedis 3.x telemetry - #20071

Draft
trask wants to merge 25 commits into
mainfrom
trask-redis-jedis-3-targets
Draft

Use configured Redis targets for Jedis 3.x telemetry#20071
trask wants to merge 25 commits into
mainfrom
trask-redis-jedis-3-targets

Conversation

@trask

@trask trask commented Sep 10, 2026

Copy link
Copy Markdown
Member

Updates stable Jedis 3.x telemetry to report the Redis target configured by the application instead of the endpoint selected for each command. This applies to direct, pooled, sharded, cluster, and Sentinel clients, including span names and database client duration metrics.

Legacy telemetry continues to report the selected endpoint. Multi-endpoint targets keep shard order, sort cluster and Sentinel endpoints, and include at most five endpoints.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Sep 10, 2026

Copy link
Copy Markdown

Pull request dashboard status

Waiting on the author · refreshed 2026-09-12 03:43 UTC

Move out of draft to request review.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The broad Set VirtualField carrier should be narrowed, and normal cluster-command propagation lacks coverage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds configured logical Redis targets to Jedis 3.x telemetry while preserving legacy selected-endpoint behavior.

Changes:

  • Propagates configured targets through connections, pools, shards, clusters, and Sentinel clients.
  • Uses shared target normalization and ordering utilities.
  • Adds integration and unit coverage plus a dedicated unit-test module.
File summaries
File Description
settings.gradle.kts Registers the unit-test module.
ShardedJedis30ClientTest.java Tests configured shard targets.
JedisAggregateTargetTest.java Tests Sentinel and cluster refresh targets.
Jedis30ClientTest.java Adds pooled-client coverage.
ShardedRoutingInstrumentation.java Propagates targets during shard selection.
ShardedJedisInstrumentation.java Captures shard configuration.
PoolResourceInstrumentation.java Transfers pool targets to resources.
JedisSingletons.java Manages target state and scopes.
JedisServerTargets.java Builds normalized Redis targets.
JedisSentinelPoolInstrumentation.java Captures Sentinel configuration and lifecycle.
JedisInstrumentationModule.java Registers new instrumentations.
JedisDbAttributesGetter.java Emits configured stable server attributes.
JedisConnectionInstrumentation.java Captures and refreshes connection targets.
JedisClusterInstrumentation.java Propagates cluster seed targets.
JedisSingletonsTest.java Tests target replacement and scoping.
JedisServerTargetsTest.java Tests rendering, ordering, and validation.
javaagent-unit-tests/build.gradle.kts Configures focused unit tests.
Review details
  • Files reviewed: 17/17 changed files
  • Comments generated: 2
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

trask and others added 2 commits September 9, 2026 21:13
Copilot comment:

[Javaagent] Using the ubiquitous JDK `Set` interface as the carrier registers this virtual field against every concrete `Set` implementation, not just Jedis' temporary parsed-sentinel sets. That unnecessarily broadens class matching/field injection to unrelated application and JDK collection classes. Please derive the target from the parsed sentinels or carry it on a narrow Jedis carrier such as the pool/listener instead.

Analysis: JedisServerTargets.ofSentinels already accepts the parsed HostAndPort values. The initSentinels advice can derive the same normalized and sorted target from those values without attaching state to Set instances.

Upsides: This removes virtual-field registration from unrelated Set implementations and deletes the parse-result bookkeeping.

Downsides: The constructor and initSentinels paths normalize equivalent configured and parsed inputs independently. No material behavior change is expected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot comment:

[Testing] The new cluster test invokes only `renewSlotCache`, which is covered by `RenewSlotCacheAdvice`; it never sends a normal command through `getConnection`/`getConnectionFromSlot`. This advice and its target attachment could therefore stop working while the suite remains green. Add a `SET` or `GET` through `JedisCluster` and assert the configured stable target/span name (and the unchanged legacy endpoint).

Analysis: The test now sends SET through JedisCluster before renewing the slot cache. It checks the aggregate configured target in the stable span name and server attributes, and checks the announced Redis node in legacy mode.

Upsides: The test now covers getConnection target propagation and protects both stable and legacy behavior.

Downsides: The test sends one extra Redis command and makes three additional span assertions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The configured-target propagation is consistent with the stated semantics and is covered across the supported client paths.

Review details
  • Files reviewed: 17/17 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

trask and others added 3 commits September 9, 2026 22:11
Review finding:

This new test class carries `@SuppressWarnings("deprecation") // using deprecated semconv`, but it uses no deprecated API. Its only semconv imports are the stable `io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS` and `SERVER_PORT`, plus `SemconvStability.emitStableDatabaseSemconv()`, which is not deprecated. `InstrumentationExtension.spans()`, `AutoCleanupExtension`, `SpanData`, and the Testcontainers APIs it uses are not deprecated either. The sibling class this PR adds, `ShardedJedis30ClientTest`, does import deprecated `DbIncubatingAttributes.DB_OPERATION`, `DB_STATEMENT`, and `DB_SYSTEM`, so its identical suppression is warranted and this one was copied along with it. `.github/instructions/java-style.instructions.md` says to add a deprecation suppression "only for intentional use of an API verified to be deprecated", and the repository review instructions say to place `@SuppressWarnings` on the single member that needs it rather than the class. Fix: delete the annotation and its comment from `JedisAggregateTargetTest`.

Analysis: JedisAggregateTargetTest asserts only against the stable server.address and server.port keys, so it never touches the deprecated incubating DB attributes that force a suppression on the other Jedis tests. Every remaining API it uses was checked against the managed dependency versions and none is deprecated: semconv 1.43.0 ServerAttributes, SDK 1.65.0 SpanData and Attributes, Testcontainers 2.0.5 GenericContainer and Wait, Awaitility 4.3.0, AssertJ 3.27.7, and the JUnit 5 annotations. The build disables javac deprecation diagnostics with -Xlint:-deprecation and relies on an Error Prone check that only reports symbols actually marked deprecated, so removing the annotation produces no diagnostic and no behavior change.

Upsides: The class no longer claims a deprecated-API dependency it does not have, so a reader can trust the annotation on ShardedJedis30ClientTest to mean what it says. A later change that does introduce a deprecated call now has to opt in deliberately instead of inheriting a class-wide suppression.

Downsides: No material downside identified.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Failing check:

build / common / test2: JedisClusterException: CLUSTERDOWN The cluster is down

Cause: The test assigned all slots and created the client before Redis reported the single-node cluster as healthy.

Fix: Poll CLUSTER INFO until cluster_state is ok before constructing JedisCluster.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Failing check:

build / test-latest-deps / testLatestDeps2: expected: "localhost:34279/mymaster" but was: "10.1.0.46:34279/mymaster"

Cause: Jedis 3.9 resolves configured Sentinel hostnames before initSentinels, so the advice replaced the original endpoint with the resolved IP address.

Fix: Associate the parsed Sentinel set with the configured set and use that configured set when assigning the pool target.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@trask trask changed the title Add configured Redis targets for Jedis 3.x Use configured Redis targets for Jedis 3.x telemetry Sep 10, 2026
@trask
trask requested a balanced review from Copilot September 10, 2026 08:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Broad Set instrumentation remains and one cluster pool-propagation path lacks coverage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 17/17 changed files
  • Comments generated: 2
  • Review effort level: Balanced

trask and others added 2 commits September 10, 2026 01:39
Copilot comment:

The cluster integration test exercises `getConnection` and `renewSlotCache`, but never calls `getNodes` or borrows a resource from one of its returned pools. Consequently, this target-propagation path can regress while all new tests still pass. Add a test that obtains a pool through `JedisCluster#getClusterNodes`, executes a command on a borrowed Jedis instance, and verifies the aggregate stable target plus the selected legacy endpoint.

Analysis: The new test gets the selected node pool from `JedisCluster#getClusterNodes`, borrows a Jedis resource, and runs `SET`. It checks the aggregate configured target in stable mode and the selected node endpoint in legacy mode.

Upsides: The test now covers `GetNodesAdvice`, pool target propagation, and resource borrowing as one end-to-end path.

Downsides: The test runs one more Redis command against the existing cluster fixture.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot comment:

[Javaagent] The current diff still keys a `VirtualField` by the ubiquitous `Set` interface, so the agent must consider unrelated application/JDK `Set` implementations for context-store transformation. Keep this state on a Jedis-specific carrier, or derive the normalized target directly from the parsed sentinel values, rather than attaching it to the temporary set.

Analysis: Each parsed `HostAndPort` now carries the original configured Sentinel collection. The target lookup reads that state from the Jedis-specific parsed values instead of registering a virtual field for every `Set` implementation.

Upsides: Context-store transformation is limited to Jedis `HostAndPort` instances while configured hostnames still survive Jedis 3.9 address resolution.

Downsides: The small configured-endpoint snapshot is attached to each parsed Sentinel address instead of once to the containing set.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Target propagation spans several version-sensitive Byte Buddy paths and Redis client topologies, warranting final human validation.

Review details
  • Files reviewed: 17/17 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

trask and others added 5 commits September 10, 2026 16:16
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@trask
trask marked this pull request as ready for review September 11, 2026 02:04
@trask
trask requested a review from a team as a code owner September 11, 2026 02:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Connections created by pool prefill or min-idle maintenance can still report selected endpoints in stable telemetry.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 18/18 changed files
  • Comments generated: 1
  • Review effort level: Balanced

trask and others added 7 commits September 10, 2026 20:25
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@trask
trask marked this pull request as draft September 11, 2026 05:44
Copilot AI and others added 5 commits September 11, 2026 22:46
Co-authored-by: trask <218610+trask@users.noreply.github.com>
Co-authored-by: trask <218610+trask@users.noreply.github.com>
Co-authored-by: trask <218610+trask@users.noreply.github.com>
Co-authored-by: trask <218610+trask@users.noreply.github.com>
…nections

Copilot comment:

[General] This scope only covers the borrow itself, so it does not repair a pooled connection created outside `getResource()` (for example via `Pool.addObjects()` or Commons Pool's min-idle maintenance). Such a connection captures the selected node in its constructor; after this scope closes, normal commands on the returned Jedis still report that node instead of the configured cluster/Sentinel target in stable mode. Persist the pool target onto every returned Jedis connection before closing the scope, and ensure background factory-created setup commands receive the same target; add an eager/min-idle pool case to the integration tests.

Analysis: The borrow scope supplied the configured target only while Commons Pool returned a resource. A connection that the min-idle thread created earlier retained its node target, and setup commands created outside the borrow had no configured target. The pool now binds its factory to the configured target, scopes factory lifecycle calls, and stores the pool target on each borrowed Jedis connection before closing the scope.

Upsides: Stable database semantic conventions now report the configured cluster or Sentinel target for eager connections, background setup commands, and later commands on borrowed clients. Legacy attributes keep reporting the connected node.

Downsides: The instrumentation adds two per-object target associations and wraps configured Jedis factory lifecycle calls in a context scope.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Broad bytecode instrumentation across several asynchronous and pooled Jedis lifecycle paths warrants final human review despite strong targeted coverage.

Review details
  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants