Skip to content

Commit d3dedb4

Browse files
BFD-4683: Add MDC-aware thread pool executor (#3116)
1 parent 88b58af commit d3dedb4

9 files changed

Lines changed: 61 additions & 9 deletions

apps/bfd-server-ng/README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,18 @@ mvn spring-boot:run
8282

8383
### Profiling SQL queries
8484

85-
The `sqlprofile` profile can be used to log SQL queries and output metrics.
85+
The `sql-profile` profile can be used to log SQL queries and output metrics.
8686

8787
```sh
88-
mvn spring-boot run -Dspring-boot.run.profiles=local,sqlprofile
88+
mvn spring-boot run -Dspring-boot.run.profiles=local,sql-profile
89+
```
90+
91+
### Structured Logging
92+
93+
The `structured-log` profile can be used to test structured logs.
94+
95+
```sh
96+
mvn spring-boot run -Dspring-boot.run.profiles=local,structured-log
8997
```
9098

9199
## Swagger

apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/Application.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.springframework.boot.web.servlet.ServletRegistrationBean;
1717
import org.springframework.context.annotation.Bean;
1818
import org.springframework.scheduling.annotation.EnableAsync;
19+
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
1920
import org.springframework.transaction.annotation.EnableTransactionManagement;
2021
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
2122

@@ -104,4 +105,14 @@ public AuditLogger auditLogger(Configuration configuration, ObjectMapper objectM
104105
public DynamoDbClient dynamoDbClient(Configuration configuration) {
105106
return configuration.getDynamoDbClient();
106107
}
108+
109+
/**
110+
* Creates the custom task executor.
111+
*
112+
* @return task executor
113+
*/
114+
@Bean
115+
public ThreadPoolTaskExecutor taskExecutor() {
116+
return new MdcAwareThreadPoolExecutor();
117+
}
107118
}

apps/bfd-server-ng/src/main/java/gov/cms/bfd/server/ng/Configuration.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@
3838
@ConfigurationProperties(prefix = "bfd")
3939
public class Configuration implements Serializable {
4040
// Unfortunately, constructor injection doesn't work with @ConfigurationProperties
41+
private static final String LOCAL_ENV = "local";
4142

4243
/** Identifies which Spring profiles indicate that the server is being run on a local machine. */
43-
private static final List<String> ALLOWED_LOCAL_PROFILES = List.of("local", "sqlprofile");
44+
private static final List<String> ALLOWED_LOCAL_PROFILES =
45+
List.of(LOCAL_ENV, "sql-profile", "structured-log");
4446

4547
// Getters should only be generated for configuration properties, not dependencies
4648
@Getter(value = AccessLevel.NONE)
@@ -57,12 +59,11 @@ public class Configuration implements Serializable {
5759
@Autowired(required = false)
5860
private JdbcConnectionDetails jdbcConnectionDetails;
5961

60-
private static final String BFD_ENV_LOCAL = "local";
6162
private String dynamoLocalUrl = "http://localhost:8000";
6263

6364
// Default to local configuration, this should be overridden on deployment with the correct
6465
// environment.
65-
private String env = BFD_ENV_LOCAL;
66+
private String env = LOCAL_ENV;
6667
private String dbIdentifier = "";
6768
private Local local = new Local();
6869
private Sensitive sensitive = new Sensitive();
@@ -129,7 +130,7 @@ public AuditLogger getAuditLogger(ObjectMapper objectMapper) {
129130
}
130131

131132
boolean isLocal() {
132-
return env.equalsIgnoreCase(BFD_ENV_LOCAL);
133+
return env.equalsIgnoreCase(LOCAL_ENV);
133134
}
134135

135136
/** Represents possible types of audit logging. */
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package gov.cms.bfd.server.ng;
2+
3+
import org.slf4j.MDC;
4+
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
5+
6+
/**
7+
* Custom task executor that preserves MDC info, ensuring all relevant info is logged for each
8+
* request.
9+
*/
10+
public class MdcAwareThreadPoolExecutor extends ThreadPoolTaskExecutor {
11+
12+
static Runnable wrapWithMdcContext(Runnable task) {
13+
// save the current MDC context
14+
var contextMap = MDC.getCopyOfContextMap();
15+
return () -> {
16+
MDC.clear();
17+
MDC.setContextMap(contextMap);
18+
try {
19+
task.run();
20+
} finally {
21+
// once the task is complete, clear MDC
22+
MDC.clear();
23+
}
24+
};
25+
}
26+
27+
@Override
28+
public void execute(Runnable command) {
29+
super.execute(wrapWithMdcContext(command));
30+
}
31+
}

apps/bfd-server-ng/src/main/resources/application-aws.properties renamed to apps/bfd-server-ng/src/main/resources/application-deployed.properties

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
spring.config.import=aws-parameterstore:/bfd/${BFD_ENV}/server-ng?prefix=bfd.
22
bfd.env=${BFD_ENV}
3-
# Use Elastic Common Schema for a sensible JSON-based log format
4-
logging.structured.format.console=ecs
53
# Native support for Forwarded headers
64
server.forward-headers-strategy=NATIVE

apps/bfd-server-ng/src/main/resources/application-sqlprofile.properties renamed to apps/bfd-server-ng/src/main/resources/application-sql-profile.properties

File renamed without changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Use Elastic Common Schema for a sensible JSON-based log format
2+
logging.structured.format.console=ecs

apps/bfd-server-ng/src/main/resources/application.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ spring.mvc.favicon.enabled=false
1313
# This is still behind mtls though so it's fine to include here
1414
management.endpoints.web.exposure.include=metrics
1515
spring.threads.virtual.enabled=true
16+
spring.profiles.group.aws=structured-log,deployed

apps/bfd-server-ng/src/main/resources/logback-spring.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
1010
<logger name="org.springframework.web" level="DEBUG" />
1111
</springProfile>
12-
<springProfile name="aws">
12+
<springProfile name="structured-log">
1313
<!-- use structured logging in the deployed environment only -->
1414
<include resource="org/springframework/boot/logging/logback/structured-console-appender.xml" />
1515
</springProfile>

0 commit comments

Comments
 (0)