dd-trace-java icon indicating copy to clipboard operation
dd-trace-java copied to clipboard

Datadog Trace Span Issue with MySQL Batch Inserts using MySQL Connector/J

Open junyeong-jang-kurly opened this issue 1 year ago • 1 comments

Hello,

I would like to report an issue in an environment using Spring Boot, Spring Data JPA, and MySQL Connector/J 8.4.0, where trace spans for MySQL queries are not being recorded in the Datadog trace menu. The issue occurs when the JDBC option rewriteBatchedStatements=true is used and batch insert queries are executed. The expected cause is that when executing batch insert queries, the MySQL Connector/J ClientPreparedStatement class creates a batchedStatement, and during this process, the Datadog context of the original statement may not be propagated.

Please look into this issue. Thank you.

When using MySQL Connector/J 8.4.0

스크린샷 2024-06-21 오후 6 33 04

When using MariaDB Connector/J 2.6.2

스크린샷 2024-06-21 오후 6 32 53

Here is my sample code for test.

@AllArgsConstructor
@RestController
public class TestController {
    private final TestService testService;
    private final TestRepository testRepository;

    @Transactional
    @GetMapping(value = "/test", produces = "application/json")
    public String test() {
        testRepository.updateName(1L, "newName");
        testService.batch(List.of("name1", "name2", "name3", "name4", "name5"));
        testRepository.updateName(1L, "newName2");
        return "{\"status\": \"success\"}";
    }
}

@Service
@AllArgsConstructor
public class TestService {
    private final JdbcTemplate jdbcTemplate;

    @Transactional
    public void batch(List<String> names) {
        jdbcTemplate.batchUpdate(
            "INSERT INTO t1 (t_name) VALUES (?)",
            new BatchPreparedStatementSetter() {
                @Override
                public void setValues(PreparedStatement ps, int i) throws SQLException {
                    ps.setString(1, names.get(i));
                }

                @Override
                public int getBatchSize() {
                    return names.size();
                }
            }
        );
    }
}

public interface TestRepository extends JpaRepository<Test, Long> {

    @Modifying
    @Query(
        value = """
            UPDATE t1 SET t_name = :newName WHERE id = :id
        """,
        nativeQuery = true
    )
    void updateName(Long id, String newName);

}

@Getter
@Entity
@Table(name = "t1")
public class Test {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "t_name")
    private String name;

    private Test() {
    }

    public Test(String name) {
        this.name = name;
    }
}

junyeong-jang-kurly avatar Jun 21 '24 09:06 junyeong-jang-kurly

Only dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/AbstractPreparedStatementInstrumentation.java add code:

transformer.applyAdvice(
        named("executeBatchInternal").and(takesArguments(0)).and(isProtected()),
        AbstractPreparedStatementInstrumentation.class.getName() + "$PreparedStatementAdvice");

lrwh avatar Oct 28 '24 10:10 lrwh