Skip to content

Commit 10a5c63

Browse files
committed
feat(samples): Add Kafka producer and consumer to Spring Boot 3 OTel sample apps
Add Kafka queue tracing support to both the OTel agent and agentless Spring Boot 3 sample applications. Each sample gets a KafkaController for producing messages and a KafkaConsumer listener, activated via the 'kafka' Spring profile. Kafka auto-configuration is excluded by default and only enabled when the kafka profile is active.
1 parent 6f90ea7 commit 10a5c63

File tree

10 files changed

+128
-0
lines changed

10 files changed

+128
-0
lines changed

sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ dependencies {
5252
implementation(projects.sentryAsyncProfiler)
5353
implementation(projects.sentryOpentelemetry.sentryOpentelemetryAgentlessSpring)
5454

55+
// kafka
56+
implementation(libs.spring.kafka3)
57+
5558
// cache tracing
5659
implementation(libs.springboot3.starter.cache)
5760
implementation(libs.caffeine)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.sentry.samples.spring.boot.jakarta;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
import org.springframework.context.annotation.Profile;
6+
import org.springframework.kafka.annotation.KafkaListener;
7+
import org.springframework.stereotype.Component;
8+
9+
@Component
10+
@Profile("kafka")
11+
public class KafkaConsumer {
12+
13+
private static final Logger logger = LoggerFactory.getLogger(KafkaConsumer.class);
14+
15+
@KafkaListener(topics = "sentry-topic", groupId = "sentry-sample-group")
16+
public void listen(String message) {
17+
logger.info("Received message: {}", message);
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package io.sentry.samples.spring.boot.jakarta;
2+
3+
import org.springframework.context.annotation.Profile;
4+
import org.springframework.kafka.core.KafkaTemplate;
5+
import org.springframework.web.bind.annotation.GetMapping;
6+
import org.springframework.web.bind.annotation.RequestMapping;
7+
import org.springframework.web.bind.annotation.RequestParam;
8+
import org.springframework.web.bind.annotation.RestController;
9+
10+
@RestController
11+
@Profile("kafka")
12+
@RequestMapping("/kafka")
13+
public class KafkaController {
14+
15+
private final KafkaTemplate<String, String> kafkaTemplate;
16+
17+
public KafkaController(KafkaTemplate<String, String> kafkaTemplate) {
18+
this.kafkaTemplate = kafkaTemplate;
19+
}
20+
21+
@GetMapping("/produce")
22+
String produce(@RequestParam(defaultValue = "hello from sentry!") String message) {
23+
kafkaTemplate.send("sentry-topic", message);
24+
return "Message sent: " + message;
25+
}
26+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Kafka — activate with: --spring.profiles.active=kafka
2+
sentry.enable-queue-tracing=true
3+
4+
spring.autoconfigure.exclude=
5+
spring.kafka.bootstrap-servers=localhost:9092
6+
spring.kafka.consumer.group-id=sentry-sample-group
7+
spring.kafka.consumer.auto-offset-reset=earliest
8+
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
9+
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
10+
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
11+
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
12+
13+
logging.level.org.apache.kafka=warn

sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/src/main/resources/application.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ spring.graphql.graphiql.enabled=true
3535
spring.graphql.websocket.path=/graphql
3636
spring.quartz.job-store-type=memory
3737

38+
# Kafka is only active with the 'kafka' profile (--spring.profiles.active=kafka)
39+
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration
40+
3841
# Cache tracing
3942
sentry.enable-cache-tracing=true
4043
spring.cache.cache-names=todos

sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ dependencies {
5656
implementation(libs.otel)
5757
implementation(projects.sentryAsyncProfiler)
5858

59+
// kafka
60+
implementation(libs.spring.kafka3)
61+
5962
// cache tracing
6063
implementation(libs.springboot3.starter.cache)
6164
implementation(libs.caffeine)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.sentry.samples.spring.boot.jakarta;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
import org.springframework.context.annotation.Profile;
6+
import org.springframework.kafka.annotation.KafkaListener;
7+
import org.springframework.stereotype.Component;
8+
9+
@Component
10+
@Profile("kafka")
11+
public class KafkaConsumer {
12+
13+
private static final Logger logger = LoggerFactory.getLogger(KafkaConsumer.class);
14+
15+
@KafkaListener(topics = "sentry-topic", groupId = "sentry-sample-group")
16+
public void listen(String message) {
17+
logger.info("Received message: {}", message);
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package io.sentry.samples.spring.boot.jakarta;
2+
3+
import org.springframework.context.annotation.Profile;
4+
import org.springframework.kafka.core.KafkaTemplate;
5+
import org.springframework.web.bind.annotation.GetMapping;
6+
import org.springframework.web.bind.annotation.RequestMapping;
7+
import org.springframework.web.bind.annotation.RequestParam;
8+
import org.springframework.web.bind.annotation.RestController;
9+
10+
@RestController
11+
@Profile("kafka")
12+
@RequestMapping("/kafka")
13+
public class KafkaController {
14+
15+
private final KafkaTemplate<String, String> kafkaTemplate;
16+
17+
public KafkaController(KafkaTemplate<String, String> kafkaTemplate) {
18+
this.kafkaTemplate = kafkaTemplate;
19+
}
20+
21+
@GetMapping("/produce")
22+
String produce(@RequestParam(defaultValue = "hello from sentry!") String message) {
23+
kafkaTemplate.send("sentry-topic", message);
24+
return "Message sent: " + message;
25+
}
26+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Kafka — activate with: --spring.profiles.active=kafka
2+
sentry.enable-queue-tracing=true
3+
4+
spring.autoconfigure.exclude=
5+
spring.kafka.bootstrap-servers=localhost:9092
6+
spring.kafka.consumer.group-id=sentry-sample-group
7+
spring.kafka.consumer.auto-offset-reset=earliest
8+
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
9+
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
10+
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
11+
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
12+
13+
logging.level.org.apache.kafka=warn

sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/src/main/resources/application.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ spring.graphql.graphiql.enabled=true
3535
spring.graphql.websocket.path=/graphql
3636
spring.quartz.job-store-type=memory
3737

38+
# Kafka is only active with the 'kafka' profile (--spring.profiles.active=kafka)
39+
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration
40+
3841
# Cache tracing
3942
sentry.enable-cache-tracing=true
4043
spring.cache.cache-names=todos

0 commit comments

Comments
 (0)