-
Notifications
You must be signed in to change notification settings - Fork 944
Add R2dbc statement javaagent instrumentation #7977
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add R2dbc statement javaagent instrumentation #7977
Conversation
...vaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/DbExecution.java
Outdated
Show resolved
Hide resolved
|
||
@Override | ||
public boolean isHelperClass(String className) { | ||
return className.startsWith("io.r2dbc.proxy"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The drawback of doing it this way is that when the application also contains the r2dbc-proxy
library there may be incompatibilities unless the library bundled in the agent has the same version that the application has.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your feedback.
So the alternative would be to basically reimplement the r2dbc-proxy
library in order to get Query Listeners just to not use r2dbx-proxy
directly? It just seemed a bit redundant to me, but I get your point.
After @marcingrzejszczak #7977 (comment), should I be simply using the existing ObservationProxyExecutionListener or stick to the manually implemented TraceProxyListener
, or even move away entirely from r2dbc-proxy
for the auto instrumentation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could shade the r2dbc-proxy
library under a different package so it wouldn't conflict with whatever is in the application. I think this isn't super important, we can always fix it later. @marcingrzejszczak is one of the authors of micrometer tracing. As for his suggestion I'm not quite sure what he means. It could be either that he is suggesting to implement some sort of bridge with micrometer api so that their instrumentations could be automatically used or he might be hinting that instead of implementing this instrumentation for opentelemetry you could be using micrometer tracing where this instrumentation already exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I'm suggesting that since the instrumentation is there providing a bridge would mean you have nothing to do 🤷 Otherwise you can just replicate the same code but use the OTel API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could shade the
r2dbc-proxy
library under a different package so it wouldn't conflict with whatever is in the application.
We're doing a similar thing in the couchbase instrumentation. @PhilKes you could probably implement it in a somewhat similar manner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could shade the
r2dbc-proxy
library under a different package so it wouldn't conflict with whatever is in the application.We're doing a similar thing in the couchbase instrumentation. @PhilKes you could probably implement it in a somewhat similar manner.
@mateuszrzeszutek I tried to shade the r2dbc-proxy
the same way as in the couchbase instrumentation, but I ran into a problem when running the tests:
R2dbcStatementTest > testQueries(Parameter) > io.opentelemetry.javaagent.instrumentation.r2dbc.v1_0.R2dbcStatementTest.testQueries(Parameter)[8] FAILED
java.util.ServiceConfigurationError: io.r2dbc.spi.ConnectionFactoryProvider: Provider io.r2dbc.proxy.ProxyConnectionFactoryProvider not found
at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:593)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(ServiceLoader.java:1219)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1228)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1273)
at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1309)
at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1393)
at io.r2dbc.spi.ConnectionFactories.find(ConnectionFactories.java:108)
at io.opentelemetry.javaagent.instrumentation.r2dbc.v1_0.AbstractR2dbcStatementTest.createProxyConnectionFactory(AbstractR2dbcStatementTest.java:93)
at io.opentelemetry.javaagent.instrumentation.r2dbc.v1_0.R2dbcStatementTest.createProxyConnectionFactory(R2dbcStatementTest.java:44)
I dont get why ConnectionFactoryProvider
looks for the io.r2dbc.proxy
package, the shaded imports work everywhere else and the ServiceLoader
should find the ProxyConnectionFactoryProvider
in the io.opentelemetry.javaagent.instrumentation.r2dbc.v1_0.shaded.io.r2dbc.proxy
package, or is there something wrong with the shaded r2dbc-proxy
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.../src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/TraceProxyListener.java
Outdated
Show resolved
Hide resolved
.../src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/TraceProxyListener.java
Outdated
Show resolved
Hide resolved
...rc/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/R2dbcInstrumentation.java
Outdated
Show resolved
Hide resolved
...vaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/DbExecution.java
Outdated
Show resolved
Hide resolved
...vaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/DbExecution.java
Outdated
Show resolved
Hide resolved
BTW you can use Micrometer Observation API that is already there in R2DBC proxy (https://github.com/r2dbc/r2dbc-proxy/tree/main/src/main/java/io/r2dbc/proxy/observation) to have the instrumentation done for you. |
No, you shouldn't worry about keeping it 1:1 with JDBC.
I think both of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @PhilKes !
...rary/src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/R2dbcTelemetry.java
Outdated
Show resolved
Hide resolved
ConnectionFactory proxiedFactory = | ||
ProxyConnectionFactory.builder(originalConnectionFactory) | ||
.listener(new TraceProxyListener(instrumenterBuilder.build(), connectionFactoryOptions)) | ||
.build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this part should live in the R2dbcTelemetry
class - instead of the getConnectionFactory
method there should be a wrapConnectionFactory(ConnectionFactory, ConnectionFactoryOptions)
(or similar name) that takes any connection factory and returns a decorated instance. The R2dbcTelemetry
class should include any actual connection factory, it should be possible to use R2dbcTelemetry
to decorate multiple connection factories - at least that's how we're doing it in all other library instrumentations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it into the R2dbcTelemetry
as suggested, so that any number of ConnectionFactory
can be wrapped.
.setStatementSanitizationEnabled( | ||
ConfigPropertiesUtil.getBoolean( | ||
"otel.instrumentation.common.db-statement-sanitizer.enabled", true)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, usually we don't use properties in library instrumentations - instead, we expose a builder method that allows users to configure the setting by themselves. The JDBC library instrumentation is not a good example of that because it utilizes the Driver
decorator approach - where it's not possible to have a builder to configure a setting.
See the CassandraTelemetryBuilder
for an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the the flag as a builder method
...rc/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/R2dbcInstrumentation.java
Outdated
Show resolved
Hide resolved
|
||
@Override | ||
public boolean isHelperClass(String className) { | ||
return className.startsWith("io.r2dbc.proxy"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could shade the
r2dbc-proxy
library under a different package so it wouldn't conflict with whatever is in the application.
We're doing a similar thing in the couchbase instrumentation. @PhilKes you could probably implement it in a somewhat similar manner.
...ary/src/test/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/DbExecutionTest.java
Outdated
Show resolved
Hide resolved
...n/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/AbstractR2dbcStatementTest.java
Show resolved
Hide resolved
...n/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/AbstractR2dbcStatementTest.java
Outdated
Show resolved
Hide resolved
Hey @PhilKes , can you rebase (or clean merge) your branch with |
…o.ValuesStore instead of Map
b379e2f
to
b1009e7
Compare
Sorry for that, I fixed the rebase |
Relocate bundled r2dbc-proxy
@PhilKes to get rid of the muzzle failure https://github.com/open-telemetry/opentelemetry-java-instrumentation/actions/runs/4425709289/jobs/7761112434 Try adding
|
.../src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/TraceProxyListener.java
Outdated
Show resolved
Hide resolved
...n/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/AbstractR2dbcStatementTest.java
Outdated
Show resolved
Hide resolved
...rc/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/internal/DbExecution.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @PhilKes !
Hello all. Thank you so much for your work on supporting thi! I'm unable to get R2DBC tracing on a Spring Boot application running with the javaagent (using the proxy). Is there any particular configuration that is required for this to work? |
hi @juandaco! can you open a new issue? you shouldn't need to make any code changes if you are using the javaagent (e.g. you shouldn't need to use a proxy) and if you can post a minimal repro that is usually the easiest way for folks to understand and help out |
This PR resolves #2515 .
It adds javaagent instrumentation for r2dbc-spi >= v1.0
As suggested by @mp911de in #2515 (comment) I used the r2dbc-proxy
ProxyConnectionFactory
to intercept Database query executions and create according spans.Example span from example project using spring-boot-starter-data-r2dbc Application:
