DataSourceTracer { @CheckReturnValue public DataSource trace(final DataSource dataSource) { return ProxyDataSourceBuilder.create(dataSource) .listener(new TracingQueryExecutionListener( tracer, operationName, lifecycle, activation, decorator)) .build(); } DataSourceTracer(final Tracer tracer); @CheckReturnValue DataSourceTracer withOperationName(
            final OperationName operationName); @CheckReturnValue DataSourceTracer withLifecycle(final Lifecycle lifecycle); @CheckReturnValue DataSourceTracer withActivation(final Activation activation); @CheckReturnValue DataSourceTracer withAdditionalSpanDecorators(
            final SpanDecorator first, final SpanDecorator... decorators); @CheckReturnValue DataSourceTracer withSpanDecorators(
            final SpanDecorator decorator, final SpanDecorator... decorators); @CheckReturnValue DataSource trace(final DataSource dataSource);  }
@Test void shouldTraceStatement() throws SQLException { final DataSource dataSource = unit.trace(original); try (final Connection connection = dataSource.getConnection(); final Statement statement = connection.createStatement()) { statement.execute("SELECT 1"); } final List<MockSpan> spans = tracer.finishedSpans(); final MockSpan span = getOnlyElement(spans); assertThat(span.operationName(), is("execute")); assertThat(span.tags(), hasEntry("component", "JDBC")); assertThat(span.tags(), hasEntry("db.instance", "USERS")); assertThat(span.tags(), hasEntry("db.statement", "SELECT 1")); assertThat(span.tags(), hasEntry("db.type", "sql")); assertThat(span.tags(), hasEntry("db.user", "")); assertThat(span.tags(), hasEntry("peer.address", "h2:mem:users")); assertThat(span.tags(), hasEntry("peer.hostname", "users")); assertThat(span.tags(), not(hasKey("peer.port"))); assertThat(span.tags(), hasEntry("span.kind", "client")); assertThat(span.tags(), hasEntry("flow_id", "REcCvlqMSReeo7adheiYFA")); assertThat(span.tags(), not(hasKey("error"))); }
@Test void shouldTracePreparedStatement() throws SQLException { final DataSource dataSource = unit.trace(original); try (final Connection connection = dataSource.getConnection(); final PreparedStatement statement = connection.prepareStatement("SELECT ?")) { statement.setInt(1, 1); statement.execute(); } final List<MockSpan> spans = tracer.finishedSpans(); final MockSpan span = getOnlyElement(spans); assertThat(span.operationName(), is("execute")); assertThat(span.tags(), hasEntry("component", "JDBC")); assertThat(span.tags(), hasEntry("db.instance", "USERS")); assertThat(span.tags(), hasEntry("db.statement", "SELECT ?")); assertThat(span.tags(), hasEntry("db.type", "sql")); assertThat(span.tags(), hasEntry("span.kind", "client")); assertThat(span.tags(), hasEntry("flow_id", "REcCvlqMSReeo7adheiYFA")); assertThat(span.tags(), not(hasKey("error"))); }
@Test void shouldTraceBatch() throws SQLException { try (final Connection connection = original.getConnection(); final Statement statement = connection.createStatement()) { statement.execute("CREATE TABLE users(id BIGINT, name TEXT)"); } final DataSource dataSource = unit.trace(original); try (final Connection connection = dataSource.getConnection(); final Statement statement = connection.createStatement()) { statement.addBatch("INSERT INTO users(id, name) VALUES (1, 'Alice')"); statement.addBatch("INSERT INTO users(id, name) VALUES (2, 'Bob')"); statement.executeBatch(); } final List<MockSpan> spans = tracer.finishedSpans(); final MockSpan span = getOnlyElement(spans); assertThat(span.operationName(), is("executeBatch")); assertThat(span.tags(), hasEntry("db.statement", "INSERT INTO users(id, name) VALUES (1, 'Alice')\nINSERT INTO users(id, name) VALUES (2, 'Bob')")); }
@Test void shouldTracePreparedBatch() throws SQLException { try (final Connection connection = original.getConnection(); final Statement statement = connection.createStatement()) { statement.execute("CREATE TABLE users(id BIGINT, name TEXT)"); } final DataSource dataSource = unit.trace(original); final String sql = "INSERT INTO users(id, name) VALUES (?, ?)"; try (final Connection connection = dataSource.getConnection(); final PreparedStatement statement = connection.prepareStatement(sql)) { statement.setInt(1, 1); statement.setString(2, "Alice"); statement.addBatch(); statement.setInt(1, 2); statement.setString(2, "Bob"); statement.addBatch(); statement.executeBatch(); } final List<MockSpan> spans = tracer.finishedSpans(); final MockSpan span = getOnlyElement(spans); assertThat(span.operationName(), is("executeBatch")); assertThat(span.tags(), hasEntry("db.statement", "INSERT INTO users(id, name) VALUES (?, ?)")); }
@Test void shouldTraceErrors() { final DataSource dataSource = unit.trace(original); assertThrows(SQLException.class, () -> { try (final Connection connection = dataSource.getConnection(); final Statement statement = connection.createStatement()) { statement.execute("SELECT * FROM MATRIX(4)"); } }); final List<MockSpan> spans = tracer.finishedSpans(); final MockSpan span = getOnlyElement(spans); assertThat(span.operationName(), is("execute")); assertThat(span.tags(), hasEntry("component", "JDBC")); assertThat(span.tags(), hasEntry("db.statement", "SELECT * FROM MATRIX(4)")); assertThat(span.tags(), hasEntry("db.type", "sql")); assertThat(span.tags(), hasEntry("span.kind", "client")); assertThat(span.tags(), hasEntry("flow_id", "REcCvlqMSReeo7adheiYFA")); assertThat(span.tags(), hasEntry("error", true)); final List<MockSpan.LogEntry> entries = span.logEntries(); assertThat(entries, hasSize(3)); assertThat(entries.get(0).fields().get("message").toString(), containsString("Function \"MATRIX\" not found")); assertThat(entries.get(1).fields(), hasEntry("error.kind", "JdbcSQLSyntaxErrorException")); assertThat(entries.get(1).fields(), hasEntry(equalTo("error.object"), instanceOf(SQLException.class))); assertThat(entries.get(2).fields().get("stack").toString(), containsString("at org.h2.jdbc")); }