co.elastic.logging.log4j.EcsLayout Maven / Gradle / Ivy
/*-
* #%L
* Java ECS logging
* %%
* Copyright (C) 2019 - 2020 Elastic and contributors
* %%
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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.
* #L%
*/
package co.elastic.logging.log4j;
import co.elastic.logging.EcsJsonSerializer;
import co.elastic.logging.AdditionalField;
import org.apache.log4j.Layout;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import java.util.ArrayList;
import java.util.List;
public class EcsLayout extends Layout {
private static final MdcAccess MDC_ACCESS = MdcAccess.Resolver.resolve();
private boolean stackTraceAsArray = false;
private String serviceName;
private String serviceVersion;
private String serviceEnvironment;
private String serviceNodeName;
private boolean includeOrigin;
private String eventDataset;
private List additionalFields = new ArrayList();
@Override
public String format(LoggingEvent event) {
StringBuilder builder = new StringBuilder();
EcsJsonSerializer.serializeObjectStart(builder, event.timeStamp);
EcsJsonSerializer.serializeLogLevel(builder, event.level.toString());
EcsJsonSerializer.serializeFormattedMessage(builder, event.getRenderedMessage());
EcsJsonSerializer.serializeEcsVersion(builder);
EcsJsonSerializer.serializeServiceName(builder, serviceName);
EcsJsonSerializer.serializeServiceVersion(builder, serviceVersion);
EcsJsonSerializer.serializeServiceEnvironment(builder, serviceEnvironment);
EcsJsonSerializer.serializeServiceNodeName(builder, serviceNodeName);
EcsJsonSerializer.serializeEventDataset(builder, eventDataset);
EcsJsonSerializer.serializeThreadName(builder, event.getThreadName());
EcsJsonSerializer.serializeLoggerName(builder, event.categoryName);
EcsJsonSerializer.serializeAdditionalFields(builder, additionalFields);
EcsJsonSerializer.serializeMDC(builder, MDC_ACCESS.getMDC(event));
EcsJsonSerializer.serializeTag(builder, event.getNDC());
if (includeOrigin) {
LocationInfo locationInformation = event.getLocationInformation();
if (locationInformation != null) {
EcsJsonSerializer.serializeOrigin(builder, locationInformation.getFileName(), locationInformation.getMethodName(), getLineNumber(locationInformation));
}
}
ThrowableInformation throwableInformation = event.getThrowableInformation();
if (throwableInformation != null) {
EcsJsonSerializer.serializeException(builder, throwableInformation.getThrowable(), stackTraceAsArray);
}
EcsJsonSerializer.serializeObjectEnd(builder);
return builder.toString();
}
private static int getLineNumber(LocationInfo locationInformation) {
int lineNumber = -1;
String lineNumberString = locationInformation.getLineNumber();
if (!LocationInfo.NA.equals(lineNumberString)) {
try {
lineNumber = Integer.parseInt(lineNumberString);
} catch (NumberFormatException e) {
// ignore
}
}
return lineNumber;
}
@Override
public boolean ignoresThrowable() {
return false;
}
@Override
public void activateOptions() {
eventDataset = EcsJsonSerializer.computeEventDataset(eventDataset, serviceName);
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public void setServiceVersion(String serviceVersion) {
this.serviceVersion = serviceVersion;
}
public void setServiceEnvironment(String serviceEnvironment) {
this.serviceEnvironment = serviceEnvironment;
}
public void setServiceNodeName(String serviceNodeName) {
this.serviceNodeName = serviceNodeName;
}
public void setIncludeOrigin(boolean includeOrigin) {
this.includeOrigin = includeOrigin;
}
public void setStackTraceAsArray(boolean stackTraceAsArray) {
this.stackTraceAsArray = stackTraceAsArray;
}
public void setEventDataset(String eventDataset) {
this.eventDataset = eventDataset;
}
public void setAdditionalField(String additionalField) {
this.additionalFields.add(AdditionalField.of(additionalField));
}
}