Datadog Trace Span Issue with MySQL Batch Inserts using MySQL Connector/J
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
When using MariaDB Connector/J 2.6.2
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;
}
}
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");