Skip to content

Commit b829eab

Browse files
authored
sleuth -> micrometer tracing + zipkin (#9)
migrating to(from sleuth) micrometer tracing with zipkin
1 parent 0865627 commit b829eab

File tree

23 files changed

+231
-78
lines changed

23 files changed

+231
-78
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
MicroService:
1313

14-
[//]: # (- Spring Micrometer based tracing)
14+
[//]: # (- Spring micrometer based tracing with zipkin)
1515
- Exposing and implementing Open Feign clients
1616
- Spring Cloud Contract (WIP)
1717

@@ -62,6 +62,7 @@ Misc:
6262
- Approval/flagging api - message based
6363
- Nested comment
6464
- Cache implemented
65+
- Zipkin tracing
6566
- Websocket implemented to show article/comment review status/notifications..
6667

6768
Future: do more stuff
@@ -70,7 +71,6 @@ Future: do more stuff
7071
- Docker-compose deploy/kubernetes
7172
- Visitors log - IP, browser, etc
7273
- Centralized error reporting
73-
- Visual Tracing
7474
- Geo-Spatial query for visitors
7575
- Grafana Dashboard, @Timed and more ...
7676
- logback LevelChangePropagator integration

config/docker-compose.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ services:
3131
- 8025:8025 # use this to access from browser
3232
networks:
3333
- seedappnet
34+
zipkin:
35+
image: 'openzipkin/zipkin'
36+
container_name: zipkin
37+
ports:
38+
- 9411:9411
39+
networks:
40+
- seedappnet
3441
volumes:
3542
esdata1:
3643
driver: local

content-checker/content-checker-service/pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@
2525
<groupId>org.springframework.boot</groupId>
2626
<artifactId>spring-boot-starter-web</artifactId>
2727
</dependency>
28+
<!-- tracing -->
29+
<dependency>
30+
<groupId>org.springframework.boot</groupId>
31+
<artifactId>spring-boot-starter-actuator</artifactId>
32+
</dependency>
33+
<dependency>
34+
<groupId>io.micrometer</groupId>
35+
<artifactId>micrometer-tracing-bridge-brave</artifactId>
36+
</dependency>
37+
<dependency>
38+
<groupId>io.zipkin.reporter2</groupId>
39+
<artifactId>zipkin-reporter-brave</artifactId>
40+
</dependency>
2841
<dependency>
2942
<groupId>org.springframework.boot</groupId>
3043
<artifactId>spring-boot-starter-artemis</artifactId>

content-checker/content-checker-service/src/main/resources/application.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,19 @@ server:
1212

1313
jms:
1414
content-checkerrequest-queue: jms-content-checker-requestqueue
15+
logging:
16+
level:
17+
web: INFO
18+
ROOT: WARN
19+
gt: DEBUG
20+
21+
management:
22+
tracing:
23+
sampling:
24+
probability: 1.0
25+
zipkin:
26+
tracing:
27+
endpoint: http://localhost:9411/api/v2/spans
28+
health:
29+
jms:
30+
enabled: true

email/email-service/pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@
3939
<artifactId>spring-boot-starter-mail</artifactId>
4040
</dependency>
4141

42+
<!-- tracing -->
43+
<dependency>
44+
<groupId>org.springframework.boot</groupId>
45+
<artifactId>spring-boot-starter-actuator</artifactId>
46+
</dependency>
47+
<dependency>
48+
<groupId>io.micrometer</groupId>
49+
<artifactId>micrometer-tracing-bridge-brave</artifactId>
50+
</dependency>
51+
<dependency>
52+
<groupId>io.zipkin.reporter2</groupId>
53+
<artifactId>zipkin-reporter-brave</artifactId>
54+
</dependency>
4255
<!-- processors/code generators -->
4356
<dependency>
4457
<groupId>org.projectlombok</groupId>

email/email-service/src/main/resources/application.yml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,18 @@ spring:
1515
server:
1616
port: 8085
1717

18-
logging.level:
19-
org.springframework.web: WARN
20-
ROOT: WARN
21-
gt: WARN
18+
logging:
19+
level:
20+
org.springframework.web: INFO
21+
ROOT: WARN
22+
gt: DEBUG
23+
24+
management:
25+
tracing:
26+
sampling:
27+
probability: 1.0
28+
zipkin:
29+
tracing:
30+
endpoint: http://localhost:9411/api/v2/spans
31+
32+

main-app/main-webapp/pom.xml

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,24 @@
7676
<groupId>org.springframework.cloud</groupId>
7777
<artifactId>spring-cloud-starter-openfeign</artifactId>
7878
</dependency>
79-
<!-- <dependency>-->
80-
<!-- <groupId>org.springframework.cloud</groupId>-->
81-
<!-- <artifactId>spring-cloud-starter-sleuth</artifactId>-->
82-
<!-- </dependency>-->
79+
<!-- tracing -->
80+
<dependency>
81+
<groupId>org.springframework.boot</groupId>
82+
<artifactId>spring-boot-starter-actuator</artifactId>
83+
</dependency>
84+
<dependency>
85+
<groupId>io.micrometer</groupId>
86+
<artifactId>micrometer-tracing-bridge-brave</artifactId>
87+
</dependency>
88+
<dependency>
89+
<groupId>io.zipkin.reporter2</groupId>
90+
<artifactId>zipkin-reporter-brave</artifactId>
91+
</dependency>
92+
<dependency>
93+
<groupId>io.github.openfeign</groupId>
94+
<artifactId>feign-micrometer</artifactId>
95+
</dependency>
96+
8397
<dependency>
8498
<groupId>org.springframework.boot</groupId>
8599
<artifactId>spring-boot-starter-artemis</artifactId>
@@ -239,6 +253,10 @@
239253
<groupId>com.github.gavlyukovskiy</groupId>
240254
<artifactId>datasource-proxy-spring-boot-starter</artifactId>
241255
</dependency>
256+
<dependency>
257+
<groupId>net.ttddyy.observation</groupId>
258+
<artifactId>datasource-micrometer-spring-boot</artifactId>
259+
</dependency>
242260

243261
<!-- spock deps -->
244262
<dependency>

main-app/main-webapp/src/main/java/gt/app/MainApplication.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package gt.app;
22

3+
import brave.sampler.Sampler;
34
import gt.app.config.AppProperties;
45
import lombok.extern.slf4j.Slf4j;
56
import org.springframework.boot.SpringApplication;
67
import org.springframework.boot.autoconfigure.SpringBootApplication;
78
import org.springframework.boot.context.properties.EnableConfigurationProperties;
89
import org.springframework.cache.annotation.EnableCaching;
10+
import org.springframework.context.annotation.Bean;
911
import org.springframework.core.env.Environment;
1012
import org.springframework.scheduling.annotation.EnableScheduling;
1113

@@ -38,5 +40,9 @@ public static void main(String[] args) throws UnknownHostException {
3840
Arrays.toString(env.getActiveProfiles())
3941
);
4042
}
41-
43+
//Force sample
44+
@Bean
45+
public Sampler defaultSampler() {
46+
return Sampler.ALWAYS_SAMPLE;
47+
}
4248
}

main-app/main-webapp/src/main/java/gt/app/config/AppHibernatePropertiesCustomizer.java

Lines changed: 0 additions & 21 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package gt.app.config.logging;
22

33
import lombok.extern.slf4j.Slf4j;
4-
import org.hibernate.Interceptor;
4+
import org.hibernate.resource.jdbc.spi.StatementInspector;
55

66
import java.io.Serial;
77
import java.io.Serializable;
88

99
@Slf4j
10-
public class HibernateStatInterceptor implements Interceptor, Serializable {
10+
public class HibernateStatementStatInterceptor implements StatementInspector, Serializable {
1111

1212
@Serial
1313
private static final long serialVersionUID = -7875557911815131906L;
@@ -25,13 +25,13 @@ public void clearCounter() {
2525
queryCount.remove();
2626
}
2727

28-
// @Override
29-
// public String onPrepareStatement(String sql) {
30-
// Long count = queryCount.get();
31-
// if (count != null) {
32-
// queryCount.set(count + 1);
33-
// }
34-
//
35-
// return super.onPrepareStatement(sql);
36-
// }
28+
@Override
29+
public String inspect(String sql) {
30+
Long count = queryCount.get();
31+
if (count != null) {
32+
queryCount.set(count + 1);
33+
}
34+
35+
return null;
36+
}
3737
}

main-app/main-webapp/src/main/java/gt/app/config/logging/WebRequestInterceptor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ public class WebRequestInterceptor implements AsyncHandlerInterceptor {
1111

1212
private final ThreadLocal<Long> exeTimeThreadLocal = new ThreadLocal<>();
1313

14-
private final HibernateStatInterceptor statisticsInterceptor;
14+
private final HibernateStatementStatInterceptor statisticsInterceptor;
1515

16-
public WebRequestInterceptor(HibernateStatInterceptor statisticsInterceptor) {
16+
public WebRequestInterceptor(HibernateStatementStatInterceptor statisticsInterceptor) {
1717
this.statisticsInterceptor = statisticsInterceptor;
1818
}
1919

main-app/main-webapp/src/main/java/gt/app/config/metrics/RequestStatisticsConfiguration.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package gt.app.config.metrics;
22

3-
import gt.app.config.logging.HibernateStatInterceptor;
3+
import gt.app.config.logging.HibernateStatementStatInterceptor;
44
import gt.app.config.logging.WebRequestInterceptor;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.hibernate.cfg.AvailableSettings;
7+
import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
58
import org.springframework.context.annotation.Bean;
69
import org.springframework.context.annotation.Configuration;
710
import org.springframework.context.annotation.Profile;
@@ -10,18 +13,24 @@
1013

1114
@Configuration
1215
@Profile("!test")
16+
@Slf4j
1317
class RequestStatisticsConfiguration implements WebMvcConfigurer {
1418

1519
@Bean
16-
public HibernateStatInterceptor hibernateInterceptor() {
17-
return new HibernateStatInterceptor();
20+
public HibernateStatementStatInterceptor hibernateInterceptor() {
21+
return new HibernateStatementStatInterceptor();
1822
}
1923

20-
// @Bean this is not working
24+
@Bean
2125
public WebRequestInterceptor requestStatisticsInterceptor() {
2226
return new WebRequestInterceptor(hibernateInterceptor());
2327
}
2428

29+
@Bean
30+
public HibernatePropertiesCustomizer hibernateCustomizer(HibernateStatementStatInterceptor statInterceptor) {
31+
return (properties) -> properties.put(AvailableSettings.STATEMENT_INSPECTOR, statInterceptor);
32+
}
33+
2534
@Override
2635
public void addInterceptors(InterceptorRegistry registry) {
2736
registry.addInterceptor(requestStatisticsInterceptor()).addPathPatterns("/", "/article/**");

main-app/main-webapp/src/main/java/gt/app/modules/review/CommentReviewResponseService.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ void handle(Response resp) {
2626
default -> throw new UnsupportedOperationException();
2727
}
2828

29-
websocketHandler.sendToUser(c.getLastModifiedByUser().getUsername(), "Your comment " + c.getContent().substring(0, 20) + " has been " + (resp.getContentCheckOutcome() == PASSED ? "approved." : "queued for manual review."));
29+
int maxLengthToTrim = Math.min(c.getContent().length(), 20);
30+
31+
websocketHandler.sendToUser(c.getLastModifiedByUser().getUsername(), "Your comment " + c.getContent().substring(0, maxLengthToTrim) + " has been " + (resp.getContentCheckOutcome() == PASSED ? "approved." : "queued for manual review."));
3032
if (resp.getContentCheckOutcome() != PASSED) {
31-
websocketHandler.sendToUser("system", "A new comment " + c.getContent().substring(0, 20) + " has is queued for system admin review.");
33+
websocketHandler.sendToUser("system", "A new comment " + c.getContent().substring(0, maxLengthToTrim) + " has is queued for system admin review.");
3234
}
3335

3436
commentRepository.save(c);

main-app/main-webapp/src/main/java/gt/app/modules/review/ContentCheckResponseListenerService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class ContentCheckResponseListenerService {
1616

1717
@JmsListener(destination = "${app-properties.jms.content-checkercallback-response-queue}")
1818
void handleContentCheckResponse(Response resp) {
19-
19+
log.info("Received review response for entity id {}, entity type {}, outcome {}", resp.getEntityId(), resp.getRequestType(), resp.getContentCheckOutcome());
2020
switch (resp.getRequestType()) {
2121
case COMMENT -> commentReviewResponseService.handle(resp);
2222
case ARTICLE -> articleReviewResponseService.handle(resp);

main-app/main-webapp/src/main/java/gt/app/modules/review/JmsContentCheckService.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import gt.app.domain.Article;
55
import gt.app.domain.Comment;
66
import lombok.RequiredArgsConstructor;
7+
import lombok.extern.slf4j.Slf4j;
78
import org.springframework.context.annotation.Profile;
89
import org.springframework.jms.core.JmsTemplate;
910
import org.springframework.scheduling.annotation.Async;
@@ -16,21 +17,24 @@
1617
@RequiredArgsConstructor
1718
@Service
1819
@Profile("!test")
20+
@Slf4j
1921
public class JmsContentCheckService implements ContentCheckService {
2022

2123
private final JmsTemplate jmsTemplate;
2224
private final AppProperties appProperties;
2325

2426
@Override
25-
@Async
27+
@Async //TODO: tracing is not working with async yet !
2628
public void sendForAutoContentReview(Article a) {
29+
log.info("Sending article {} for review", a.getId());
2730
var req = withArticle(a.getContent(), appProperties.getJms().getContentCheckerCallBackResponseQueue(), Long.toString(a.getId()), ARTICLE);
2831
jmsTemplate.convertAndSend(appProperties.getJms().getContentCheckerRequestQueue(), req);
2932
}
3033

3134
@Override
3235
@Async
3336
public void sendForAutoContentReview(Comment c) {
37+
log.info("Sending comment {} for review", c.getId());
3438
var req = withArticle(c.getContent(), appProperties.getJms().getContentCheckerCallBackResponseQueue(), Long.toString(c.getId()), COMMENT);
3539
jmsTemplate.convertAndSend(appProperties.getJms().getContentCheckerRequestQueue(), req);
3640
}

main-app/main-webapp/src/main/resources/application-dev.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
spring:
22
thymeleaf:
3-
cache: false # set to false, this if you are working on UI
3+
cache: true # set to false, this if you are working on UI
44
prefix: file:main-app/main-webapp/src/main/resources/templates/ #directly serve from src folder instead of target
55
web:
66
resources:
@@ -10,10 +10,10 @@ spring:
1010
- classpath:/resources/
1111
- classpath:/static/
1212
- classpath:/public/
13-
# cache:
14-
# period: 500000
15-
# chain:
16-
# cache: true
13+
cache:
14+
period: 500000
15+
chain:
16+
cache: true
1717
mvc:
1818
static-path-pattern: /static/**
1919

0 commit comments

Comments
 (0)