diff --git a/ojdbc-provider-observability/pom.xml b/ojdbc-provider-observability/pom.xml
new file mode 100644
index 00000000..8a7601cb
--- /dev/null
+++ b/ojdbc-provider-observability/pom.xml
@@ -0,0 +1,73 @@
+
+
+ 4.0.0
+
+
+ com.oracle.database.jdbc
+ ojdbc-extensions
+ 1.0.3
+
+
+ Oracle JDBC Observability Provider
+ com.oracle.database.jdbc
+ ojdbc-provider-observability
+
+
+ 1.44.1
+ 11
+ 11
+
+
+
+
+ com.oracle.database.jdbc
+ ojdbc11
+
+
+ io.opentelemetry
+ opentelemetry-api
+ ${opentelemetry.version}
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ test
+
+
+ ojdbc-provider-common
+ com.oracle.database.jdbc
+ tests
+ test-jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ none
+ alphabetical
+
+
+
+
+
\ No newline at end of file
diff --git a/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityConfiguration.java b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityConfiguration.java
new file mode 100644
index 00000000..0fc81a11
--- /dev/null
+++ b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityConfiguration.java
@@ -0,0 +1,333 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
+
+import oracle.jdbc.provider.observability.tracers.ObservabilityTracer;
+import oracle.jdbc.provider.observability.tracers.jfr.JFRTracer;
+import oracle.jdbc.provider.observability.tracers.otel.OTelTracer;
+
+/**
+ *
+ * Implementation of {@link ObservabilityConfigurationMBean} that allows to
+ * configure the Oracle JDBC Observability Provider. The system properties that
+ * can be used to configure the Observability Provider depend on the provider
+ * used:
+ *
+ * If {@link ObservabilityTraceEventListenerProvider} is being used:
+ *
+ * - {@link ObservabilityConfiguration#ENABLED_TRACERS}: comma separated list
+ * of enabled tracers, default "JFR,OTEL"
+ * - {@link ObservabilityConfiguration#SENSITIVE_DATA_ENABLED}: true if
+ * sensitive data is enabled, default false
+ *
+ * If {@link OpenTelemetryTraceEventListenerProvider} is being used:
+ *
+ * - {@link ObservabilityConfiguration#OPEN_TELEMETRY_TRACE_EVENT_LISTENER_ENABLED}:
+ * true if OTEL tracer is enabled, otherwise false. Default true.
+ * - {@link ObservabilityConfiguration#OPEN_TELEMETRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED}:
+ * true if sensitive data is enabled, default false
+ *
+ */
+public class ObservabilityConfiguration implements ObservabilityConfigurationMBean {
+
+ /**
+ *
+ * System property used to enabled/disable tracers. The value of this system property should be a comma separated list
+ * of tracers to enable.
+ *
+ *
+ * This extension implements two tracers:
+ *
+ *
+ * - OTEL: which exports traces to Open Telemetry {@link OTelTracer}
+ * - JFR: which exports traces to Java Flight recorder {@link JFRTracer}
+ *
+ *
+ * By default all tracers will be enabled.
+ */
+ public static final String ENABLED_TRACERS = "oracle.jdbc.provider.observability.enabledTracers";
+
+ /**
+ * System property used to enable/disable exporting sensitive data. Set the property to true to enable sensitive data.
+ * By default exporting sensitive data is disabled.
+ */
+ public static final String SENSITIVE_DATA_ENABLED = "oracle.jdbc.provider.observability.sensitiveDataEnabled";
+
+ /**
+ * This property is kept for backward compatibility. It is used to enable/disable the previous verison of the provider:
+ * "open-telemetry-trace-event-listener-provider".
+ */
+ public static final String OPEN_TELEMETRY_TRACE_EVENT_LISTENER_ENABLED = "oracle.jdbc.provider.opentelemetry.enabled";
+
+ /**
+ * This property is kept for backward compatibility. It allows to enable/disable sensitive data when using the previous
+ * version of the provider: "open-telemetry-trace-event-listener-provider".
+ */
+ public static final String OPEN_TELEMETRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED = "oracle.jdbc.provider.opentelemetry.sensitive-enabled";
+
+ /**
+ * Default values
+ */
+ private static final String DEFAULT_ENABLED_TRACERS = "OTEL,JFR";
+ private static final String DEFAULT_SENSITIVE_DATA_ENABLED = "false";
+ private static final String DEFAULT_OPEN_TELEMETRY_ENABLED = "true";
+
+ /**
+ * Lock used to ensure that only one thread can access the configuration at a time.
+ */
+ private static final ReentrantLock observabilityConfigurationLock = new ReentrantLock();
+
+ /**
+ * Indicates whether traces are enabled
+ */
+ private boolean enabled = true;
+
+ /**
+ * Indicates whether sensitive data is enabled
+ */
+ private boolean sensitiveDataEnabled;
+
+ /**
+ * List of enabled tracers
+ */
+ private List enabledTracers = new ArrayList<>();
+
+ /**
+ * Maps registered tracer's name to its instance.
+ */
+ Map registeredTracers = new HashMap<>(2, 1);
+
+
+ /**
+ * Types of configuration. For backward compatibility allows to use OTEL for
+ * Oracle JDBC Open Telemetry Provider configuration properties.
+ */
+ public enum ObservabilityConfigurationType {
+ /**
+ * Use Oracle JDBC Open Telemetry Provider configuration properties
+ */
+ OTEL,
+ /**
+ * USE Oracle JDBC Observability Provider configuration properties
+ */
+ OBSERVABILITY
+ }
+
+ /**
+ * Constructor
+ */
+ public ObservabilityConfiguration() {
+ this(ObservabilityConfigurationType.OBSERVABILITY);
+ }
+
+ /**
+ * Constructor used by {@link ObservabilityTraceEventListener} to create a configuration.
+ *
+ * @param configurationType indicates which system properties to use. When
+ * {@link ObservabilityConfigurationType#OTEL}, the previous
+ * verison of system properties are used.
+ */
+ ObservabilityConfiguration(ObservabilityConfigurationType configurationType) {
+ String enabledTracers = DEFAULT_ENABLED_TRACERS;
+ String sensitiveDataEnabled = DEFAULT_SENSITIVE_DATA_ENABLED;
+ if (ObservabilityConfigurationType.OBSERVABILITY.equals(configurationType)) {
+ enabledTracers = System.getProperty(ENABLED_TRACERS, DEFAULT_ENABLED_TRACERS);
+ sensitiveDataEnabled = System.getProperty(SENSITIVE_DATA_ENABLED, DEFAULT_SENSITIVE_DATA_ENABLED);
+ } else {
+ String otelEnabled = System.getProperty(OPEN_TELEMETRY_TRACE_EVENT_LISTENER_ENABLED, DEFAULT_OPEN_TELEMETRY_ENABLED);
+ if (otelEnabled != null) {
+ enabledTracers = "OTEL";
+ this.enabled = Boolean.parseBoolean(otelEnabled);
+ }
+ String otelSensitiveDataEnabled = System.getProperty(OPEN_TELEMETRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED, DEFAULT_SENSITIVE_DATA_ENABLED);
+ if(otelSensitiveDataEnabled != null) {
+ sensitiveDataEnabled = otelSensitiveDataEnabled;
+ }
+ }
+
+ setEnabledTracers(enabledTracers);
+ setSensitiveDataEnabled(Boolean.parseBoolean(sensitiveDataEnabled));
+ }
+
+ /**
+ * Returns true if the provider is enabled, otherwise false.
+ *
+ * @return true if the provider is enabled, otherwise false.
+ */
+ @Override
+ public boolean getEnabled() {
+ observabilityConfigurationLock.lock();
+ try {
+ return enabled;
+ } finally {
+ observabilityConfigurationLock.unlock();
+ }
+ }
+
+ /**
+ * Enables/disables the provider.
+ *
+ * @param enabled true to enable the provider, otherwise false.
+ */
+ @Override
+ public void setEnabled(boolean enabled) {
+ observabilityConfigurationLock.lock();
+ try {
+ this.enabled = enabled;
+ } finally {
+ observabilityConfigurationLock.unlock();
+ }
+ }
+
+ /**
+ * Returns a comma separated list of enabled tracers. Not {@code null}.
+ */
+ @Override
+ public String getEnabledTracers() {
+ observabilityConfigurationLock.lock();
+ try {
+ return enabledTracers == null ?
+ "" :
+ enabledTracers.stream().collect(Collectors.joining(","));
+ } finally {
+ observabilityConfigurationLock.unlock();
+ }
+ }
+
+ /**
+ * Enables the tracers.
+ *
+ * This extension implements two tracers:
+ *
+ *
+ * - OTEL: which exports traces to Open Telemetry {@link OTelTracer}
+ * - JFR: which exports traces to Java Flight recorder {@link JFRTracer}
+ *
+ *
+ * Other tracer can be registered using the {@link ObservabilityConfiguration#registeredTracers}
+ * method.
+ *
+ * @param tracers comma separated list of enabled tracers.
+ */
+ @Override
+ public void setEnabledTracers(String tracers){
+ observabilityConfigurationLock.lock();
+ try {
+ String[] items = tracers.replaceAll("\\s", "").split(",");
+ enabledTracers = Arrays.asList(items);
+ } finally {
+ observabilityConfigurationLock.unlock();
+ }
+
+ }
+
+ /**
+ * Returns true if sensitive data is enabled, otherwise false.
+ * @return true if sensitive data is enabled, otherwise false.
+ */
+ @Override
+ public boolean getSensitiveDataEnabled() {
+ observabilityConfigurationLock.lock();
+ try {
+ return sensitiveDataEnabled;
+ } finally {
+ observabilityConfigurationLock.unlock();
+ }
+ }
+
+ /**
+ * Enables/disables sensitive data.
+ *
+ * @param sensitiveDataEnabled true to enable sensitive data, otherwise false.
+ */
+ @Override
+ public void setSensitiveDataEnabled(boolean sensitiveDataEnabled) {
+ observabilityConfigurationLock.lock();
+ try {
+ this.sensitiveDataEnabled = sensitiveDataEnabled;
+ } finally {
+ observabilityConfigurationLock.unlock();
+ }
+ }
+
+ /**
+ * Returns a list of enabled tracers.
+ * @return then list of enabled tracers.
+ */
+ public List getEnabledTracersAsList() {
+ observabilityConfigurationLock.lock();
+ try {
+ return enabledTracers;
+ } finally {
+ observabilityConfigurationLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the tracer registered with that name.
+ * @param tracerName the name of the tracer.
+ * @return returns the registered tracer that was registered using that name.
+ */
+ public ObservabilityTracer getTracer(String tracerName) {
+ return registeredTracers.get(tracerName);
+ }
+
+ /**
+ * Registeres a tracer.
+ *
+ * @param tracer the tracer to register
+ */
+ public void registerTracer(ObservabilityTracer tracer) {
+ observabilityConfigurationLock.lock();
+ try {
+ registeredTracers.put(tracer.getName(), tracer);
+ } finally {
+ observabilityConfigurationLock.unlock();
+ }
+ }
+
+
+}
diff --git a/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityConfigurationMBean.java b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityConfigurationMBean.java
new file mode 100644
index 00000000..f516dafa
--- /dev/null
+++ b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityConfigurationMBean.java
@@ -0,0 +1,96 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability;
+
+import oracle.jdbc.provider.observability.tracers.jfr.JFRTracer;
+import oracle.jdbc.provider.observability.tracers.otel.OTelTracer;
+
+/**
+ * MBean that allows to configure the Oracle JDBC Observability Provider.
+ */
+public interface ObservabilityConfigurationMBean {
+
+ /**
+ * Returns true if the provider is enabled, otherwise false.
+ *
+ * @return true if the provider is enabled, otherwise false.
+ */
+ boolean getEnabled();
+
+ /**
+ * Enables/disables the provider.
+ *
+ * @param enabled true to enable the provider, otherwise false.
+ */
+ void setEnabled(boolean enabled);
+
+ /**
+ * Returns a comma separated list of enabled tracers.
+ *
+ * @return a comma separated list of enabled tracers.
+ */
+ String getEnabledTracers();
+
+ /**
+ * Enables the tracers.
+ *
+ * This extension implements two tracers:
+ *
+ *
+ * - OTEL: which exports traces to Open Telemetry {@link OTelTracer}
+ * - JFR: which exports traces to Java Flight recorder {@link JFRTracer}
+ *
+ *
+ * @param tracers comma separated list of enabled tracers.
+ */
+ void setEnabledTracers(String tracers);
+
+ /**
+ * Returns true if sensitive data is enabled, otherwise false.
+ *
+ * @return true if sensitive data is enabled, otherwise false.
+ */
+ boolean getSensitiveDataEnabled();
+
+ /**
+ * Enables/disables sensitive data.
+ *
+ * @param sensitiveDataEnabled true to enable sensitive data, otherwise false.
+ */
+ void setSensitiveDataEnabled(boolean sensitiveDataEnabled);
+}
diff --git a/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityTraceEventListener.java b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityTraceEventListener.java
new file mode 100644
index 00000000..9fd33725
--- /dev/null
+++ b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityTraceEventListener.java
@@ -0,0 +1,275 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability;
+
+import java.lang.management.ManagementFactory;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+
+import oracle.jdbc.TraceEventListener;
+import oracle.jdbc.provider.observability.ObservabilityConfiguration.ObservabilityConfigurationType;
+import oracle.jdbc.provider.observability.tracers.ObservabilityTracer;
+import oracle.jdbc.provider.observability.tracers.jfr.JFRTracer;
+import oracle.jdbc.provider.observability.tracers.otel.OTelTracer;
+
+/**
+ *
+ * TraceEventListener implementation that receives notifications whenever events
+ * are generated in the driver and publishes these events different tracers
+ * depending on the configuration.
+ *
+ *
+ * These events include:
+ *
+ *
+ * - roundtrips to the database server
+ * - AC begin and success
+ * - VIP down event
+ *
+ *
+ * This extension implements two tracers:
+ *
+ *
+ * - OTEL: which exports traces to Open Telemetry
+ * - JFR: which exports traces to Java Flight recorder
+ *
+ *
+ * The {@link ObservabilityConfiguration} class allows to configure which tracers
+ * are enabled and whether sensitive data should be exported or not.
+ *
+ *
+ * The {@link ObservabilityConfiguration} is a registered MBean the object name
+ * can be retrieved by calling {@link ObservabilityTraceEventListener#getMBeanObjectName()}.
+ * This MBean allows to configure the TraceEventListener by setting attributes.
+ * The following attributes are available:
+ *
+ *
+ * - EnabledTracers: comma separated list of tracers "OTEL,JFR" by
+ * default.
+ * - SensitiveDataEnabled: enables/disables exporting sensiteve data
+ * (false by default)
+ *
+ */
+public class ObservabilityTraceEventListener implements TraceEventListener {
+ /**
+ * MBean object name format
+ */
+ private static final String MBEAN_OBJECT_NAME = "com.oracle.jdbc.provider.observability:type=ObservabilityConfiguration,uniqueIdentifier=%s";
+ private static final String MBEAN_OBJECT_NAME_OTEL = "com.oracle.jdbc.extension.opentelemetry:type=OpenTelemetryTraceEventListener,uniqueIdentifier=%s";
+
+ /**
+ * Default unique identifier, if parameter not set.
+ */
+ static final CharSequence DEFAULT_UNIQUE_IDENTIFIER = "default";
+
+ /**
+ * MBean server
+ */
+ private static final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+ /**
+ * Logger
+ */
+ private static final Logger logger = Logger.getLogger(
+ ObservabilityTraceEventListener.class.getPackageName());
+
+ /**
+ * Configuration for this instance of Trace Event Listener
+ */
+ private final ObservabilityConfiguration configuration;
+
+ /**
+ * Static map linking the name of the listener to its instance.
+ */
+ private static final Map INSTANCES
+ = new ConcurrentHashMap<>();
+
+ private ObjectName mBeanObjectName;
+
+ /**
+ * Create a trace event listener identified by the given name.
+ * @param uniqueIdentifier the name of the trace event listener.
+ * @param configurationType configuration type for backward compatibility.
+ */
+ private ObservabilityTraceEventListener(String uniqueIdentifier,
+ ObservabilityConfigurationType configurationType) {
+ // Create the configuration for this instance and register MBean
+ final String mBeanName = ObservabilityConfigurationType.OTEL.equals(configurationType) ?
+ String.format(MBEAN_OBJECT_NAME_OTEL, uniqueIdentifier) :
+ String.format(MBEAN_OBJECT_NAME, uniqueIdentifier);
+ this.configuration = new ObservabilityConfiguration(configurationType);
+ try {
+ mBeanObjectName = new ObjectName(mBeanName);
+ if (!server.isRegistered(mBeanObjectName)) {
+ server.registerMBean(configuration, mBeanObjectName);
+ logger.log(Level.FINEST, "MBean and tracers registered");
+ }
+ } catch (InstanceAlreadyExistsException | MBeanRegistrationException |
+ NotCompliantMBeanException | MalformedObjectNameException e) {
+ logger.log(Level.WARNING, "Could not register MBean", e);
+ }
+ // Register known tracers
+ configuration.registerTracer(new OTelTracer(configuration));
+ configuration.registerTracer(new JFRTracer(configuration));
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object roundTrip(Sequence sequence, TraceContext traceContext, Object userContext) {
+ if (!configuration.getEnabled()) { return null;}
+
+ // Cast the userContext to the map this listener uses, or create a new one
+ // if it is being used for the first time. This is the return value of the
+ // method, and will be send back by the driver on the next event.
+ Map currentUserContext = userContext == null ?
+ new HashMap<>() : (Map)userContext;
+
+ // loop through all the enabled tracers
+ for (String tracerName : configuration.getEnabledTracersAsList()) {
+ ObservabilityTracer tracer = configuration.getTracer(tracerName);
+ if (tracer != null) {
+ // call the tracer's round trip event with the tracer's context and store
+ // the new user context returned by the tracer in the user context map
+ Object newUserContext = tracer.traceRoundTrip(sequence, traceContext, currentUserContext.get(tracerName));
+ currentUserContext.put(tracerName, newUserContext);
+ } else {
+ // the listener does not fail if the tracer is unknow, it is possible to
+ // enable a tracer and register it later
+ logger.log(Level.WARNING, "Could not find registered tracer with name: " + tracer);
+ }
+ }
+
+ // return the new user context
+ return currentUserContext;
+ }
+
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object onExecutionEventReceived(JdbcExecutionEvent event, Object userContext, Object... params) {
+ if (!configuration.getEnabled()) { return null;}
+
+ // Cast the userContext to the map this listener uses, or create a new one
+ // if it is being used for the first time. This is the return value of the
+ // method, and will be send back by the driver on the next event.
+ Map currentUserContext = userContext == null ?
+ new HashMap<>() : (Map)userContext;
+
+ // loop through all the enabled tracers
+ for (String tracerName : configuration.getEnabledTracersAsList()) {
+ ObservabilityTracer tracer = configuration.getTracer(tracerName);
+ if (tracer != null) {
+ // call the tracer's execution event with the tracer's context and store
+ // the new user context returned by the tracer in the user context map
+ Object newUserContext = tracer.traceExecutionEvent(event, currentUserContext.get(tracerName), params);
+ currentUserContext.put(tracerName, newUserContext);
+ } else {
+ // the listener does not fail if the tracer is unknow, it is possible to
+ // enable a tracer and register it later
+ logger.log(Level.WARNING, "Could not find registered tracer with name: " + tracer);
+ }
+ }
+
+ // return the new user context
+ return currentUserContext;
+ }
+
+ @Override
+ public boolean isDesiredEvent(JdbcExecutionEvent event) {
+ // Accept all events
+ return true;
+ }
+
+
+ /**
+ * Returns the MBean object name assiciated with the configuration of the
+ * listener.
+ *
+ * @return the MBean object name.
+ */
+ public ObjectName getMBeanObjectName() {
+ return mBeanObjectName;
+ }
+
+ /**
+ * Returns the listener's configuration.
+ *
+ * @return the configuration instance associated to the listener.
+ */
+ public ObservabilityConfiguration getObservabilityConfiguration() {
+ return configuration;
+ }
+
+
+ /**
+ * Returns the trace event listener identified by the given unique idetifier.
+ *
+ * @param uniqueIdentifier the unique identifier, if no unique identifier was
+ * provided as a connection property, the unique identifier is "default".
+ * @return the trace event listener identified by the given unique idetifier,
+ * or {@code null} if no trace event listener with that unique idetifier was
+ * found.
+ */
+ public static ObservabilityTraceEventListener getTraceEventListener(String uniqueIdentifier) {
+ return INSTANCES.get(uniqueIdentifier);
+ }
+
+ /**
+ * Gets or creates an instance of {@link ObservabilityTraceEventListener}
+ * associated to the name.
+ * @param uniqueIdentifier the name of the listener instance.
+ * @param configurationType configuration type for backward compatibility.
+ *
+ * @return an instance of {@link ObservabilityTraceEventListener}.
+ */
+ static ObservabilityTraceEventListener getOrCreateInstance(String uniqueIdentifier,
+ ObservabilityConfigurationType configurationType) {
+ return INSTANCES.computeIfAbsent(uniqueIdentifier, n -> new ObservabilityTraceEventListener(n, configurationType));
+ }
+
+}
diff --git a/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityTraceEventListenerProvider.java b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityTraceEventListenerProvider.java
new file mode 100644
index 00000000..26b726a7
--- /dev/null
+++ b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/ObservabilityTraceEventListenerProvider.java
@@ -0,0 +1,108 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import oracle.jdbc.TraceEventListener;
+import oracle.jdbc.provider.observability.ObservabilityConfiguration.ObservabilityConfigurationType;
+import oracle.jdbc.spi.TraceEventListenerProvider;
+
+/**
+ * Implementation of Oracle JDBC {@link TraceEventListenerProvider} for
+ * {@link ObservabilityTraceEventListener}.
+ */
+public class ObservabilityTraceEventListenerProvider implements TraceEventListenerProvider {
+
+ /**
+ * Provider name
+ */
+ private static final String PROVIDER_NAME = "observability-trace-event-listener-provider";
+
+ /**
+ * Name Parameter name, identifies the listener
+ */
+ private static final String UNIQUE_IDENTIFIER_PARAMETER_NAME = "UNIQUE_IDENTIFIER";
+
+
+ /**
+ * Unique identifier, identifies a {@link ObservabilityTraceEventListener}.
+ */
+ protected static final Parameter uniqueIdentifierParameter = new Parameter() {
+
+ @Override
+ public boolean isSensitive() {
+ return false;
+ }
+
+ @Override
+ public String name() {
+ return UNIQUE_IDENTIFIER_PARAMETER_NAME;
+ }
+
+ };
+
+ /**
+ * Constructs a new instance of ObservabilityTraceEventListenerProvider. This
+ * constructor will be called by the driver's service provider to create a new
+ * instance.
+ */
+ public ObservabilityTraceEventListenerProvider() { }
+
+ @Override
+ public TraceEventListener getTraceEventListener(Map map) {
+ String uniqueIdentifier =
+ map.getOrDefault(
+ uniqueIdentifierParameter,
+ (CharSequence)ObservabilityTraceEventListener.DEFAULT_UNIQUE_IDENTIFIER).toString();
+ return ObservabilityTraceEventListener.getOrCreateInstance(uniqueIdentifier, ObservabilityConfigurationType.OBSERVABILITY);
+ }
+
+ @Override
+ public String getName() {
+ return PROVIDER_NAME;
+ }
+
+ @Override
+ public Collection extends Parameter> getParameters() {
+ return Collections.singletonList(uniqueIdentifierParameter);
+ }
+
+}
diff --git a/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/OpenTelemetryTraceEventListenerProvider.java b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/OpenTelemetryTraceEventListenerProvider.java
new file mode 100644
index 00000000..b815bcea
--- /dev/null
+++ b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/OpenTelemetryTraceEventListenerProvider.java
@@ -0,0 +1,78 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability;
+
+import java.util.Map;
+
+import oracle.jdbc.TraceEventListener;
+import oracle.jdbc.provider.observability.ObservabilityConfiguration.ObservabilityConfigurationType;
+
+/**
+ *
+ * This class implements the TraceEventListenerProvider interface exposed by the
+ * Oracle JDBC driver. It provides TraceEventListeners of type {@link
+ * oracle.jdbc.provider.observability.ObservabilityTraceEventListener}.
+ *
+ */
+public class OpenTelemetryTraceEventListenerProvider extends ObservabilityTraceEventListenerProvider {
+
+ /**
+ * Name of the provider
+ */
+ private static final String PROVIDER_NAME = "open-telemetry-trace-event-listener-provider";
+
+ /**
+ * Constructs a new instance of OpenTelemetryTraceEventListenerProvider. This
+ * constructor will be called by the driver's service provider to create a new
+ * instance.
+ */
+ public OpenTelemetryTraceEventListenerProvider() { }
+
+ @Override
+ public String getName() {
+ return PROVIDER_NAME;
+ }
+
+ @Override
+ public TraceEventListener getTraceEventListener(Map map) {
+ String uniqueIdentifier = map.get(uniqueIdentifierParameter).toString();
+ return ObservabilityTraceEventListener.getOrCreateInstance(uniqueIdentifier,
+ ObservabilityConfigurationType.OTEL);
+ }
+
+}
diff --git a/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/ObservabilityTracer.java b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/ObservabilityTracer.java
new file mode 100644
index 00000000..d0c4c208
--- /dev/null
+++ b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/ObservabilityTracer.java
@@ -0,0 +1,100 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability.tracers;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+import oracle.jdbc.TraceEventListener.JdbcExecutionEvent;
+import oracle.jdbc.TraceEventListener.Sequence;
+import oracle.jdbc.TraceEventListener.TraceContext;
+import oracle.jdbc.provider.observability.ObservabilityTraceEventListener;
+
+/**
+ * This interface must be implemented by all Observability tracers.
+ */
+public interface ObservabilityTracer {
+
+ /**
+ * Map containing the number of parameters expected for each execution event
+ */
+ Map EXECUTION_EVENTS_PARAMETERS
+ = new EnumMap(JdbcExecutionEvent.class) {
+ {
+ put(JdbcExecutionEvent.AC_REPLAY_STARTED, 3);
+ put(JdbcExecutionEvent.AC_REPLAY_SUCCESSFUL, 3);
+ put(JdbcExecutionEvent.VIP_RETRY, 8);
+ }
+ };
+
+ /**
+ * Returns the unique name of the tracer.
+ * @return the unique name of the tracer.
+ */
+ String getName();
+
+
+ /**
+ * Called by {@link ObservabilityTraceEventListener} when a round trip event
+ * is received.
+ *
+ * @param sequence BEFORE if before the round trip, AFTER if after the round
+ * trip
+ * @param traceContext Information about the round trip. Valid only during the
+ * call
+ * @param userContext Result of previous call on this Connection or null if no
+ * previous call or if observability was disabled since the previous call.
+ * @return a user context object that is passed to the next call on this
+ * Connection. May be null.
+ */
+ Object traceRoundTrip(Sequence sequence, TraceContext traceContext, Object userContext);
+
+ /**
+ * Called by {@link ObservabilityTraceEventListener} when an execution event
+ * is received.
+ *
+ * @param event the event.
+ * @param userContext the result of the previous call or null if no previous
+ * call has been made.
+ * @param params event specific parameters.
+ * @return a user context object that is passed to the next call for the same
+ * type of event. May be null.
+ */
+ Object traceExecutionEvent(JdbcExecutionEvent event, Object userContext, Object... params);
+
+}
diff --git a/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/jfr/JFREventFactory.java b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/jfr/JFREventFactory.java
new file mode 100644
index 00000000..f42c811a
--- /dev/null
+++ b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/jfr/JFREventFactory.java
@@ -0,0 +1,1054 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability.tracers.jfr;
+
+import jdk.jfr.Event;
+import jdk.jfr.Label;
+import jdk.jfr.Name;
+
+import java.sql.SQLException;
+import java.util.logging.Logger;
+
+import jdk.jfr.Category;
+import oracle.jdbc.TraceEventListener.JdbcExecutionEvent;
+import oracle.jdbc.TraceEventListener.TraceContext;
+import oracle.jdbc.provider.observability.ObservabilityConfiguration;
+import oracle.jdbc.provider.observability.ObservabilityTraceEventListener;
+import oracle.jdbc.provider.observability.tracers.ObservabilityTracer;
+
+/**
+ * Factory class for creating JFR events depending on the database function.
+ */
+public class JFREventFactory {
+
+ /**
+ * Logger
+ */
+ private static final Logger logger = Logger.getLogger(
+ ObservabilityTraceEventListener.class.getPackageName());
+
+ /**
+ * This class only has a static method, no public constructor needed.
+ */
+ private JFREventFactory() { }
+
+ /**
+ * Creates an instance of {@link RoundTripEvent} for the given trace context.
+ * The type of round trip event depends on the database function.
+ *
+ * @param traceContext the trace context received by a TraceEventListener.
+ * @param configuration the configuration
+ * @return the {@link RoundTripEvent} for the database function.
+ */
+ public static RoundTripEvent createJFRRoundTripEvent(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ switch (traceContext.databaseFunction()) {
+ case ADVANCED_QUEUING_12C_EMON_DEQUEUE:
+ return new AdvancedQueuing12cEminDequeueEvent(traceContext, configuration);
+ case ADVANCED_QUEUING_ARRAY_ENQUEUE_DEQUEUE:
+ return new AdvancedQueuingArrayEnqueueDequeue(traceContext, configuration);
+ case ADVANCED_QUEUING_DEQUEUE_V8:
+ return new AdvancedQueuingDequeueV8(traceContext, configuration);
+ case ADVANCED_QUEUING_ENQUEUE:
+ return new AdvancedQueuingEnqueue(traceContext, configuration);
+ case ADVANCED_QUEUING_GET_PROPAGATION_STATUS:
+ return new AdvancedQueuingGetPropagationStatus(traceContext, configuration);
+ case ADVANCED_QUEUING_LISTEN:
+ return new AdvancedQueuingListen(traceContext, configuration);
+ case ADVANCED_QUEUING_SESSION_GET_RPC_1:
+ return new AdvancedQueuingSessionGetRPC1(traceContext, configuration);
+ case ADVANCED_QUEUING_SESSION_GET_RPC_2:
+ return new AdvancedQueuingSessionGetRPC2(traceContext, configuration);
+ case ADVANCED_QUEUING_SHARED_DEQUEUE:
+ return new AdvancedQueuingSharedDequeue(traceContext, configuration);
+ case ADVANCED_QUEUING_SHARED_ENQUEUE:
+ return new AdvancedQueuingSharedEnqueue(traceContext, configuration);
+ case APP_REPLAY:
+ return new AppReplay(traceContext, configuration);
+ case AUTH_CALL:
+ return new AuthCall(traceContext, configuration);
+ case AUTO_COMMIT_OFF:
+ return new AutoCommitOff(traceContext, configuration);
+ case AUTO_COMMIT_ON:
+ return new AutoCommitOn(traceContext, configuration);
+ case CANCEL_ALL:
+ return new CancelAll(traceContext, configuration);
+ case CANCEL_OPERATION:
+ return new CancelOperation(traceContext, configuration);
+ case CHUNCK_INFO:
+ return new ChunkInfo(traceContext, configuration);
+ case CLIENT_FEATURES:
+ return new ClientFeatures(traceContext, configuration);
+ case CLIENT_QUERY_CACHE_IDS:
+ return new ClientQueryCacheIds(traceContext, configuration);
+ case CLIENT_QUERY_CACHE_STATS_UPDATE:
+ return new ClientQueryCacheStatsUpdate(traceContext, configuration);
+ case CLOSE_ALL_CURSOR:
+ return new CloseAllCursor(traceContext, configuration);
+ case CLOSE_CURSOR:
+ return new CloseCursor(traceContext, configuration);
+ case COMMIT:
+ return new Commit(traceContext, configuration);
+ case DB12C_NOTIFICATION_RCV:
+ return new DB12cNotificationRCV(traceContext, configuration);
+ case DBNS_SAGAS:
+ return new DBNSSagas(traceContext, configuration);
+ case DESCRIBE_ANY_V8:
+ return new DescribeAnyV8(traceContext, configuration);
+ case DESCRIBE_ARRAY:
+ return new DescribeArray(traceContext, configuration);
+ case DESCRIBE_QUERY_CALL:
+ return new DescribeQueryCall(traceContext, configuration);
+ case DIRECT_PATH_LOAD_STREAM:
+ return new DirectPathLoadStream(traceContext, configuration);
+ case DIRECT_PATH_MISC_OP:
+ return new DirectPathMISCOp(traceContext, configuration);
+ case DIRECT_PATH_PREPARE:
+ return new DirectPathPrepare(traceContext, configuration);
+ case DISTRIBUTED_TRANS_MGR_RPC:
+ return new DistributedTransMGRRPC(traceContext, configuration);
+ case EXECUTE_QUERY:
+ return new ExecuteQuery(traceContext, configuration);
+ case EXTENSIBLE_SECURITY_SESSION_CREATE:
+ return new ExtensibleSecuritySessionCreate(traceContext, configuration);
+ case EXTENSIBLE_SECURITY_SESSION_PIGGYBACK:
+ return new ExtensibleSecuritySessionPiggyback(traceContext, configuration);
+ case EXTENSIBLE_SECURITY_SESSION_ROUNDTRIP:
+ return new ExtensibleSecuritySessionRoundtrip(traceContext, configuration);
+ case FAST_UPI_CALLS:
+ return new FastUPICalls(traceContext, configuration);
+ case FETCH_ROW:
+ return new FetchRow(traceContext, configuration);
+ case GET_VERSION:
+ return new GetVersion(traceContext, configuration);
+ case KERNEL_PROGRAMMATIC_NOTIFICATION:
+ return new KernelProgrammaticNotification(traceContext, configuration);
+ case KEY_VALUE:
+ return new KeyValue(traceContext, configuration);
+ case LOB_FILE_CALL:
+ return new LOBFileCall(traceContext, configuration);
+ case LOGOFF:
+ return new LogOff(traceContext, configuration);
+ case LOGON_CHALLENGE_RESPONSE_1:
+ return new LogonChallengeResponse1(traceContext, configuration);
+ case LOGON_CHALLENGE_RESPONSE_2:
+ return new LogonChallengeResponse2(traceContext, configuration);
+ case OEXFEN:
+ return new OEXFEN(traceContext, configuration);
+ case OPEN_CURSOR:
+ return new OpenCursor(traceContext, configuration);
+ case OSQL7:
+ return new OSQL7(traceContext, configuration);
+ case OSTART:
+ return new OStart(traceContext, configuration);
+ case OSTOP:
+ return new OStop(traceContext, configuration);
+ case PARAMETER_PUT_SPFILE:
+ return new ParameterPutSPFile(traceContext, configuration);
+ case PING:
+ return new Ping(traceContext, configuration);
+ case PIPELINE_END:
+ return new PipelineEnd(traceContext, configuration);
+ case PIPELINE_PIGGYBACK_BEGIN:
+ return new PipelinePiggybackBegin(traceContext, configuration);
+ case PIPELINE_PIGGYBACK_OP:
+ return new PipelinePiggybackOp(traceContext, configuration);
+ case ROLLBACK:
+ return new Rollback(traceContext, configuration);
+ case SESSION_KEY:
+ return new SessionKey(traceContext, configuration);
+ case SESSION_STATE_OPS:
+ return new SessionStateOps(traceContext, configuration);
+ case SESSION_STATE_TEMPLATE:
+ return new SessionStateTemplate(traceContext, configuration);
+ case SESSION_SWITCH_V8:
+ return new SessionSwitchV8(traceContext, configuration);
+ case TRACING_MESSAGE:
+ return new TracingMessage(traceContext, configuration);
+ case TRANSACTION_COMMIT:
+ return new TransactionCommit(traceContext, configuration);
+ case TRANSACTION_START:
+ return new TransactionStart(traceContext, configuration);
+ case TTC_DTY_ROUNDTRIP:
+ return new TTCDTYRoundtrip(traceContext, configuration);
+ case TTC_PRO_ROUNDTRIP:
+ return new TTCPRORoundtrip(traceContext, configuration);
+ case XS_ATTACH_SESSION:
+ return new XSAttachSession(traceContext, configuration);
+ case XS_CREATE_SESSION:
+ return new XSCreateSession(traceContext, configuration);
+ case XS_DESTROY_SESSION:
+ return new XSDestroySession(traceContext, configuration);
+ case XS_DETACH_SESSION:
+ return new XSDetachSession(traceContext, configuration);
+ case XS_NAMESPACE_OP:
+ return new XSNamespaceOp(traceContext, configuration);
+ case XS_NAMESPACE_OPS:
+ return new XSNamespaceOps(traceContext, configuration);
+ case XS_SET_SESSION_PARAMETER:
+ return new XSSetSessionParameter(traceContext, configuration);
+ case XS_STATE_SYNC_OP:
+ return new XSStateSyncOp(traceContext, configuration);
+ default:
+ logger.warning("Unknown round trip received: " + traceContext.databaseFunction());
+ return new RoundTripEvent(traceContext, configuration);
+ }
+ }
+
+ /**
+ * Creates an instance {@link ExecutionEvent} for the given {@link
+ * JdbcExecutionEvent}.
+ *
+ * @param event the event.
+ * @param params the parameters to populate the event properties.
+ * @return the execution event.
+ */
+ public static Event createExecutionEvent(JdbcExecutionEvent event, Object... params) {
+ switch (event) {
+ case AC_REPLAY_STARTED:
+ return new ACReplayStarted(event, params);
+ case AC_REPLAY_SUCCESSFUL:
+ return new ACReplaySuccessful(event, params);
+ case VIP_RETRY:
+ return new VIPRetry(event, params);
+ default:
+ logger.warning("Unknow event received: " + event);
+ return new ExecutionEvent(event, params);
+ }
+ }
+
+ // Round-trip events
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ADVANCED_QUEUING_12C_EMON_DEQUEUE")
+ @Label("AQ 12c emon dequeue")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AdvancedQueuing12cEminDequeueEvent extends RoundTripEvent{
+ public AdvancedQueuing12cEminDequeueEvent(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ADVANCED_QUEUING_ARRAY_ENQUEUE_DEQUEUE")
+ @Label("AQ Array Enqueue/Dequeue")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AdvancedQueuingArrayEnqueueDequeue extends RoundTripEvent{
+ public AdvancedQueuingArrayEnqueueDequeue(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ADVANCED_QUEUING_DEQUEUE_V8")
+ @Label("AQ Dequeue before 8.1")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AdvancedQueuingDequeueV8 extends RoundTripEvent{
+ public AdvancedQueuingDequeueV8(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ADVANCED_QUEUING_ENQUEUE")
+ @Label("AQ EnQueue")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AdvancedQueuingEnqueue extends RoundTripEvent{
+ public AdvancedQueuingEnqueue(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ADVANCED_QUEUING_GET_PROPAGATION_STATUS")
+ @Label("AQ get propagation status entries")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AdvancedQueuingGetPropagationStatus extends RoundTripEvent{
+ public AdvancedQueuingGetPropagationStatus(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ADVANCED_QUEUING_LISTEN")
+ @Label("AQ Listen")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AdvancedQueuingListen extends RoundTripEvent{
+ public AdvancedQueuingListen(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ADVANCED_QUEUING_SESSION_GET_RPC_1")
+ @Label("Session get RPC in server pool scenario")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AdvancedQueuingSessionGetRPC1 extends RoundTripEvent{
+ public AdvancedQueuingSessionGetRPC1(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ADVANCED_QUEUING_SESSION_GET_RPC_2")
+ @Label("Session get RPC in server pool scenario")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AdvancedQueuingSessionGetRPC2 extends RoundTripEvent{
+ public AdvancedQueuingSessionGetRPC2(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ADVANCED_QUEUING_SHARED_DEQUEUE")
+ @Label("AQ Sharded dequeue")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AdvancedQueuingSharedDequeue extends RoundTripEvent{
+ public AdvancedQueuingSharedDequeue(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ADVANCED_QUEUING_SHARED_ENQUEUE")
+ @Label("AQ Sharded enqueue")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AdvancedQueuingSharedEnqueue extends RoundTripEvent{
+ public AdvancedQueuingSharedEnqueue(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.APP_REPLAY")
+ @Label("Application continuity REPLAY")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AppReplay extends RoundTripEvent{
+ public AppReplay(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.AUTH_CALL")
+ @Label("Generic authentication call")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AuthCall extends RoundTripEvent{
+ public AuthCall(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.AUTO_COMMIT_OFF")
+ @Label("Auto commit off")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AutoCommitOff extends RoundTripEvent{
+ public AutoCommitOff(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.AUTO_COMMIT_ON")
+ @Label("Auto commit on")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class AutoCommitOn extends RoundTripEvent{
+ public AutoCommitOn(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.CANCEL_ALL")
+ @Label("Cancel All")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class CancelAll extends RoundTripEvent{
+ public CancelAll(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.CANCEL_OPERATION")
+ @Label("Cancel the current operation")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class CancelOperation extends RoundTripEvent{
+ public CancelOperation(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.CHUNCK_INFO")
+ @Label("Chunk info RPC")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class ChunkInfo extends RoundTripEvent{
+ public ChunkInfo(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.CLIENT_FEATURES")
+ @Label("Client features")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class ClientFeatures extends RoundTripEvent{
+ public ClientFeatures(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.CLIENT_QUERY_CACHE_IDS")
+ @Label("Client query cache IDs")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class ClientQueryCacheIds extends RoundTripEvent{
+ public ClientQueryCacheIds(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.CLIENT_QUERY_CACHE_STATS_UPDATE")
+ @Label("Client query cache statistics update")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class ClientQueryCacheStatsUpdate extends RoundTripEvent{
+ public ClientQueryCacheStatsUpdate(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.CLOSE_ALL_CURSOR")
+ @Label("Cursor close all")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class CloseAllCursor extends RoundTripEvent{
+ public CloseAllCursor(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.CLOSE_CURSOR")
+ @Label("Close a cursor")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class CloseCursor extends RoundTripEvent{
+ public CloseCursor(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.COMMIT")
+ @Label("Commit")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class Commit extends RoundTripEvent{
+ public Commit(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.DB12C_NOTIFICATION_RCV")
+ @Label("12c notification receive")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class DB12cNotificationRCV extends RoundTripEvent{
+ public DB12cNotificationRCV(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.DBNS_SAGAS")
+ @Label("DBMS Sagas")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class DBNSSagas extends RoundTripEvent{
+ public DBNSSagas(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.DESCRIBE_ANY_V8")
+ @Label("V8 Describe Any")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class DescribeAnyV8 extends RoundTripEvent{
+ public DescribeAnyV8(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.DESCRIBE_ARRAY")
+ @Label("Array describe")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class DescribeArray extends RoundTripEvent{
+ public DescribeArray(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.DESCRIBE_QUERY_CALL")
+ @Label("New describe query call")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class DescribeQueryCall extends RoundTripEvent{
+ public DescribeQueryCall(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.DIRECT_PATH_LOAD_STREAM")
+ @Label("Direct Path Load Stream")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class DirectPathLoadStream extends RoundTripEvent{
+ public DirectPathLoadStream(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.DIRECT_PATH_MISC_OP")
+ @Label("Direct Path Misc Operations")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class DirectPathMISCOp extends RoundTripEvent{
+ public DirectPathMISCOp(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.DIRECT_PATH_PREPARE")
+ @Label("Direct Path Prepare")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class DirectPathPrepare extends RoundTripEvent{
+ public DirectPathPrepare(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.DISTRIBUTED_TRANS_MGR_RPC")
+ @Label("Distributed transaction manager RPC")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class DistributedTransMGRRPC extends RoundTripEvent{
+ public DistributedTransMGRRPC(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.EXECUTE_QUERY")
+ @Label("Execute query")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class ExecuteQuery extends RoundTripEvent{
+ public ExecuteQuery(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.EXTENSIBLE_SECURITY_SESSION_CREATE")
+ @Label("eXtensible Security Sessions Create Session")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class ExtensibleSecuritySessionCreate extends RoundTripEvent{
+ public ExtensibleSecuritySessionCreate(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.EXTENSIBLE_SECURITY_SESSION_PIGGYBACK")
+ @Label("eXtensible Security Sessions Piggyback")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class ExtensibleSecuritySessionPiggyback extends RoundTripEvent{
+ public ExtensibleSecuritySessionPiggyback(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.EXTENSIBLE_SECURITY_SESSION_ROUNDTRIP")
+ @Label("eXtensible Security Session Roundtrip")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class ExtensibleSecuritySessionRoundtrip extends RoundTripEvent{
+ public ExtensibleSecuritySessionRoundtrip(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.FAST_UPI_CALLS")
+ @Label("Fast UPI calls to opial7")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class FastUPICalls extends RoundTripEvent{
+ public FastUPICalls(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.FETCH_ROW")
+ @Label("Fetch a row")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class FetchRow extends RoundTripEvent{
+ public FetchRow(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.GET_VERSION")
+ @Label("Get Oracle version-date string in new format")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class GetVersion extends RoundTripEvent{
+ public GetVersion(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.KERNEL_PROGRAMMATIC_NOTIFICATION")
+ @Label("Kernel Programmatic Notification")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class KernelProgrammaticNotification extends RoundTripEvent{
+ public KernelProgrammaticNotification(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.KEY_VALUE")
+ @Label("Client app context, configurationspace, attribute, values")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class KeyValue extends RoundTripEvent{
+ public KeyValue(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.LOB_FILE_CALL")
+ @Label("LOB and FILE related calls")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class LOBFileCall extends RoundTripEvent{
+ public LOBFileCall(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.LOGOFF")
+ @Label("Logoff of Oracle")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class LogOff extends RoundTripEvent{
+ public LogOff(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.LOGON_CHALLENGE_RESPONSE_1")
+ @Label("First half of challenge-response logon")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class LogonChallengeResponse1 extends RoundTripEvent{
+ public LogonChallengeResponse1(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.LOGON_CHALLENGE_RESPONSE_2")
+ @Label("Second half of challenge-response logon")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class LogonChallengeResponse2 extends RoundTripEvent{
+ public LogonChallengeResponse2(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.OEXFEN")
+ @Label("OEXFEN")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class OEXFEN extends RoundTripEvent{
+ public OEXFEN(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.OPEN_CURSOR")
+ @Label("Open a cursor")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class OpenCursor extends RoundTripEvent{
+ public OpenCursor(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.OSQL7")
+ @Label("OSQL7")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class OSQL7 extends RoundTripEvent{
+ public OSQL7(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.OSTART")
+ @Label("Starts Oracle")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class OStart extends RoundTripEvent{
+ public OStart(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.OSTOP")
+ @Label("Stops Oracle")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class OStop extends RoundTripEvent{
+ public OStop(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.PARAMETER_PUT_SPFILE")
+ @Label("Put parameter using spfile (for startup)")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class ParameterPutSPFile extends RoundTripEvent{
+ public ParameterPutSPFile(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.PING")
+ @Label("Ping")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class Ping extends RoundTripEvent{
+ public Ping(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.PIPELINE_END")
+ @Label("Pipeline End")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class PipelineEnd extends RoundTripEvent{
+ public PipelineEnd(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.PIPELINE_PIGGYBACK_BEGIN")
+ @Label("Pipeline Begin Piggyback")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class PipelinePiggybackBegin extends RoundTripEvent{
+ public PipelinePiggybackBegin(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.PIPELINE_PIGGYBACK_OP")
+ @Label("Pipeline Operation Piggyback")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class PipelinePiggybackOp extends RoundTripEvent{
+ public PipelinePiggybackOp(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.ROLLBACK")
+ @Label("Rollback")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class Rollback extends RoundTripEvent{
+ public Rollback(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.SESSION_KEY")
+ @Label("Get the session key")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class SessionKey extends RoundTripEvent{
+ public SessionKey(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.SESSION_STATE_OPS")
+ @Label("Session state ops")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class SessionStateOps extends RoundTripEvent{
+ public SessionStateOps(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.SESSION_STATE_TEMPLATE")
+ @Label("Session state template")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class SessionStateTemplate extends RoundTripEvent{
+ public SessionStateTemplate(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.SESSION_SWITCH_V8")
+ @Label("V8 session switching piggyback")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class SessionSwitchV8 extends RoundTripEvent{
+ public SessionSwitchV8(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.TRACING_MESSAGE")
+ @Label("End to end tracing message")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class TracingMessage extends RoundTripEvent{
+ public TracingMessage(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.TRANSACTION_COMMIT")
+ @Label("Transaction commit, rollback, recover")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class TransactionCommit extends RoundTripEvent{
+ public TransactionCommit(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.TRANSACTION_START")
+ @Label("Transaction start, attach, detach")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class TransactionStart extends RoundTripEvent{
+ public TransactionStart(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.TTC_DTY_ROUNDTRIP")
+ @Label("Data type message exchange")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class TTCDTYRoundtrip extends RoundTripEvent{
+ public TTCDTYRoundtrip(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.TTC_PRO_ROUNDTRIP")
+ @Label("Protocol negotiation message exchange")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class TTCPRORoundtrip extends RoundTripEvent{
+ public TTCPRORoundtrip(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.XS_ATTACH_SESSION")
+ @Label("XS Attach Session")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class XSAttachSession extends RoundTripEvent{
+ public XSAttachSession(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.XS_CREATE_SESSION")
+ @Label("XS Create Session")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class XSCreateSession extends RoundTripEvent{
+ public XSCreateSession(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.XS_DESTROY_SESSION")
+ @Label("XS Destroy Session")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class XSDestroySession extends RoundTripEvent{
+ public XSDestroySession(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.XS_DETACH_SESSION")
+ @Label("XS Detach Session")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class XSDetachSession extends RoundTripEvent{
+ public XSDetachSession(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.XS_NAMESPACE_OP")
+ @Label("XS Namespace OP")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class XSNamespaceOp extends RoundTripEvent{
+ public XSNamespaceOp(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.XS_NAMESPACE_OPS")
+ @Label("XS namespace OPs")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class XSNamespaceOps extends RoundTripEvent{
+ public XSNamespaceOps(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.XS_SET_SESSION_PARAMETER")
+ @Label("XS Set Session Parameter")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class XSSetSessionParameter extends RoundTripEvent{
+ public XSSetSessionParameter(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip.XS_STATE_SYNC_OP")
+ @Label("XS State Sync OP")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class XSStateSyncOp extends RoundTripEvent{
+ public XSStateSyncOp(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ super(traceContext, configuration);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.RoundTrip")
+ @Label("Round trip")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class RoundTripEvent extends Event {
+
+ public RoundTripEvent(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ setValues(traceContext, configuration);
+ }
+
+ public void setValues(TraceContext traceContext, ObservabilityConfiguration configuration) {
+ this.connectionID = traceContext.getConnectionId();
+ this.databaseOperation = traceContext.databaseOperation();
+ this.tenant = traceContext.tenant();
+ this.sqlID = traceContext.getSqlId();
+ if (configuration.getSensitiveDataEnabled()) {
+ this.originalSQLText = traceContext.originalSqlText();
+ this.actualSQLText = traceContext.actualSqlText();
+ this.databaseUser = traceContext.user();
+ }
+ }
+
+ @Label("Connection ID")
+ String connectionID;
+
+ @Label("Database operation")
+ String databaseOperation;
+
+ @Label("Database tenant")
+ String tenant;
+
+ @Label("SQL ID")
+ String sqlID;
+
+ @Label("Original SQL text")
+ String originalSQLText;
+
+ @Label("Actual SQL text")
+ String actualSQLText;
+
+ @Label("Database user")
+ String databaseUser;
+
+ }
+
+ // Execution Events
+ @Name("oracle.jdbc.provider.observability.ExecutionEvent.AC_REPLAY_STARTED")
+ @Label("AC replay started")
+ @Category({"Oracle JDBC", "Execution events"})
+ static class ACReplayStarted extends ACReplay {
+ public ACReplayStarted(JdbcExecutionEvent event, Object... params) {
+ super(event, params);
+ }
+ }
+
+ @Name("oracle.jdbc.provider.observability.ExecutionEvent.AC_REPLAY_SUCCESSFUL")
+ @Label("AC replay successful")
+ @Category({"Oracle JDBC", "Execution events"})
+ static class ACReplaySuccessful extends ACReplay {
+ public ACReplaySuccessful(JdbcExecutionEvent event, Object... params) {
+ super(event, params);
+ }
+ }
+
+
+ @Name("oracle.jdbc.provider.observability.ExecutionEvent.AC_REPLAY")
+ @Label("AC replay")
+ @Category({"Oracle JDBC", "Execution events"})
+ static class ACReplay extends ExecutionEvent {
+ public ACReplay(JdbcExecutionEvent event, Object... params) {
+ super(event, params);
+ if (ObservabilityTracer.EXECUTION_EVENTS_PARAMETERS.get(event) == params.length) {
+ this.errorCode = ((SQLException) params[1]).getErrorCode();
+ this.sqlState = ((SQLException) params[1]).getSQLState();
+ this.currentReplayRetryCount = params[2].toString();
+ }
+ }
+ @Label("Error code")
+ public int errorCode;
+
+ @Label("SQL state")
+ public String sqlState;
+
+ @Label("Current replay retry count")
+ public String currentReplayRetryCount;
+ }
+
+ @Name("oracle.jdbc.provider.observability.ExecutionEvent.VIP_RETRY")
+ @Label("VIP retry")
+ @Category({"Oracle JDBC", "Round trips"})
+ static class VIPRetry extends ExecutionEvent {
+ public VIPRetry(JdbcExecutionEvent event, Object... params) {
+ super(event, params);
+ if (ObservabilityTracer.EXECUTION_EVENTS_PARAMETERS.get(event) == params.length) {
+ protocol = params[1].toString();
+ host = params[2].toString();
+ port = params[3].toString();
+ serviceName = params[4].toString();
+ sid = params[5].toString();
+ connectionData = params[6].toString();
+ vipAddress = params[7].toString();
+ }
+ }
+
+ @Label("The protocol")
+ public String protocol;
+
+ @Label("The host")
+ public String host;
+
+ @Label("The port")
+ public String port;
+
+ @Label("The service name")
+ public String serviceName;
+
+ @Label("The SID")
+ public String sid;
+
+ @Label("The connection data")
+ public String connectionData;
+
+ @Label("The VIP address")
+ public String vipAddress;
+ }
+
+ @Name("oracle.jdbc.provider.observability.ExecutionEvent")
+ @Label("Execution event")
+ @Category({"Oracle JDBC", "Execution events"})
+ static class ExecutionEvent extends Event {
+ public ExecutionEvent(JdbcExecutionEvent event, Object... params) {
+ if (ObservabilityTracer.EXECUTION_EVENTS_PARAMETERS.get(event) == params.length) {
+ if (params != null && params.length > 0) {
+ this.errorMessage = params[0].toString();
+ }
+ }
+ }
+
+ @Label("Error message")
+ String errorMessage;
+ }
+
+}
diff --git a/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/jfr/JFRTracer.java b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/jfr/JFRTracer.java
new file mode 100644
index 00000000..2c195506
--- /dev/null
+++ b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/jfr/JFRTracer.java
@@ -0,0 +1,112 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability.tracers.jfr;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jdk.jfr.Event;
+import oracle.jdbc.TraceEventListener.JdbcExecutionEvent;
+import oracle.jdbc.TraceEventListener.Sequence;
+import oracle.jdbc.TraceEventListener.TraceContext;
+import oracle.jdbc.provider.observability.ObservabilityConfiguration;
+import oracle.jdbc.provider.observability.tracers.ObservabilityTracer;
+import oracle.jdbc.provider.observability.tracers.jfr.JFREventFactory.RoundTripEvent;
+
+/**
+ * {@link ObservabilityTracer} for tracing Java Flight Recorder events.
+ */
+public class JFRTracer implements ObservabilityTracer{
+
+ /**
+ * Configuraiton
+ */
+ private final ObservabilityConfiguration configuration;
+
+ /**
+ * Logger.
+ */
+ private static Logger logger = Logger.getLogger(JFRTracer.class.getPackageName());
+
+ /**
+ * Creates a new instance.
+ *
+ * @param configuration the configuraiton.
+ */
+ public JFRTracer(ObservabilityConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public String getName() {
+ return "JFR";
+ }
+
+ @Override
+ public Object traceRoundTrip(Sequence sequence, TraceContext traceContext, Object userContext) {
+ if (sequence.equals(Sequence.BEFORE)) {
+ // Create the event and start measuring event duration
+ RoundTripEvent event = JFREventFactory.createJFRRoundTripEvent(traceContext, configuration);
+ event.begin();
+ return event;
+ } else {
+ if (userContext != null) {
+ RoundTripEvent event = (RoundTripEvent) userContext;
+ // set event attributes
+ event.setValues(traceContext, configuration);
+ // stop the measuring event durating and commit
+ event.commit();
+ } else {
+ logger.log(Level.WARNING, "Unknown or null user context received from the driver on " +
+ "database operation: " + traceContext.databaseOperation());
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public Object traceExecutionEvent(JdbcExecutionEvent event, Object userContext, Object... params) {
+ // Create event and commit
+ Event executionEvent = JFREventFactory.createExecutionEvent(event, params);
+ executionEvent.begin();
+ executionEvent.commit();
+ //Return previous user context
+ return userContext;
+ }
+
+}
diff --git a/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/otel/OTelTracer.java b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/otel/OTelTracer.java
new file mode 100644
index 00000000..f922004f
--- /dev/null
+++ b/ojdbc-provider-observability/src/main/java/oracle/jdbc/provider/observability/tracers/otel/OTelTracer.java
@@ -0,0 +1,272 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability.tracers.otel;
+
+import java.sql.SQLException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.api.trace.SpanBuilder;
+import io.opentelemetry.api.trace.SpanContext;
+import io.opentelemetry.api.trace.SpanKind;
+import io.opentelemetry.api.trace.StatusCode;
+import io.opentelemetry.api.trace.TraceState;
+import io.opentelemetry.api.trace.Tracer;
+import io.opentelemetry.context.Scope;
+import oracle.jdbc.TraceEventListener;
+import oracle.jdbc.TraceEventListener.JdbcExecutionEvent;
+import oracle.jdbc.TraceEventListener.Sequence;
+import oracle.jdbc.TraceEventListener.TraceContext;
+import oracle.jdbc.provider.observability.ObservabilityConfiguration;
+import oracle.jdbc.provider.observability.tracers.ObservabilityTracer;
+
+/**
+ * Open Telemetry tracer. Exports round trip event and execution events to
+ * Open Telemetry.
+ */
+public class OTelTracer implements ObservabilityTracer {
+
+ /**
+ * Key used to send the current Open Telemetry Trace Context to the server
+ * using {@link TraceContext#setClientInfo(String, String)}.
+ */
+ private static final String TRACE_KEY = "clientcontext.ora$opentelem$tracectx";
+
+ /**
+ * The trace context is sent to the server in two lines, this is the first
+ * line it contains the version and the span context.
+ */
+ private static final String TRACE_FORMAT = "traceparent: %s-%s-%s-%s\r\n";
+
+ /**
+ * Trace context version.
+ */
+ private static final String TRACE_VERSION = "00";
+
+ /**
+ * Format of the second line sent to the server containing the trace context.
+ * It contains the trace state.
+ */
+ private static final String TRACE_STATE_FORMAT = "tracestate: %s\r\n";
+
+ /**
+ * Logger.
+ */
+ private static Logger logger = Logger.getLogger(OTelTracer.class.getPackageName());
+
+ /**
+ * Configuraiton
+ */
+ private final ObservabilityConfiguration configuration;
+
+
+ /**
+ * Constructor. This tracer always uses {@link GlobalOpenTelemetry} to get
+ * the Open Telemetry tracer.
+ *
+ * @param configuration the configuration.
+ */
+ public OTelTracer(ObservabilityConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public String getName() {
+ return "OTEL";
+ }
+
+ @Override
+ public Object traceRoundTrip(Sequence sequence, TraceContext traceContext, Object userContext) {
+ if (sequence == Sequence.BEFORE) {
+ // Create the Span before the round-trip.
+ final Span span = initAndGetSpan(traceContext, traceContext.databaseOperation());
+ makeSpanCurrentAndSendContextToServer(traceContext, span);
+ // Return the Span instance to the driver. The driver holds this instance and
+ // supplies it as user context parameter on the next round-trip call.
+ return span;
+ } else {
+ // End the Span after the round-trip.
+ if (userContext != null) {
+ final Span span = (Span) userContext;
+ span.setStatus(traceContext.isCompletedExceptionally() ? StatusCode.ERROR : StatusCode.OK);
+ span.end();
+ } else {
+ logger.log(Level.WARNING, "Unknown or null user context received from the driver on " +
+ "database operation: " + traceContext.databaseOperation());
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public Object traceExecutionEvent(JdbcExecutionEvent event, Object userContext, Object... params) {
+ if (EXECUTION_EVENTS_PARAMETERS.get(event) == params.length) {
+ Tracer tracer = GlobalOpenTelemetry.get().getTracer(OTelTracer.class.getName());
+ if (event == TraceEventListener.JdbcExecutionEvent.VIP_RETRY) {
+ SpanBuilder spanBuilder = tracer
+ .spanBuilder(event.getDescription())
+ .setAttribute("Error message", params[0].toString())
+ .setAttribute("VIP Address", params[7].toString());
+ // Add sensitive information (URL and SQL) if it is enabled
+ if (configuration.getSensitiveDataEnabled()) {
+ logger.log(Level.FINEST, "Sensitive information on");
+ spanBuilder.setAttribute("Protocol", params[1].toString())
+ .setAttribute("Host", params[2].toString())
+ .setAttribute("Port", params[3].toString())
+ .setAttribute("Service name", params[4].toString())
+ .setAttribute("SID", params[5].toString())
+ .setAttribute("Connection data", params[6].toString());
+ }
+ // start and end span.
+ spanBuilder.startSpan().end();
+ } else if (event == TraceEventListener.JdbcExecutionEvent.AC_REPLAY_STARTED
+ || event == TraceEventListener.JdbcExecutionEvent.AC_REPLAY_SUCCESSFUL) {
+ SpanBuilder spanBuilder = tracer
+ .spanBuilder(event.getDescription())
+ .setAttribute("Error Message", params[0].toString())
+ .setAttribute("Error code", ((SQLException) params[1]).getErrorCode())
+ .setAttribute("SQL state", ((SQLException) params[1]).getSQLState())
+ .setAttribute("Current replay retry count", params[2].toString());
+ spanBuilder.startSpan().end();
+ } else {
+ logger.log(Level.WARNING, "Unknown event received : " + event.toString());
+ }
+ } else {
+ // log wrong number of parameters returned for execution event
+ logger.log(Level.WARNING, "Wrong number of parameters received for event " + event.toString());
+ }
+ // return the previous userContext
+ return userContext;
+ }
+
+ /**
+ * Creates a Open Telemetry Span and sets it's attributes according to the
+ * trace context and the configuration.
+ *
+ * @param traceContext the trace context.
+ * @param spanName then span name.
+ * @return returns the Span.
+ */
+ private Span initAndGetSpan(TraceContext traceContext, String spanName) {
+ /*
+ * If this is in the context of current span, the following becomes a nested or
+ * child span to the current span. I.e. the current span in context becomes
+ * parent to this child span.
+ */
+ Tracer tracer = GlobalOpenTelemetry.get().getTracer(OTelTracer.class.getName());
+ SpanBuilder spanBuilder = tracer
+ .spanBuilder(spanName)
+ .setAttribute("thread.id", Thread.currentThread().getId())
+ .setAttribute("thread.name", Thread.currentThread().getName())
+ .setAttribute("Connection ID", traceContext.getConnectionId())
+ .setAttribute("Database Operation", traceContext.databaseOperation())
+ .setAttribute("Database Tenant", traceContext.tenant())
+ .setAttribute("SQL ID", traceContext.getSqlId());
+
+ // Add sensitive information (URL and SQL) if it is enabled
+ if (configuration.getSensitiveDataEnabled()) {
+ logger.log(Level.FINEST, "Sensitive information on");
+ spanBuilder
+ .setAttribute("Database User", traceContext.user())
+ .setAttribute("Original SQL Text", traceContext.originalSqlText())
+ .setAttribute("Actual SQL Text", traceContext.actualSqlText());
+ }
+
+ // According to the semantic conventions the Span Kind should be CLIENT,
+ // used to be SERVER.
+ return spanBuilder.setSpanKind(SpanKind.CLIENT).startSpan();
+
+ }
+
+ /**
+ * Sets the span as the current Open Telemetry Span and sends context information
+ * to the database server.
+ *
+ * @param traceContext the trace context
+ * @param span the currect spans
+ */
+ private void makeSpanCurrentAndSendContextToServer(TraceContext traceContext, Span span) {
+ final String traceParent = initAndGetTraceParent(span);
+ final String traceState = initAndGetTraceState(span);
+
+ try (Scope ignored = span.makeCurrent()) {
+ // Send the current context to the server
+ traceContext.setClientInfo(TRACE_KEY, traceParent + traceState);
+ } catch (Exception ex) {
+ logger.log(Level.WARNING, "An error occured while sending the current Open Telemetry context to the server. "
+ + ex.getMessage(), ex);
+ }
+ }
+
+ /**
+ * Formats the current Open Telemetry context in a format that the server can
+ * understand.
+ *
+ * @param span the current Span
+ * @return the current Open Telemetry context formatted so that the server
+ * can understand.
+ */
+ private String initAndGetTraceParent(Span span) {
+ final SpanContext spanContext = span.getSpanContext();
+ final String traceId = spanContext.getTraceId();
+ // parent-id is known as the span-id
+ final String parentId = spanContext.getSpanId();
+ final String traceFlags = spanContext.getTraceFlags().toString();
+
+ return String.format(TRACE_FORMAT, TRACE_VERSION, traceId, parentId, traceFlags);
+ }
+
+ /**
+ * Formats the current Open Telemetry Span state in a format that the server
+ * can understand.
+ *
+ * @param span the current Span
+ * @return the current Open Telemetry Span state formatted so that the server
+ * can understand.
+ */
+ private String initAndGetTraceState(Span span) {
+ final TraceState traceState = span.getSpanContext().getTraceState();
+ final StringBuilder stringBuilder = new StringBuilder();
+
+ traceState.forEach((k, v) -> stringBuilder.append(k).append("=").append(v));
+ return String.format(TRACE_STATE_FORMAT, stringBuilder);
+ }
+
+}
diff --git a/ojdbc-provider-observability/src/main/resources/META-INF/services/oracle.jdbc.spi.TraceEventListenerProvider b/ojdbc-provider-observability/src/main/resources/META-INF/services/oracle.jdbc.spi.TraceEventListenerProvider
new file mode 100644
index 00000000..b1c86eef
--- /dev/null
+++ b/ojdbc-provider-observability/src/main/resources/META-INF/services/oracle.jdbc.spi.TraceEventListenerProvider
@@ -0,0 +1,2 @@
+oracle.jdbc.provider.observability.ObservabilityTraceEventListenerProvider
+oracle.jdbc.provider.observability.OpenTelemetryTraceEventListenerProvider
\ No newline at end of file
diff --git a/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/BackwardCompatibilityTest.java b/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/BackwardCompatibilityTest.java
new file mode 100644
index 00000000..81e4e7f9
--- /dev/null
+++ b/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/BackwardCompatibilityTest.java
@@ -0,0 +1,119 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.lang.management.ManagementFactory;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.junit.jupiter.api.Test;
+
+import oracle.jdbc.spi.OracleResourceProvider.Parameter;
+import oracle.jdbc.spi.TraceEventListenerProvider;
+
+public class BackwardCompatibilityTest {
+ private static final String INSTANCE_NAME = "test-instance";
+
+ @Test
+ public void testConfiguration() throws Exception {
+
+ // System properties
+ System.setProperty("oracle.jdbc.provider.opentelemetry.enabled", "true");
+ System.setProperty("oracle.jdbc.provider.opentelemetry.sensitive-enabled", "true");
+
+ TraceEventListenerProvider provider = new OpenTelemetryTraceEventListenerProvider();
+ Map parameters = new HashMap<>();
+ provider.getParameters().forEach(parameter -> {
+ parameters.put(parameter, (CharSequence)INSTANCE_NAME);
+ });
+ ObservabilityTraceEventListener listener = (ObservabilityTraceEventListener)provider.getTraceEventListener(parameters);
+ ObservabilityConfiguration configuration = listener.getObservabilityConfiguration();
+
+ assertEquals(true, configuration.getEnabled());
+ assertEquals("OTEL", configuration.getEnabledTracers());
+ assertEquals(true, configuration.getSensitiveDataEnabled());
+
+ assertEquals(1, configuration.getEnabledTracersAsList().size());
+ assertEquals("OTEL", configuration.getEnabledTracersAsList().get(0));
+
+ // MBean
+ ObjectName objectName = listener.getMBeanObjectName();
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+ String enabled = server.getAttribute(objectName, "Enabled").toString();
+ String enabledTracers = server.getAttribute(objectName, "EnabledTracers").toString();
+ String sensitiveDataEnabled = server.getAttribute(objectName, "SensitiveDataEnabled").toString();
+
+ assertEquals(enabled, "true");
+ assertEquals(enabledTracers, "OTEL");
+ assertEquals(sensitiveDataEnabled, "true");
+
+ server.setAttribute(objectName, new Attribute("Enabled", false));
+ server.setAttribute(objectName, new Attribute("SensitiveDataEnabled", false));
+
+ assertEquals(false, configuration.getEnabled());
+ assertEquals(false, configuration.getSensitiveDataEnabled());
+
+ assertEquals("OTEL", configuration.getEnabledTracers());
+ assertEquals(false, configuration.getSensitiveDataEnabled());
+
+ assertEquals(1, configuration.getEnabledTracersAsList().size());
+ assertEquals("OTEL", configuration.getEnabledTracersAsList().get(0));
+
+ // Singleton
+ configuration.setEnabled(true);
+ configuration.setSensitiveDataEnabled(true);
+
+ enabled = server.getAttribute(objectName, "Enabled").toString();
+ enabledTracers = server.getAttribute(objectName, "EnabledTracers").toString();
+ sensitiveDataEnabled = server.getAttribute(objectName, "SensitiveDataEnabled").toString();
+
+ assertEquals("true", enabled);
+ assertEquals("OTEL", enabledTracers);
+ assertEquals("true", sensitiveDataEnabled);
+
+ assertEquals(1, configuration.getEnabledTracersAsList().size());
+ assertEquals("OTEL", configuration.getEnabledTracersAsList().get(0));
+
+ }
+}
diff --git a/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/ObservabilityConfigurationTest.java b/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/ObservabilityConfigurationTest.java
new file mode 100644
index 00000000..df8e2ab6
--- /dev/null
+++ b/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/ObservabilityConfigurationTest.java
@@ -0,0 +1,203 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.lang.management.ManagementFactory;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.junit.jupiter.api.Test;
+
+import oracle.jdbc.spi.TraceEventListenerProvider;
+import oracle.jdbc.spi.OracleResourceProvider.Parameter;
+
+public class ObservabilityConfigurationTest {
+
+ private static final String INSTANCE_NAME = "configuration-single";
+ private static final String INSTANCE_NAME_1 = "configuration-test-one";
+ private static final String INSTANCE_NAME_2 = "configuration-test-two";
+
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+ // Set system properties before starting
+ static {
+ System.setProperty("oracle.jdbc.provider.observability.enabledTracers", "JFR");
+ System.setProperty("oracle.jdbc.provider.observability.sensitiveDataEnabled", "true");
+ }
+
+ @Test
+ public void testConfiguration() throws Exception {
+
+ // Create a TraceEventListner named test-instance
+ TraceEventListenerProvider provider = new ObservabilityTraceEventListenerProvider();
+ ObservabilityTraceEventListener listener = createTraceEventListener(provider, INSTANCE_NAME);
+
+ // Get the configuration object
+ ObservabilityConfiguration configuration = listener.getObservabilityConfiguration();
+
+ // Verify that listener one is configured with values from system properties
+ verifyConfiguration(configuration, listener.getMBeanObjectName(), "JFR", 1, true);
+
+ // Update configuration using MBean
+ server.setAttribute(listener.getMBeanObjectName(), new Attribute("EnabledTracers", "OTEL, JFR"));
+ server.setAttribute(listener.getMBeanObjectName(), new Attribute("SensitiveDataEnabled", false));
+
+ // check that the values have been updated using the instance of the configuration
+ verifyConfiguration(configuration, listener.getMBeanObjectName(), "OTEL,JFR", 2, false);
+
+ // Update the configuration using the instance of the configuration
+ configuration.setEnabledTracers("OTEL");
+ configuration.setSensitiveDataEnabled(true);
+
+ // Check that the values returned by the MBean correspond to the values set using the instance
+ verifyConfiguration(configuration, listener.getMBeanObjectName(), "OTEL", 1, true);
+
+ }
+
+ @Test
+ public void testConfigurationWith2Instances() throws Exception {
+
+ // Create a TraceEventListner named test-instance
+ TraceEventListenerProvider provider = new ObservabilityTraceEventListenerProvider();
+ ObservabilityTraceEventListener listener1 = createTraceEventListener(provider, INSTANCE_NAME_1);
+ ObservabilityTraceEventListener listener2 = createTraceEventListener(provider, INSTANCE_NAME_2);
+
+ // Verify that listener one is configured with values from system properties
+ verifyConfiguration(listener1.getObservabilityConfiguration(),
+ listener1.getMBeanObjectName(), "JFR", 1, true);
+
+ // Verify that listener two is configured with values from system properties
+ verifyConfiguration(listener2.getObservabilityConfiguration(),
+ listener2.getMBeanObjectName(), "JFR", 1, true);
+
+ // Update configuration one using MBean
+ server.setAttribute(listener1.getMBeanObjectName(), new Attribute("EnabledTracers", "OTEL,JFR"));
+ server.setAttribute(listener1.getMBeanObjectName(), new Attribute("SensitiveDataEnabled", false));
+
+ // Verify that listener one's configuration with the values set using the MBean
+ verifyConfiguration(listener1.getObservabilityConfiguration(),
+ listener1.getMBeanObjectName(), "OTEL,JFR", 2, false);
+
+ // Verify that listener two's configuration did not change
+ verifyConfiguration(listener2.getObservabilityConfiguration(),
+ listener2.getMBeanObjectName(), "JFR", 1, true);
+
+ // Update the configuration using the instance of the configuration
+ ObservabilityConfiguration configuration2 = listener2.getObservabilityConfiguration();
+ configuration2.setEnabledTracers("OTEL");
+ configuration2.setSensitiveDataEnabled(false);
+
+ // Verify that listener one's configuration did not change
+ verifyConfiguration(listener1.getObservabilityConfiguration(),
+ listener1.getMBeanObjectName(), "OTEL,JFR", 2, false);
+
+ // Verify that listener two's configuration has been updated
+ verifyConfiguration(listener2.getObservabilityConfiguration(),
+ listener2.getMBeanObjectName(), "OTEL", 1, false);
+
+ }
+
+ @Test
+ public void testDefaultUniqueIdentifier() throws Exception {
+
+ // Create a TraceEventListner named test-instance
+ TraceEventListenerProvider provider = new ObservabilityTraceEventListenerProvider();
+ ObservabilityTraceEventListener listener = (ObservabilityTraceEventListener)provider.getTraceEventListener(new HashMap<>());
+
+ // Get the configuration object
+ ObservabilityConfiguration configuration = listener.getObservabilityConfiguration();
+
+ // Verify that listener one is configured with values from system properties
+ verifyConfiguration(configuration, listener.getMBeanObjectName(), "JFR", 1, true);
+
+ // Update configuration using MBean
+ server.setAttribute(listener.getMBeanObjectName(), new Attribute("EnabledTracers", "OTEL, JFR"));
+ server.setAttribute(listener.getMBeanObjectName(), new Attribute("SensitiveDataEnabled", false));
+
+ // check that the values have been updated using the instance of the configuration
+ verifyConfiguration(configuration, listener.getMBeanObjectName(), "OTEL,JFR", 2, false);
+
+ // Update the configuration using the instance of the configuration
+ configuration.setEnabledTracers("OTEL");
+ configuration.setSensitiveDataEnabled(true);
+
+ // Check that the values returned by the MBean correspond to the values set using the instance
+ verifyConfiguration(configuration, listener.getMBeanObjectName(), "OTEL", 1, true);
+
+ }
+
+ private ObservabilityTraceEventListener createTraceEventListener(TraceEventListenerProvider provider,
+ String instanceName) {
+ Map parameters = new HashMap<>();
+ provider.getParameters().forEach(parameter -> {
+ parameters.put(parameter, (CharSequence)instanceName);
+ });
+ return (ObservabilityTraceEventListener)provider.getTraceEventListener(parameters);
+ }
+
+ private void verifyConfiguration(ObservabilityConfiguration configuration,
+ ObjectName mBeanObjectName,
+ String expectedTracers,
+ int expectedTracerCount,
+ boolean expectedSensitiveDataEnabled) throws Exception{
+
+ String[] expectedTracersArray = expectedTracers.split(",");
+ // Verify that the configuration matches the configuration set using system properties
+ assertEquals(expectedTracers, configuration.getEnabledTracers());
+ assertEquals(expectedSensitiveDataEnabled, configuration.getSensitiveDataEnabled());
+ assertEquals(expectedTracerCount, configuration.getEnabledTracersAsList().size());
+ assertEquals(expectedTracerCount, expectedTracersArray.length, "Wrong number of tracers.");
+ for (int i = 0; i < expectedTracerCount; i++) {
+ assertEquals(expectedTracersArray[i], configuration.getEnabledTracersAsList().get(i));
+ }
+
+ // Get configuration using MBean and check that it matches the configuration set using system properties
+ String enabledTracers = server.getAttribute(mBeanObjectName, "EnabledTracers").toString();
+ String sensitiveDataEnabled = server.getAttribute(mBeanObjectName, "SensitiveDataEnabled").toString();
+ assertEquals(enabledTracers, expectedTracers);
+ assertEquals(Boolean.parseBoolean(sensitiveDataEnabled), expectedSensitiveDataEnabled);
+
+ }
+
+}
diff --git a/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/ObservabilityTestProperties.java b/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/ObservabilityTestProperties.java
new file mode 100644
index 00000000..7a765d5a
--- /dev/null
+++ b/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/ObservabilityTestProperties.java
@@ -0,0 +1,44 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability;
+
+public enum ObservabilityTestProperties {
+ OBSERVABILITY_URL,
+ OBSERVABILITY_USERNAME,
+ OBSERVABILITY_PASSWORD
+}
diff --git a/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/ObservabilityTraceEventListenerTest.java b/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/ObservabilityTraceEventListenerTest.java
new file mode 100644
index 00000000..52432893
--- /dev/null
+++ b/ojdbc-provider-observability/src/test/java/oracle/jdbc/provider/observability/ObservabilityTraceEventListenerTest.java
@@ -0,0 +1,235 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+package oracle.jdbc.provider.observability;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
+
+import java.nio.file.Path;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.Mockito;
+
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.api.metrics.MeterBuilder;
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.api.trace.SpanBuilder;
+import io.opentelemetry.api.trace.SpanContext;
+import io.opentelemetry.api.trace.SpanKind;
+import io.opentelemetry.api.trace.TraceFlags;
+import io.opentelemetry.api.trace.TraceState;
+import io.opentelemetry.api.trace.Tracer;
+import io.opentelemetry.api.trace.TracerProvider;
+import jdk.jfr.Configuration;
+import jdk.jfr.Recording;
+import jdk.jfr.consumer.RecordedEvent;
+import jdk.jfr.consumer.RecordingFile;
+import oracle.jdbc.DatabaseFunction;
+import oracle.jdbc.driver.OracleConnection;
+import oracle.jdbc.provider.TestProperties;
+
+public class ObservabilityTraceEventListenerTest {
+ String url = TestProperties.getOrAbort(ObservabilityTestProperties.OBSERVABILITY_URL);
+ String userName = TestProperties.getOrAbort(ObservabilityTestProperties.OBSERVABILITY_USERNAME);
+ String password = TestProperties.getOrAbort(ObservabilityTestProperties.OBSERVABILITY_PASSWORD);
+
+ // JFR
+ private static final String SESSION_KEY = "oracle.jdbc.provider.observability.RoundTrip.SESSION_KEY";
+ private static final String AUTH_CALL = "oracle.jdbc.provider.observability.RoundTrip.AUTH_CALL";
+ private static final String EXECUTE_QUERY = "oracle.jdbc.provider.observability.RoundTrip.EXECUTE_QUERY";
+ private static final String LOGOFF = "oracle.jdbc.provider.observability.RoundTrip.LOGOFF";
+
+ // OTEL
+ private static final OpenTelemetry openTelemetry = Mockito.mock(OpenTelemetry.class);
+ private static final Span span = Mockito.mock(Span.class);
+ private static final SpanContext spanContext = Mockito.mock(SpanContext.class);
+ private static final TraceFlags traceFlags = Mockito.mock(TraceFlags.class);
+ private static final TraceState traceState = Mockito.mock(TraceState.class);
+ private static final SpanBuilder spanBuilder = Mockito.mock(SpanBuilder.class);
+ private static final TracerProvider tracerProvider = Mockito.mock(TracerProvider.class);
+ private static final Tracer tracer = Mockito.mock(Tracer.class);
+ private static final MeterBuilder meterBuilder = Mockito.mock(MeterBuilder.class);
+
+ static {
+ GlobalOpenTelemetry.set(openTelemetry);
+ configureOTEL();
+ }
+
+ @ParameterizedTest(name = "JFRTraceTest - {arguments}")
+ @ValueSource(booleans = {true, false})
+ public void JFRTraceTest(boolean sensitiveDataEnabled) throws Exception {
+
+ System.setProperty("oracle.jdbc.provider.observability.enabledTracers", "JFR");
+ System.setProperty("oracle.jdbc.provider.observability.sensitiveDataEnabled", String.valueOf(sensitiveDataEnabled));
+ Configuration configuration = Configuration.getConfiguration("default");
+ String connectionId = null;
+ try (Recording recording = new Recording(configuration)) {
+ recording.start();
+ String jfrUrl = url + "?oracle.jdbc.provider.traceEventListener=observability-trace-event-listener-provider&oracle.jdbc.provider.traceEventListener.unique_identifier=test-jfr" + sensitiveDataEnabled;
+ try (Connection connection = DriverManager.getConnection(jfrUrl, userName, password);
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SELECT 'OK' FROM DUAL")) {
+ connectionId = ((OracleConnection)connection).getNetConnectionId();
+ while (resultSet.next()) {
+ assertEquals("OK", resultSet.getString(1));
+ }
+ }
+ recording.stop();
+ recording.dump(Path.of("dump" + sensitiveDataEnabled + ".jfr"));
+
+ try (RecordingFile recordingFile = new RecordingFile(Path.of("dump" + sensitiveDataEnabled + ".jfr"))) {
+ int countRoundTrips = 0;
+ while (recordingFile.hasMoreEvents()) {
+ RecordedEvent event = recordingFile.readEvent();
+ if (event.getEventType().getCategoryNames().contains("Round trips")) {
+ countRoundTrips++;
+ switch (event.getEventType().getName()) {
+ case SESSION_KEY:
+ assertEquals(connectionId, event.getString("connectionID"));
+ assertNotNull(event.getString("databaseOperation"));
+ assertNull(event.getString("sqlID"));
+ assertNull(event.getString("originalSQLText"));
+ assertNull(event.getString("actualSQLText"));
+ assertEquals(sensitiveDataEnabled, event.getString("databaseUser") != null);
+ break;
+ case AUTH_CALL:
+ assertEquals(connectionId, event.getString("connectionID"));
+ assertNotNull(event.getString("databaseOperation"));
+ assertNull(event.getString("sqlID"));
+ assertNull(event.getString("originalSQLText"));
+ assertNull(event.getString("actualSQLText"));
+ assertEquals(sensitiveDataEnabled, event.getString("databaseUser") != null);
+
+ break;
+ case EXECUTE_QUERY:
+ assertEquals(connectionId, event.getString("connectionID"));
+ assertNotNull(event.getString("databaseOperation"));
+ assertNotNull(event.getString("sqlID"));
+ assertEquals(sensitiveDataEnabled, event.getString("originalSQLText") != null);
+ assertEquals(sensitiveDataEnabled, event.getString("actualSQLText") != null);
+ assertEquals(sensitiveDataEnabled, event.getString("databaseUser") != null);
+ break;
+ case LOGOFF:
+ assertEquals(connectionId, event.getString("connectionID"));
+ assertNotNull(event.getString("databaseOperation"));
+ assertNull(event.getString("sqlID"));
+ assertNull(event.getString("originalSQLText"));
+ assertNull(event.getString("actualSQLText"));
+ assertEquals(sensitiveDataEnabled, event.getString("databaseUser") != null);
+ break;
+ default:
+ fail("Unexpected event");
+ }
+ }
+ }
+ assertTrue(countRoundTrips > 0, "Application should have performed at least one round trip");
+ }
+ }
+
+ }
+
+ @ParameterizedTest(name = "OTELTraceTest - {arguments}")
+ @ValueSource(booleans = {true, false})
+ public void OTELTraceTest(boolean sensitiveDataEnabled) throws Exception {
+ Mockito.clearInvocations(tracer, spanBuilder);
+ System.setProperty("oracle.jdbc.provider.observability.enabledTracers", "OTEL");
+ System.setProperty("oracle.jdbc.provider.observability.sensitiveDataEnabled", String.valueOf(sensitiveDataEnabled));
+ String otelUrl = url + "?oracle.jdbc.provider.traceEventListener=observability-trace-event-listener-provider&oracle.jdbc.provider.traceEventListener.unique_identifier=test-otel-" + sensitiveDataEnabled ;
+ String connectionId = null;
+ try (Connection connection = DriverManager.getConnection(otelUrl, userName, password);
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SELECT 'OK' FROM DUAL")) {
+ connectionId = ((OracleConnection)connection).getNetConnectionId();
+ while (resultSet.next()) {
+ assertEquals("OK", resultSet.getString(1));
+ }
+ }
+
+ Mockito.verify(tracer, atLeastOnce()).spanBuilder(DatabaseFunction.SESSION_KEY.getDescription());
+ Mockito.verify(tracer, atLeastOnce()).spanBuilder(DatabaseFunction.AUTH_CALL.getDescription());
+ Mockito.verify(tracer, atLeastOnce()).spanBuilder(DatabaseFunction.EXECUTE_QUERY.getDescription());
+ Mockito.verify(tracer, atLeastOnce()).spanBuilder(DatabaseFunction.LOGOFF.getDescription());
+ Mockito.verify(spanBuilder, atLeastOnce()).startSpan();
+ Mockito.verify(spanBuilder, Mockito.atLeast(4)).setAttribute("thread.id", Thread.currentThread().getId());
+ Mockito.verify(spanBuilder, Mockito.atLeast(4)).setAttribute("thread.name", Thread.currentThread().getName());
+ Mockito.verify(spanBuilder, Mockito.atLeast(1)).setAttribute("Connection ID", connectionId);
+ Mockito.verify(spanBuilder, Mockito.times(1)).setAttribute("Database Operation", DatabaseFunction.SESSION_KEY.getDescription());
+ Mockito.verify(spanBuilder, Mockito.times(1)).setAttribute("Database Operation", DatabaseFunction.AUTH_CALL.getDescription());
+ Mockito.verify(spanBuilder, Mockito.times(1)).setAttribute("Database Operation", DatabaseFunction.EXECUTE_QUERY.getDescription());
+ Mockito.verify(spanBuilder, Mockito.times(1)).setAttribute("Database Operation", DatabaseFunction.LOGOFF.getDescription());
+ if (sensitiveDataEnabled) {
+ Mockito.verify(spanBuilder, Mockito.times(4)).setAttribute("Database User", userName);
+ Mockito.verify(spanBuilder, Mockito.times(1)).setAttribute("Original SQL Text", "SELECT 'OK' FROM DUAL");
+ Mockito.verify(spanBuilder, Mockito.times(1)).setAttribute("Actual SQL Text", "SELECT 'OK' FROM DUAL");
+ } else {
+ Mockito.verify(spanBuilder, Mockito.times(0)).setAttribute("Database User", userName);
+ Mockito.verify(spanBuilder, Mockito.times(0)).setAttribute("Original SQL Text", "SELECT 'OK' FROM DUAL");
+ Mockito.verify(spanBuilder, Mockito.times(0)).setAttribute("Actual SQL Text", "SELECT 'OK' FROM DUAL");
+ }
+ Mockito.verify(span, atLeast(4)).end();
+
+ }
+
+ private static void configureOTEL() {
+ Mockito.when(openTelemetry.getTracerProvider()).thenReturn(tracerProvider);
+ Mockito.when(tracerProvider.get(Mockito.anyString())).thenReturn(tracer);
+ Mockito.when(openTelemetry.meterBuilder(Mockito.anyString())).thenReturn(meterBuilder);
+ Mockito.when(spanContext.getTraceFlags()).thenReturn(traceFlags);
+ Mockito.when(spanContext.getTraceState()).thenReturn(traceState);
+ Mockito.when(span.getSpanContext()).thenReturn(spanContext);
+ Mockito.when(spanBuilder.setAttribute(Mockito.anyString(), Mockito.anyString())).thenReturn(spanBuilder);
+ Mockito.when(spanBuilder.setAttribute(Mockito.anyString(), Mockito.anyLong())).thenReturn(spanBuilder);
+ Mockito.when(spanBuilder.setAttribute(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(spanBuilder);
+ Mockito.when(spanBuilder.setAttribute(Mockito.anyString(), Mockito.any())).thenReturn(spanBuilder);
+ Mockito.when(spanBuilder.setSpanKind(Mockito.any(SpanKind.class))).thenReturn(spanBuilder);
+ Mockito.when(spanBuilder.startSpan()).thenReturn(span);
+ Mockito.when(tracer.spanBuilder(Mockito.anyString())).thenReturn(spanBuilder);
+ }
+
+}
diff --git a/ojdbc-provider-opentelemetry/src/main/java/oracle/jdbc/provider/opentelemetry/OpenTelemetryTraceEventListener.java b/ojdbc-provider-opentelemetry/src/main/java/oracle/jdbc/provider/opentelemetry/OpenTelemetryTraceEventListener.java
index 00ac32c7..4c63944d 100644
--- a/ojdbc-provider-opentelemetry/src/main/java/oracle/jdbc/provider/opentelemetry/OpenTelemetryTraceEventListener.java
+++ b/ojdbc-provider-opentelemetry/src/main/java/oracle/jdbc/provider/opentelemetry/OpenTelemetryTraceEventListener.java
@@ -73,9 +73,9 @@
*
*
* The system properties
- * {@value #OPEN_TELEMENTRY_TRACE_EVENT_LISTENER_ENABLED}
+ * {@value #OPEN_TELEMETRY_TRACE_EVENT_LISTENER_ENABLED}
* and
- * {@value #OPEN_TELEMENTRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED}
+ * {@value #OPEN_TELEMETRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED}
* can be used
* to enable/disable this listener and the use of sensitive data by this
* listener. A MBean registered by the {@link
@@ -88,12 +88,12 @@ public class OpenTelemetryTraceEventListener
/**
* Name of the property used to enable or disable this listener.
*/
- public static final String OPEN_TELEMENTRY_TRACE_EVENT_LISTENER_ENABLED = "oracle.jdbc.provider.opentelemetry.enabled";
+ public static final String OPEN_TELEMETRY_TRACE_EVENT_LISTENER_ENABLED = "oracle.jdbc.provider.opentelemetry.enabled";
/**
* Name of the property used to enable or disable sensitive data for this
* listener.
*/
- public static final String OPEN_TELEMENTRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED = "oracle.jdbc.provider.opentelemetry.sensitive-enabled";
+ public static final String OPEN_TELEMETRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED = "oracle.jdbc.provider.opentelemetry.sensitive-enabled";
private static final String TRACE_KEY = "clientcontext.ora$opentelem$tracectx";
@@ -107,7 +107,7 @@ public class OpenTelemetryTraceEventListener
}
};
- private static Logger logger = Logger.getLogger(OpenTelemetryTraceEventListener.class.getName());
+ private static Logger logger = Logger.getLogger(OpenTelemetryTraceEventListener.class.getPackageName());
private Tracer tracer;
@@ -132,8 +132,8 @@ private enum Configuration {
private AtomicBoolean sensitiveDataEnabled;
private Configuration(boolean enabled, boolean sensitiveDataEnabled) {
- String enabledStr = System.getProperty(OPEN_TELEMENTRY_TRACE_EVENT_LISTENER_ENABLED);
- String sensitiveStr = System.getProperty(OPEN_TELEMENTRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED);
+ String enabledStr = System.getProperty(OPEN_TELEMETRY_TRACE_EVENT_LISTENER_ENABLED);
+ String sensitiveStr = System.getProperty(OPEN_TELEMETRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED);
this.enabled = new AtomicBoolean(enabledStr == null ? enabled : Boolean.parseBoolean(enabledStr));
this.sensitiveDataEnabled = new AtomicBoolean(
sensitiveStr == null ? sensitiveDataEnabled : Boolean.parseBoolean(sensitiveStr));
diff --git a/ojdbc-provider-opentelemetry/src/test/java/oracle/jdbc/provider/opentelemetry/OpenTelemetryTraceEventListenerTest.java b/ojdbc-provider-opentelemetry/src/test/java/oracle/jdbc/provider/opentelemetry/OpenTelemetryTraceEventListenerTest.java
index 8bac137e..3fd05dba 100644
--- a/ojdbc-provider-opentelemetry/src/test/java/oracle/jdbc/provider/opentelemetry/OpenTelemetryTraceEventListenerTest.java
+++ b/ojdbc-provider-opentelemetry/src/test/java/oracle/jdbc/provider/opentelemetry/OpenTelemetryTraceEventListenerTest.java
@@ -97,8 +97,8 @@ public void setupMocks() throws Exception {
@Test
void testPropertiesDisabled() throws Exception {
- System.setProperty(OpenTelemetryTraceEventListener.OPEN_TELEMENTRY_TRACE_EVENT_LISTENER_ENABLED, "false");
- System.setProperty(OpenTelemetryTraceEventListener.OPEN_TELEMENTRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED, "false");
+ System.setProperty(OpenTelemetryTraceEventListener.OPEN_TELEMETRY_TRACE_EVENT_LISTENER_ENABLED, "false");
+ System.setProperty(OpenTelemetryTraceEventListener.OPEN_TELEMETRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED, "false");
OpenTelemetryTraceEventListener traceEventListener = new OpenTelemetryTraceEventListener(tracer);
Assertions.assertFalse(traceEventListener.isEnabled(), "Set to false using system property");
Assertions.assertFalse(traceEventListener.isSensitiveDataEnabled(), "Set to false using system property");
@@ -106,8 +106,8 @@ void testPropertiesDisabled() throws Exception {
@Test
void testPropertiesEnabled() throws Exception {
- System.setProperty(OpenTelemetryTraceEventListener.OPEN_TELEMENTRY_TRACE_EVENT_LISTENER_ENABLED, "true");
- System.setProperty(OpenTelemetryTraceEventListener.OPEN_TELEMENTRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED, "true");
+ System.setProperty(OpenTelemetryTraceEventListener.OPEN_TELEMETRY_TRACE_EVENT_LISTENER_ENABLED, "true");
+ System.setProperty(OpenTelemetryTraceEventListener.OPEN_TELEMETRY_TRACE_EVENT_LISTENER_SENSITIVE_ENABLED, "true");
OpenTelemetryTraceEventListener traceEventListener = new OpenTelemetryTraceEventListener(tracer);
Assertions.assertTrue(traceEventListener.isEnabled(), "Set to false using system property");
Assertions.assertTrue(traceEventListener.isSensitiveDataEnabled(), "Set to false using system property");
diff --git a/ojdbc-provider-samples/pom.xml b/ojdbc-provider-samples/pom.xml
index fe4ec2bc..a815c2ee 100644
--- a/ojdbc-provider-samples/pom.xml
+++ b/ojdbc-provider-samples/pom.xml
@@ -5,7 +5,7 @@
Oracle JDBC Provider Code Samples
ojdbc-provider-samples
- ${project.parent.version}
+ 1.0.3
jar
@@ -23,17 +23,17 @@
com.oracle.database.jdbc
ojdbc-provider-azure
- ${project.parent.version}
+ 1.0.3
com.oracle.database.jdbc
ojdbc-provider-oci
- ${project.parent.version}
+ 1.0.3
com.oracle.database.jdbc
ojdbc-provider-jackson-oson
- ${project.parent.version}
+ 1.0.3
com.oracle.database.jdbc
diff --git a/pom.xml b/pom.xml
index 28583708..03ac4cba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,6 +53,15 @@
8
+
+ javac-release-jfr
+
+ [9,)
+
+
+ 11
+
+
@@ -63,6 +72,7 @@
ojdbc-provider-opentelemetry
ojdbc-provider-aws
ojdbc-provider-jackson-oson
+ ojdbc-provider-observability
@@ -77,6 +87,11 @@
ojdbc8
${jdbc.version}
+
+ com.oracle.database.jdbc
+ ojdbc11
+ ${jdbc.version}
+
com.oracle.database.security
oraclepki