net.logstash.logback.pattern.AbstractJsonPatternParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of logstash-logback-encoder Show documentation
Show all versions of logstash-logback-encoder Show documentation
Provides logback encoders, layouts, and appenders to log in JSON and other formats supported by Jackson
/**
* Licensed 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 net.logstash.logback.pattern;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import ch.qos.logback.core.pattern.PatternLayoutBase;
import ch.qos.logback.core.spi.ContextAware;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
/**
* Parser that takes a JSON pattern, resolves all the conversion specifiers and returns an instance
* of NodeWriter that, when its write() method is invoked, produces JSON defined by the parsed pattern.
*
* @param - type of the event (ILoggingEvent, IAccessEvent)
*
* @author Dmitry Andrianov
*/
public abstract class AbstractJsonPatternParser {
public static final Pattern OPERATION_PATTERN = Pattern.compile("\\# (\\w+) (?: \\{ (.*) \\} )?", Pattern.COMMENTS);
private final ContextAware contextAware;
private final JsonFactory jsonFactory;
private final Map operations = new HashMap<>();
/**
* When true, fields whose values are considered empty ({@link #isEmptyValue(Object)}})
* will be omitted from json output.
*/
private boolean omitEmptyFields;
public AbstractJsonPatternParser(final ContextAware contextAware, final JsonFactory jsonFactory) {
this.contextAware = contextAware;
this.jsonFactory = jsonFactory;
addOperation(new AsLongOperation());
addOperation(new AsDoubleOperation());
addOperation(new AsJsonOperation());
addOperation(new TryJsonOperation());
}
protected void addOperation(Operation operation) {
this.operations.put(operation.getName(), operation);
}
protected abstract class Operation {
private final String name;
private final boolean requiresData;
public Operation(String name, boolean requiresData) {
this.name = name;
this.requiresData = requiresData;
}
public String getName() {
return name;
}
public boolean requiresData() {
return requiresData;
}
public abstract ValueGetter, Event> createValueGetter(String data);
}
protected class AsLongOperation extends Operation {
public AsLongOperation() {
super("asLong", true);
}
@Override
public ValueGetter, Event> createValueGetter(String data) {
return new AsLongValueTransformer<>(makeLayoutValueGetter(data));
}
}
protected class AsDoubleOperation extends Operation {
public AsDoubleOperation() {
super("asDouble", true);
}
@Override
public ValueGetter, Event> createValueGetter(String data) {
return new AsDoubleValueTransformer<>(makeLayoutValueGetter(data));
}
}
protected class AsJsonOperation extends Operation {
public AsJsonOperation() {
super("asJson", true);
}
@Override
public ValueGetter, Event> createValueGetter(String data) {
return new AsJsonValueTransformer(makeLayoutValueGetter(data));
}
}
protected class TryJsonOperation extends Operation {
public TryJsonOperation() {
super("tryJson", true);
}
@Override
public ValueGetter, Event> createValueGetter(String data) {
return new TryJsonValueTransformer(makeLayoutValueGetter(data));
}
}
protected static class LayoutValueGetter implements ValueGetter {
private final PatternLayoutBase layout;
LayoutValueGetter(final PatternLayoutBase layout) {
this.layout = layout;
}
@Override
public String getValue(final Event event) {
return layout.doLayout(event);
}
}
protected static abstract class AbstractAsObjectTransformer implements ValueGetter {
private final ValueGetter generator;
AbstractAsObjectTransformer(final ValueGetter generator) {
this.generator = generator;
}
@Override
public T getValue(final Event event) {
final String value = generator.getValue(event);
if (value == null || value.isEmpty()) {
return null;
}
try {
return transform(value);
} catch (Exception e) {
return null;
}
}
abstract protected T transform(final String value) throws NumberFormatException, IOException;
}
protected static abstract class AbstractAsNumberTransformer implements ValueGetter {
private final ValueGetter generator;
AbstractAsNumberTransformer(final ValueGetter generator) {
this.generator = generator;
}
@Override
public T getValue(final Event event) {
final String value = generator.getValue(event);
if (value == null || value.isEmpty()) {
return null;
}
try {
return transform(value);
} catch (NumberFormatException e) {
return null;
}
}
abstract protected T transform(final String value) throws NumberFormatException;
}
protected static class AsLongValueTransformer extends AbstractAsNumberTransformer {
public AsLongValueTransformer(final ValueGetter generator) {
super(generator);
}
protected Long transform(final String value) throws NumberFormatException {
return Long.parseLong(value);
}
}
protected static class AsDoubleValueTransformer extends AbstractAsNumberTransformer {
public AsDoubleValueTransformer(final ValueGetter generator) {
super(generator);
}
protected Double transform(final String value) throws NumberFormatException {
return Double.parseDouble(value);
}
}
protected class AsJsonValueTransformer extends AbstractAsObjectTransformer {
public AsJsonValueTransformer(final ValueGetter generator) {
super(generator);
}
protected JsonNode transform(final String value) throws IOException {
return jsonFactory.getCodec().readTree(jsonFactory.createParser(value));
}
}
protected class TryJsonValueTransformer extends AbstractAsObjectTransformer