blob: 442572b70d5ccc46bee66c90f2e85ce582c4a321 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache license, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the license for the specific language governing permissions and
* limitations under the license.
*/
package org.apache.logging.log4j.layout.template.json;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.LogEvent;
import org.junit.jupiter.api.Test;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import static org.apache.logging.log4j.layout.template.json.TestHelpers.CONFIGURATION;
import static org.apache.logging.log4j.layout.template.json.TestHelpers.usingSerializedLogEventAccessor;
import static org.assertj.core.api.Assertions.assertThat;
class GcpLayoutTest {
private static final JsonTemplateLayout LAYOUT = JsonTemplateLayout
.newBuilder()
.setConfiguration(CONFIGURATION)
.setStackTraceEnabled(true)
.setLocationInfoEnabled(true)
.setEventTemplateUri("classpath:GcpLayout.json")
.build();
private static final int LOG_EVENT_COUNT = 1_000;
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
@Test
void test_lite_log_events() {
LogEventFixture
.createLiteLogEvents(LOG_EVENT_COUNT)
.forEach(GcpLayoutTest::verifySerialization);
}
@Test
void test_full_log_events() {
LogEventFixture
.createFullLogEvents(LOG_EVENT_COUNT)
.forEach(GcpLayoutTest::verifySerialization);
}
private static void verifySerialization(final LogEvent logEvent) {
usingSerializedLogEventAccessor(LAYOUT, logEvent, accessor -> {
// Verify timestamp.
final String expectedTimestamp = formatLogEventInstant(logEvent);
assertThat(accessor.getString("timestamp")).isEqualTo(expectedTimestamp);
// Verify severity.
final Level level = logEvent.getLevel();
final String expectedSeverity;
if (Level.WARN.equals(level)) {
expectedSeverity = "WARNING";
} else if (Level.TRACE.equals(level)) {
expectedSeverity = "TRACE";
} else if (Level.FATAL.equals(level)) {
expectedSeverity = "EMERGENCY";
} else {
expectedSeverity = level.name();
}
assertThat(accessor.getString("severity")).isEqualTo(expectedSeverity);
// Verify message.
final Throwable exception = logEvent.getThrown();
if (exception != null) {
final String actualMessage = accessor.getString("message");
assertThat(actualMessage)
.contains(logEvent.getMessage().getFormattedMessage())
.contains(exception.getLocalizedMessage())
.contains("at org.apache.logging.log4j.layout.template.json")
.contains("at java.base/java.lang.reflect.Method")
.contains("at org.junit.platform.engine");
}
// Verify labels.
logEvent.getContextData().forEach((key, value) -> {
final String expectedValue = String.valueOf(value);
final String actualValue =
accessor.getString(new String[]{
"logging.googleapis.com/labels", key});
assertThat(actualValue).isEqualTo(expectedValue);
});
final StackTraceElement source = logEvent.getSource();
if (source != null) {
// Verify file name.
final String actualFileName =
accessor.getString(new String[]{
"logging.googleapis.com/sourceLocation", "file"});
assertThat(actualFileName).isEqualTo(source.getFileName());
// Verify line number.
final int actualLineNumber =
accessor.getInteger(new String[]{
"logging.googleapis.com/sourceLocation", "line"});
assertThat(actualLineNumber).isEqualTo(source.getLineNumber());
// Verify function.
final String expectedFunction =
source.getClassName() + "." + source.getMethodName();
final String actualFunction =
accessor.getString(new String[]{
"logging.googleapis.com/sourceLocation", "function"});
assertThat(actualFunction).isEqualTo(expectedFunction);
} else {
assertThat(accessor.exists(
new String[]{"logging.googleapis.com/sourceLocation", "file"}))
.isFalse();
assertThat(accessor.exists(
new String[]{"logging.googleapis.com/sourceLocation", "line"}))
.isFalse();
assertThat(accessor.getString(
new String[]{"logging.googleapis.com/sourceLocation", "function"}))
.isEmpty();
}
// Verify insert id.
assertThat(accessor.getString("logging.googleapis.com/insertId"))
.matches("[-]?[0-9]+");
// Verify exception.
if (exception != null) {
// Verify exception class.
assertThat(accessor.getString(
new String[]{"_exception", "class"}))
.isEqualTo(exception.getClass().getCanonicalName());
// Verify exception message.
assertThat(accessor.getString(
new String[]{"_exception", "message"}))
.isEqualTo(exception.getMessage());
// Verify exception stack trace.
assertThat(accessor.getString(
new String[]{"_exception", "stackTrace"}))
.contains(exception.getLocalizedMessage())
.contains("at org.apache.logging.log4j.layout.template.json")
.contains("at java.base/java.lang.reflect.Method")
.contains("at org.junit.platform.engine");
} else {
assertThat(accessor.getObject(
new String[]{"_exception", "class"}))
.isNull();
assertThat(accessor.getObject(
new String[]{"_exception", "message"}))
.isNull();
assertThat(accessor.getString(
new String[]{"_exception", "stackTrace"}))
.isEmpty();
}
// Verify thread name.
assertThat(accessor.getString("_thread"))
.isEqualTo(logEvent.getThreadName());
// Verify logger name.
assertThat(accessor.getString("_logger"))
.isEqualTo(logEvent.getLoggerName());
});
}
private static String formatLogEventInstant(final LogEvent logEvent) {
org.apache.logging.log4j.core.time.Instant instant = logEvent.getInstant();
ZonedDateTime dateTime = Instant.ofEpochSecond(
instant.getEpochSecond(),
instant.getNanoOfSecond()).atZone(ZoneId.of("UTC"));
return DATE_TIME_FORMATTER.format(dateTime);
}
}