Conversation
Agent-Logs-Url: https://github.com/Open-J-Proxy/ojp/sessions/34dc81e6-214b-4343-97de-cc15a14fc6be Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Open-J-Proxy/ojp/sessions/38f43dd6-4ed9-40cf-bf77-2336673b960c Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Added Appendix §9 to
|
|
@copilot lets go with Option C, create the ADR and start implementing it. |
Agent-Logs-Url: https://github.com/Open-J-Proxy/ojp/sessions/e39bc249-cc2d-49b2-b1aa-467b95a1d1e5 Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
…rivate Agent-Logs-Url: https://github.com/Open-J-Proxy/ojp/sessions/e39bc249-cc2d-49b2-b1aa-467b95a1d1e5 Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Done — ADR + Phase 1 landed. ADR-010 ( Phase 1 implementation in
MBean attributes exposed: Validation: new tests Deferred to a follow-up PR per ADR-010: the separate Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Agent-Logs-Url: https://github.com/Open-J-Proxy/ojp/sessions/dfef0f70-9cde-4c40-b7c2-bb7e4c2b0e57 Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
No — Phase 1 was done, Phase 2 was deferred. Now landed in 2f747bf. Phase 2: What changed:
Validation: How to use: add the adapter jar to the application classpath and start the JVM with ADR-010 updated to mark both phases as implemented. The server-side Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
…symmetry Agent-Logs-Url: https://github.com/Open-J-Proxy/ojp/sessions/f5f42e3b-120c-4c80-87f0-36bb5160487d Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Did the audit end-to-end (
Validation: full driver suite passes (1028 tests), adapter suite passes (9 tests), checkstyle clean on both modules, CodeQL 0 alerts. Added regression test Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Agent-Logs-Url: https://github.com/Open-J-Proxy/ojp/sessions/f5f42e3b-120c-4c80-87f0-36bb5160487d Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
|



