Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/marschall/jfr-jdbctemplate

an implementation of Spring JdbcTemplate that generates Flight Recorder events
https://github.com/marschall/jfr-jdbctemplate

java-flight-recorder jdbctemplate spring-jdbctemplate

Last synced: about 1 month ago
JSON representation

an implementation of Spring JdbcTemplate that generates Flight Recorder events

Awesome Lists containing this project

README

        

JFR JdbcTemplate [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.marschall/jfr-jdbctemplate/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.marschall/jfr-jdbctemplate) [![Javadocs](https://www.javadoc.io/badge/com.github.marschall/jfr-jdbctemplate.svg)](https://www.javadoc.io/doc/com.github.marschall/jfr-jdbctemplate)
================

An implementation of Spring [JdbcTemplate](https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#jdbc) that generates [Flight Recorder](https://openjdk.java.net/jeps/328) events.

This project requires Java 11 based on OpenJDK or later.

```xml

com.github.marschall
jfr-jdbctemplate
2.0.0

```

Versions 1.x are intended for Spring 5.x / Java 11, versions 2.x are intended for Spring 6.x / Java 17.

![Flight Recording of a JUnit Test](https://github.com/marschall/jfr-jdbctemplate/raw/master/src/main/javadoc/resources/Screenshot%20from%202019-05-13%2021-09-33.png)

Compared to approaches based on `DataSource` an approach based on `JdbcTemplate` has the advantage that it captures a complete database interaction. For example if you process many rows the initial `PreparedStatement#execute()` might be fast but most of the time may be spent in `ResultSet#next()`. A `JdbcTemplate` based approach generates a single JFR event for the entire interaction that involves several JDBC method invocations.

Spring Class | JFR Class |
|-------------------------------------------------------------------------|------------------------------------------------------------------------|
| `org.springframework.jdbc.core.JdbcOperations` | `com.github.marschall.jfr.jdbctemplate.JfrJdbcOperations` |
| `org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations` | `com.github.marschall.jfr.jdbctemplate.JfrNamedParameterJdbcOperations` |

Reported Attributes
-------------------


operationName

The name of the execute JDBC operation, this corresponds to the method name on JdbcOperations/JdbcTemplate.

query

The SQL query string passed to the JDBC driver. May be missing especially if custom org.springframework.jdbc.core.PreparedStatementCreator fail to implement org.springframework.jdbc.core.SqlProvider.

rowCount

In the case of a SELECT the number of rows returned. In the case of an UPDATE or DELETE the number of rows affected. -1 for a statement that does not return anything like a DDL. -2 when no information about the number of rows is available.

Overhead
--------

We try to keep overhead to a minimum and have no additional allocations besides the JFR events. Besides the overhead of the event the only additional overhead is:

* a wrapper around `JdbcTemplate`
* a few `instanceof` operations and casts
* a `finally` block
* a capturing lambda for `#queryForStream` methods to record `Stream#close` as the end time of the event
* a small wrapper around every `RowCallbackHandler`

We assume `org.springframework.jdbc.core.SqlProvider#getSql()` is a simple getter.

Usage
-----

```java
@Configuration
public class JdbcConfiguration {

@Autowired
private DataSource dataSource;

@Bean
public JdbcOperations jdbcOperations() {
return new JfrJdbcOperations(new JdbcTemplate(this.dataSource));
}

@Bean
public NamedParameterJdbcOperations namedParameterJdbcOperations() {
return new JfrNamedParameterJdbcOperations(new NamedParameterJdbcTemplate(this.jdbcOperations()));
}

}
```

You need something like the following JVM options to run Flight Recorder

```
-XX:StartFlightRecording:filename=recording.jfr
-XX:FlightRecorderOptions:stackdepth=128
```

Limitations
-----------

* When the SQL query is not provided as a `String` but as a `PreparedStatementCreator` or `CallableStatementCreator` it has to implement `SqlProvider` for the query string to show up in the flight recording.
* `JdbcTemplate#query(PreparedStatementCreator, PreparedStatementSetter, ResultSetExtractor)` is not available because it is defined on `JdbcTemplate` and not `JdbcOperations`.
* Several spring-jdbc classes `AbstractJdbcCall`, `SimpleJdbcCall`, `StoredProcedure`, `RdbmsOperation`, `AbstractJdbcInsert`, `SimpleJdbcInsert` but also `JdbcTestUtils` and `JdbcBeanDefinitionReader` require a `JdbcTemplate` and do not work with `JdbcOperations`. We have a [pull request](https://github.com/spring-projects/spring-framework/pull/23066/files) open for this but it has not been merged yet.
* `JdbcOperations#execute(ConnectionCallback)` can not provide any insight into what is executed inside, that would require integration with [marschall/jfr-jdbc](https://github.com/marschall/jfr-jdbc)