Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions instrumentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Here's a brief overview of what's packaged here:
* [httpclient](httpclient/README.md) - Tracing decorator for [Apache HttpClient](http://hc.apache.org/httpcomponents-client-4.4.x/index.html) 4.3+
* [jaxrs2](jaxrs2/README.md) - Client tracing filter and span customizing resource filter for JAX-RS 2.x
* [jersey-server](jersey-server/README.md) - Tracing and span customizing application event listeners for [Jersey Server](https://jersey.github.io/documentation/latest/monitoring_tracing.html#d0e16007).
* [jdbi3](jdbi3/README.md) - Tracing decorators for [JDBI 3](https://jdbi.org/) SQL statements.
* [jms](jms/README.md) - Tracing decorators for JMS 1.1-2.01 producers, consumers and listeners.
* [kafka-clients](kafka-clients/README.md) - Tracing decorators for Kafka 0.11+ producers and consumers.
* [kafka-streams](kafka-streams/README.md) - Tracing decorator for Kafka Streams 2.0+ clients.
Expand Down
53 changes: 53 additions & 0 deletions instrumentation/jdbi3/RATIONALE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# brave-instrumentation-jdbi3 rationale

## Floor JRE version

JDBI 3.x has a floor JRE version of 8.

## Default data policy

This is an alternative to [brave-instrumentation-mysql8][mysql8], so has the
same data policy. Changes to this should also be considered for MySQL as both
use JDBC underneath. That or extract a JDBC instrumentation base similar to
[brave-instrumentation-http][http], with helped `brave.Tag` implementations.

## Why not a `StatementContextListener`?

`StatementContextListener` has no way to get the exception for a failed
statement. Also, [brave-instrumentation-mongodb][mongodb] is similar code to
JDBI `StatementLogger`. Instrumentation that is similar is easier to maintain
over time.

## Why not a `Plugin`?

This replaces the JDBI `StatementLogger`, so should be used carefully. For
example, a `Plugin` might want to check if a `StatementLogger` already exists
and delegate to that.

## Why don't we parse the query parameter "zipkinServiceName"?

MySQL's driver initializes statically, so there is no mechanism to pass a
remote service name such as we do for all other instrumentation. In that case,
we add a query parameter "zipkinServiceName" to the connection URL.

JDBI is not initialized statically, so can avoid the overhead and complexity
of parsing a query parameter. Instead, we use the `TracingJdbiPlugin` to assign
this in the builder, like all other instrumentation.

## Why don't we use execution and completion moment from JDBI for the span?

JDBI exposes clock times like `ctx.getCompletionMoment().toEpochMilli()` which
could be considered to substitute for span start and duration. However, the
rest of Brave instrumentation are aligned with its clock, which is locked to
an epoch millisecond, with durations calculated from a monotonic source from
there.

If we used JDBI's clock, it would be inconsistent with the rest of
instrumentation, possibly starting before the parent span, and subject to
clock updates. Rather than attempt to heuristically align JDBI's clock, we use
brave's clock like everything else.

---
[mysql8]: ../mysql8/README.md
[http]: ../http/README.md
[mongodb]: ../mongodb/README.md
25 changes: 10 additions & 15 deletions instrumentation/jdbi3/README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
# brave-instrumentation-jdbi3

This includes a JDBI 3 plugin that will report to Zipkin how long each
statement takes, along with relevant tags like the query.

To use it, call the `installPlugin` on the `Jdbi` instance you want to
instrument, or add the statement context listener manually like so:
```
jdbi.getConfig(SqlStatements.class)
.addContextListener(new BraveStatementContextListener(tracing));
This includes [TracingSqlLogger][TracingSqlLogger] for the Jdbi instance that
reports via Brave how long each query takes, along with relevant tags like the
query.

Example Usage:
```java
SqlLogger sqlLogger = JdbiTracing.create(tracing).sqlLogger();
jdbi.getConfig(SqlStatements.class).setSqlLogger(sqlLogger);
```

The remote service name of the span is set to the hostname and port number of
the database server, if available, and the URL scheme if not. If the database
URL format allows it, you can add the `zipkinServiceName` query parameter to
override the remote service name.

Bind variable values are not included in the traces, only the SQL statement
with placeholders.
---
[TracingSqlLogger]: src/main/java/brave/jdbi3/TracingSqlLogger.java
10 changes: 9 additions & 1 deletion instrumentation/jdbi3/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
SPDX-License-Identifier: Apache-2.0

-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-parent</artifactId>
Expand Down Expand Up @@ -43,5 +45,11 @@
<version>${mysql-connector-j8.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

This file was deleted.

This file was deleted.

85 changes: 85 additions & 0 deletions instrumentation/jdbi3/src/main/java/brave/jdbi3/JdbiTracing.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright The OpenZipkin Authors
* SPDX-License-Identifier: Apache-2.0
*/
package brave.jdbi3;

import brave.Tracing;
import brave.internal.Nullable;
import org.jdbi.v3.core.statement.SqlLogger;

/**
* Use this class to decorate your Jdbi3 client and enable Tracing.
*
* @since 6.3
*/
public final class JdbiTracing {

/**
* @since 6.3
*/
public static JdbiTracing create(Tracing tracing) {
return newBuilder(tracing).build();
}

/**
* @since 6.3
*/
public static Builder newBuilder(Tracing tracing) {
return new Builder(tracing);
}

/**
* A {@linkplain SqlLogger} that will report to Zipkin how long each query
* takes.
*
* <p>To use it, add it like this:
* <pre>{@code
* SqlLogger sqlLogger = JdbiTracing.create(tracing).sqlLogger();
* jdbi.getConfig(SqlStatements.class).setSqlLogger(sqlLogger);
* }</pre>
*
* @since 6.3
*/
public SqlLogger sqlLogger() {
return new TracingSqlLogger(this);
}

public static final class Builder {
final Tracing tracing;
@Nullable String remoteServiceName;

Builder(Tracing tracing) {
if (tracing == null) throw new NullPointerException("tracing == null");
this.tracing = tracing;
}

/**
* The remote service name that describes the database.
*
* <p>Defaults to {@code $databaseType=$databaseName} e.g. "mysql-mydb" or
* "mysql" if the database name is not available.
*
* @since 6.3
*/
public Builder remoteServiceName(String remoteServiceName) {
if (remoteServiceName != null && remoteServiceName.isEmpty()) {
remoteServiceName = null;
}
this.remoteServiceName = remoteServiceName;
return this;
}

public JdbiTracing build() {
return new JdbiTracing(this);
}
}

final Tracing tracing;
@Nullable final String remoteServiceName;

JdbiTracing(Builder builder) {
tracing = builder.tracing;
remoteServiceName = builder.remoteServiceName;
}
}
Loading