Summary
Lands the throttling-metrics analysis, an ADR adopting the hybrid (JMX core + opt-in OpenTelemetry adapter) approach for the JDBC driver, and both phases of that approach: Phase 1 (JMX in
ojp-jdbc-driver, no new runtime deps) and Phase 2 (the separately publishedojp-jdbc-driver-otel-metricsadapter module).Server-side
ojp.throttle.*metrics (gRPC interceptor +SlotManager) remain analysis-only in this PR and will be implemented in follow-up PRs per the rollout in §7 of the analysis document.What this PR adds
Documentation
documents/analysis/THROTTLING_METRICS_ANALYSIS.md— full analysis covering:ConcurrencyThrottleInterceptor,SlotManager,ClientThrottleManager) and the observability gap in eachojp.throttle.*OpenTelemetry meter scope, following the existingojp.sql/ojp.*.poolconvention (interface + OTel impl + NoOp + factory)SlotManagerper datasource × lane (slots total/active/available/utilization, queue depth/max, acquired/rejected counters withpathandreason, wait time histogram, borrowed gauge, observedPeak, enabled)ojp-jdbc-driver-otel-metricsadapter jar, mirroring HikariCP's pattern), a comparison table, recommendation with ~80% confidence, and conditions that would change the recommendation.documents/analysis/README.md— link to the new analysis under "Latest Analysis".documents/ADRs/adr-010-hybrid-jmx-otel-driver-metrics.md— records the decision to adopt the hybrid approach (Option C), with scope, configuration (ojp.jdbc.metricssystem property), neglected options, accepted trade-offs, and a two-phase rollout (both phases now marked as implemented).Phase 1 implementation (
ojp-jdbc-driver, no new runtime deps)New package
org.openjproxy.jdbc.metrics:ClientThrottleMetrics— small sink interface withLimitChangeDirectionenum (mirrors the server'sSqlStatementMetricspattern).NoOpClientThrottleMetrics— singleton.ClientThrottleMetricsMXBean+JmxClientThrottleMetrics— registers one MBean perconnHashunderorg.openjproxy:type=ClientThrottle,connHash=<hash>. Best-effort registration (warns and degrades gracefully onSecurityManagerdenial / duplicate name), idempotentclose().ClientThrottleStateProvider— read-only snapshot interface so the MBean doesn't importClientThrottleManager.ClientThrottleMetricsProvider—ServiceLoaderSPI used by the factory to discover non-built-in bindings (e.g. the Phase 2 OTel adapter).ClientThrottleMetricsFactory— selects the implementation from theojp.jdbc.metricssystem property. Built-ins (jmxdefault,none) are hard-wired; other values (e.g.otel) are resolved viaServiceLoader. Falls back to JMX with a single WARN when the requested provider is not on the classpath.Wiring:
ClientThrottleManagergainssetMetrics(...)and records on acquire / reject / server-overload / AIMD limit-change.ClientThrottleManager.tryAcquire(...)now increments theinFlightcounter on the unlimited path (effectiveLimit == Integer.MAX_VALUE) too, keeping it symmetric withrelease()so the JMXInFlightattribute and the OTelojp.client.throttle.inflightgauge reflect concurrent driver load from the first request — not only once throttling kicks in.Connection.createThrottleManager(...)creates one metrics instance perconnHash; the throttle mode is snapshotted to avoid the state provider pinning the firstConnection.MBean attributes exposed:
ConnHash,Mode,InFlight,ProactiveLimit,ReactiveLimit,EffectiveLimit,AcquiredTotal,RejectedTotal,ServerOverloadEventsTotal,LimitIncreaseTotal,LimitDecreaseTotal.Phase 2 implementation —
ojp-jdbc-driver-otel-metricsadapter moduleNew Maven module registered in the parent
pom.xml. The driver core gains zero new runtime dependencies; only this opt-in module depends on OpenTelemetry.opentelemetry-apiis declared withprovidedscope so the host application controls the OTel version (avoids the classpath-conflict / version-skew risk called out in Appendix §9).OpenTelemetryClientThrottleMetricspublishes meter scopeojp.client.throttlewith attributeojp.connection.hash:ojp.client.throttle.inflight,ojp.client.throttle.limit.proactive,ojp.client.throttle.limit.reactive,ojp.client.throttle.limit.effective. The driver'sInteger.MAX_VALUE"no limit" sentinel is saturated to 0 so dashboards don't show a 2-billion bar before SessionInfo arrives.ojp.client.throttle.acquired.total,ojp.client.throttle.rejected.total,ojp.client.throttle.server.overload.total, andojp.client.throttle.limit.changes.totaltagged bydirection=increase|decrease.close()(guarded by avolatile boolean) unregisters the observable callbacks.GlobalOpenTelemetry.get()and gets back the no-op instance (no SDK registered — exactly the risk flagged in Appendix §9), the adapter logs a single WARN explaining how to register an SDK (OpenTelemetry Java agent,opentelemetry-sdk-extension-autoconfigure, or a manualGlobalOpenTelemetry.set(sdk)). Without this surfacing,-Dojp.jdbc.metrics=otelwould silently drop every counter and gauge.OpenTelemetryClientThrottleMetricsProviderregistered viaMETA-INF/services/org.openjproxy.jdbc.metrics.ClientThrottleMetricsProvider; usesGlobalOpenTelemetry.get()by default; returnsNoOpClientThrottleMetricsonNoClassDefFoundError/ unexpected failure so metrics never break JDBC functionality.Usage: drop the adapter jar on the application classpath and start the JVM with
-Dojp.jdbc.metrics=otel. Without the jar,jmx(Phase 1) remains the default and nothing changes.Tests
JmxClientThrottleMetricsTest— MBean registration, attribute reads, unregistration, duplicate-name tolerance.ClientThrottleMetricsFactoryTest— default,none,otel-fallback, and null-guard behaviour.ClientThrottleManagerMetricsIntegrationTest— end-to-end manager↔metrics counter recording, plusshouldTrackInFlightEvenWhenLimitIsUnlimitedregression test for the unlimited-pathinFlightsymmetry fix.OpenTelemetryClientThrottleMetricsTest— counter/gauge values, direction tagging,Integer.MAX_VALUEsaturation, double-close, null-arg validation (usesopentelemetry-sdk-testing+InMemoryMetricReader).OpenTelemetryClientThrottleMetricsProviderTest—ServiceLoaderdiscovery and provider name.FactorySelectsOtelWhenAdapterPresentTest— end-to-end factory selection of the OTel implementation when the adapter is on the classpath.ojp-jdbc-driverunit suite passes; new adapter module: 9 tests, 0 failures;mvn checkstyle:checkpasses for both modules; CodeQL: 0 alerts; GitHub Advisory DB: no advisories for OpenTelemetry 1.62.0 (API + SDK + SDK-testing).Open questions for reviewers
datasourceattribute identity (for the server-side metrics in the analysis). Use existingconnHashinitially, or invest in human-friendly names from the start?grpc.methodcardinality. ~10 RPC methods today; OK to use as a label onojp.throttle.grpc.*?ojp.sql.slow.executions.total. Lane attribution is proposed only on slot metrics; SQL metrics keep their existing shape — confirm this split.Deferred to follow-up PRs
ojp.throttle.*implementation (gRPC interceptor +SlotManagermetrics) per §7 of the analysis.