diff --git a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DriverInstrumentation.java b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DriverInstrumentation.java index 2530f1bb25..95776808a4 100644 --- a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DriverInstrumentation.java +++ b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DriverInstrumentation.java @@ -58,7 +58,7 @@ public class DriverInstrumentation implements TypeInstrumentation { return; } DbInfo dbInfo = JdbcConnectionUrlParser.parse(url, props); - JdbcData.connectionInfo.set(connection, dbInfo); + JdbcData.connectionInfo.set(connection, JdbcData.intern(dbInfo)); } } } diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcData.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcData.java index 5bbafafb8d..8af7f0e764 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcData.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcData.java @@ -6,16 +6,42 @@ package io.opentelemetry.instrumentation.jdbc.internal; import io.opentelemetry.instrumentation.api.field.VirtualField; +import java.lang.ref.WeakReference; import java.sql.Connection; import java.sql.PreparedStatement; +import java.util.Map; +import java.util.WeakHashMap; /** Holds info associated with JDBC connections and prepared statements. */ public final class JdbcData { + private static final Map> dbInfos = new WeakHashMap<>(); public static VirtualField connectionInfo = VirtualField.find(Connection.class, DbInfo.class); public static VirtualField preparedStatement = VirtualField.find(PreparedStatement.class, String.class); private JdbcData() {} + + /** + * Returns canonical representation of db info. + * + * @param dbInfo db info to canonicalize + * @return db info with same content as input db info. If two equal inputs are given to this + * method, both calls will return the same instance. This method may return one instance now + * and a different instance later if the original interned instance was garbage collected. + */ + public static DbInfo intern(DbInfo dbInfo) { + synchronized (dbInfos) { + WeakReference reference = dbInfos.get(dbInfo); + if (reference != null) { + DbInfo result = reference.get(); + if (result != null) { + return result; + } + } + dbInfos.put(dbInfo, new WeakReference<>(dbInfo)); + return dbInfo; + } + } } diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcUtils.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcUtils.java index 731c8cec5d..20643270b8 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcUtils.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcUtils.java @@ -72,7 +72,7 @@ public final class JdbcUtils { DbInfo dbInfo = JdbcData.connectionInfo.get(connection); if (dbInfo == null) { dbInfo = computeDbInfo(connection); - JdbcData.connectionInfo.set(connection, dbInfo); + JdbcData.connectionInfo.set(connection, JdbcData.intern(dbInfo)); } return dbInfo; }