fix: optimize dataSourceName to resolve metrics high cardinality#19159
fix: optimize dataSourceName to resolve metrics high cardinality#19159YaoYingLong wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes a high-cardinality metrics issue in the c3p0-0.9 connection pool instrumentation. c3p0's PooledDataSource#getDataSourceName() falls back to a per-instance identityToken when a user does not explicitly call setDataSourceName(...). Using that token as pool.name / db.client.connection.pool.name produces high-cardinality metric attributes. The change detects this fallback and substitutes a stable, low-cardinality generated name (c3p0-N), while preserving explicitly configured names.
Changes:
- In
ConnectionPoolMetrics, resolve the pool name via a newgetPoolName(...)helper that keeps explicitdataSourceNamevalues but replaces the identity-token fallback with a generatedc3p0-Nname cached per data source. - Track generated names in a
generatedPoolNamesmap keyed by the identity-basedIdentityDataSourceKey, and clean it up inunregisterMetrics. - Update the shared abstract test to cover both the explicit
dataSourceNamecase and the generated-default-name case.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| instrumentation/c3p0-0.9/library/src/main/java/io/opentelemetry/instrumentation/c3p0/v0_9/ConnectionPoolMetrics.java | Adds getPoolName to detect the identity-token fallback and assign a stable generated name, with cleanup on unregister. |
| instrumentation/c3p0-0.9/testing/src/main/java/io/opentelemetry/instrumentation/c3p0/AbstractC3p0InstrumentationTest.java | Sets an explicit pool name in the existing test and adds a new test verifying the generated c3p0-N default name. |
I reviewed the pool-name resolution logic (null-check-before-equals avoids NPE; the fallback is reliably detected since getDataSourceName() returns exactly getIdentityToken() when unset), verified the two ConcurrentHashMaps use the same identity-based key and are both cleaned up on unregister, confirmed there is no nested same-map compute/computeIfAbsent hazard, and checked that the generated-name approach is consistent with sibling instrumentations (e.g. apache-dbcp's dbcp2-<id> fallback). The tests cover both code paths. I did not find substantive issues.
| String dataSourceName = dataSource.getDataSourceName(); | ||
| if (dataSourceName == null || dataSourceName.equals(dataSource.getIdentityToken())) { | ||
| return generatedPoolNames.computeIfAbsent( | ||
| key, unused -> DEFAULT_POOL_NAME + "-" + idGenerator.getAndIncrement()); |
There was a problem hiding this comment.
Pending the discussion in #19160 (comment), I think we should avoid process-local -N suffixes here. If no stable name exists, use a stable fallback and let duplicates merge so metric identities remain consistent across restarts.
Pull request dashboard statusStatus last refreshed: 2026-07-22 03:19:10 UTC.
This automated status or its linked feedback items may be incorrect. If something looks wrong, report it with the result you expected. |
Summary
Fix high-cardinality c3p0 connection pool metric attributes when
dataSourceNameis not explicitly configured.Previously, c3p0 metrics used
PooledDataSource#getDataSourceName()directly as the connection pool name. In c3p0, if users do not callsetDataSourceName(...), the underlyingdataSourceNameproperty remains unset, butgetDataSourceName()falls back togetIdentityToken(). That identity token is generated per data source instance and includes VM/object-identity based values, so using it aspool.name/db.client.connection.pool.namecan create high-cardinality metric attributes.This change keeps explicitly configured
dataSourceNamevalues unchanged, but replaces c3p0 identity-token fallback values with generated low-cardinality names likec3p0-1.Details
c3p0 documents
dataSourceNameas defaulting to either the named config name or an opaque identity token when no explicit name is set:https://www.mchange.com/projects/c3p0/#dataSourceName
The fallback behavior is implemented in
AbstractPoolBackedDataSource#getDataSourceName(), which returnsgetIdentityToken()when the storeddataSourceNameis null:https://github.com/swaldman/c3p0/blob/9084ab6577bb195672b8831d8fdbb9be22f76ebe/src/com/mchange/v2/c3p0/impl/AbstractPoolBackedDataSource.java#L1506-L1521
The identity token is generated by
C3P0ImplUtils.allocateIdentityToken(...)using VM/object-identity based values:https://github.com/swaldman/c3p0/blob/9084ab6577bb195672b8831d8fdbb9be22f76ebe/src/com/mchange/v2/c3p0/impl/C3P0ImplUtils.java#L1407-L1452
Changes
dataSourceNamevalues for connection pool metrics.dataSourceNameand unsetdataSourceNamecases.