StructuredLogLayoutTests Class — spring-boot Architecture
Architecture documentation for the StructuredLogLayoutTests class in StructuredLogLayoutTests.java from the spring-boot codebase.
Entity Profile
Relationship Graph
Source Code
core/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/StructuredLogLayoutTests.java lines 44–195
class StructuredLogLayoutTests extends AbstractStructuredLoggingTests {
private MockEnvironment environment;
private LoggerContext loggerContext;
@BeforeEach
void setup() {
this.environment = new MockEnvironment();
this.environment.setProperty("logging.structured.json.stacktrace.printer",
SimpleStackTracePrinter.class.getName());
this.loggerContext = (LoggerContext) LogManager.getContext(false);
this.loggerContext.putObject(Log4J2LoggingSystem.ENVIRONMENT_KEY, this.environment);
}
@AfterEach
void cleanup() {
this.loggerContext.removeObject(Log4J2LoggingSystem.ENVIRONMENT_KEY);
}
@Test
@SuppressWarnings("unchecked")
void shouldSupportEcsCommonFormat() {
StructuredLogLayout layout = newBuilder().setFormat("ecs").build();
String json = layout.toSerializable(createEvent(new RuntimeException("Boom!")));
Map<String, Object> deserialized = deserialize(json);
assertThat(deserialized).containsEntry("ecs", Map.of("version", "8.11"));
Map<String, Object> error = (Map<String, Object>) deserialized.get("error");
assertThat(error).isNotNull();
assertThat(error.get("stack_trace")).isEqualTo("stacktrace:RuntimeException");
}
@Test
@SuppressWarnings("unchecked")
void shouldOutputNestedAdditionalEcsJson() {
this.environment.setProperty("logging.structured.json.add.extra.value", "test");
StructuredLogLayout layout = newBuilder().setFormat("ecs").build();
String json = layout.toSerializable(createEvent(new RuntimeException("Boom!")));
Map<String, Object> deserialized = deserialize(json);
assertThat(deserialized).containsKey("extra");
assertThat((Map<String, Object>) deserialized.get("extra")).containsEntry("value", "test");
System.out.println(deserialized);
}
@Test
void shouldSupportLogstashCommonFormat() {
StructuredLogLayout layout = newBuilder().setFormat("logstash").build();
String json = layout.toSerializable(createEvent(new RuntimeException("Boom!")));
Map<String, Object> deserialized = deserialize(json);
assertThat(deserialized).containsKey("@version");
assertThat(deserialized.get("stack_trace")).isEqualTo("stacktrace:RuntimeException");
}
@Test
void shouldSupportGelfCommonFormat() {
StructuredLogLayout layout = newBuilder().setFormat("gelf").build();
String json = layout.toSerializable(createEvent(new RuntimeException("Boom!")));
Map<String, Object> deserialized = deserialize(json);
assertThat(deserialized).containsKey("version");
assertThat(deserialized.get("_error_stack_trace")).isEqualTo("stacktrace:RuntimeException");
}
@Test
void shouldSupportCustomFormat() {
StructuredLogLayout layout = newBuilder().setFormat(CustomLog4j2StructuredLoggingFormatter.class.getName())
.build();
String format = layout.toSerializable(createEvent());
assertThat(format).isEqualTo("custom-format");
}
@Test
void shouldInjectCustomFormatConstructorParameters() {
this.environment.setProperty("spring.application.pid", "42");
StructuredLogLayout layout = newBuilder()
.setFormat(CustomLog4j2StructuredLoggingFormatterWithInjection.class.getName())
.build();
String format = layout.toSerializable(createEvent());
assertThat(format).isEqualTo("custom-format-with-injection pid=42");
}
@Test
void shouldCheckTypeArgument() {
assertThatIllegalStateException().isThrownBy(
() -> newBuilder().setFormat(CustomLog4j2StructuredLoggingFormatterWrongType.class.getName()).build())
.withMessageContaining("must be org.apache.logging.log4j.core.LogEvent but was java.lang.String");
}
@Test
void shouldCheckTypeArgumentWithRawType() {
assertThatIllegalStateException()
.isThrownBy(
() -> newBuilder().setFormat(CustomLog4j2StructuredLoggingFormatterRawType.class.getName()).build())
.withMessageContaining("must be org.apache.logging.log4j.core.LogEvent but was null");
}
@Test
void shouldFailIfNoCommonOrCustomFormatIsSet() {
assertThatIllegalArgumentException().isThrownBy(() -> newBuilder().setFormat("does-not-exist").build())
.withMessageContaining("Unknown format 'does-not-exist'. "
+ "Values can be a valid fully-qualified class name or one of the common formats: [ecs, gelf, logstash]");
}
private Builder newBuilder() {
Builder builder = StructuredLogLayout.newBuilder();
ReflectionTestUtils.setField(builder, "loggerContext", this.loggerContext);
return builder;
}
static final class CustomLog4j2StructuredLoggingFormatter implements StructuredLogFormatter<LogEvent> {
@Override
public String format(LogEvent event) {
return "custom-format";
}
}
static final class CustomLog4j2StructuredLoggingFormatterWithInjection implements StructuredLogFormatter<LogEvent> {
private final Environment environment;
CustomLog4j2StructuredLoggingFormatterWithInjection(Environment environment) {
this.environment = environment;
}
@Override
public String format(LogEvent event) {
return "custom-format-with-injection pid=" + this.environment.getProperty("spring.application.pid");
}
}
static final class CustomLog4j2StructuredLoggingFormatterWrongType implements StructuredLogFormatter<String> {
@Override
public String format(String event) {
return event;
}
}
@SuppressWarnings("rawtypes")
static final class CustomLog4j2StructuredLoggingFormatterRawType implements StructuredLogFormatter {
@Override
public String format(Object event) {
return "";
}
}
}
Domain
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free