net.logstash.logback.marker.SingleFieldAppendingMarker Maven / Gradle / Ivy
Show all versions of logstash-logback-encoder Show documentation
/*
* Copyright 2013-2022 the original author or authors.
*
* 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.marker;
import java.io.IOException;
import java.util.Objects;
import net.logstash.logback.argument.StructuredArgument;
import net.logstash.logback.argument.StructuredArguments;
import net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider;
import net.logstash.logback.composite.loggingevent.LogstashMarkersJsonProvider;
import com.fasterxml.jackson.core.JsonGenerator;
import org.slf4j.Marker;
/**
* A {@link Marker} OR {@link StructuredArgument} that appends
* a single field into the JSON event.
*
*
* When writing to the JSON data (via {@link ArgumentsJsonProvider} or {@link LogstashMarkersJsonProvider}):
*
* - Field names are written via {@link #writeFieldName(JsonGenerator)},
* which just uses {@link #fieldName} is used as the field name
* - Values are written via {@link #writeFieldValue(JsonGenerator)},
* which subclasses must override
*
*
*
* When writing to a String (when used as a {@link StructuredArgument} to the event's formatted message),
* the {@link #messageFormatPattern} is used to construct the string output.
* {@link #getFieldName()} will be substituted in {0} in the {@link #messageFormatPattern}.
* {@link #getFieldValue()} will be substituted in {1} in the {@link #messageFormatPattern}.
* Subclasses must override {@link #getFieldValue()} to provide the field value to include.
*/
@SuppressWarnings("serial")
public abstract class SingleFieldAppendingMarker extends LogstashMarker implements StructuredArgument {
public static final String MARKER_NAME_PREFIX = LogstashMarker.MARKER_NAME_PREFIX + "APPEND_";
/**
* Name of the field to append.
*
* Note that the value of the field is provided by subclasses via {@link #writeFieldValue(JsonGenerator)}.
*/
private final String fieldName;
/**
* Pattern to use when appending the field/value in {@link #toString()}.
*
* {@link #getFieldName()} will be substituted in {0}.
* {@link #getFieldValue()} will be substituted in {1}.
*/
private final String messageFormatPattern;
public SingleFieldAppendingMarker(String markerName, String fieldName) {
this(markerName, fieldName, StructuredArguments.DEFAULT_KEY_VALUE_MESSAGE_FORMAT_PATTERN);
}
public SingleFieldAppendingMarker(String markerName, String fieldName, String messageFormatPattern) {
super(markerName);
this.fieldName = Objects.requireNonNull(fieldName, "fieldName must not be null");
this.messageFormatPattern = Objects.requireNonNull(messageFormatPattern, "messageFormatPattern must not be null");
}
public String getFieldName() {
return fieldName;
}
public void writeTo(JsonGenerator generator) throws IOException {
writeFieldName(generator);
writeFieldValue(generator);
}
/**
* Writes the field name to the generator.
*
* @param generator the generator to write JSON
* @throws IOException if an I/O error occurs
*/
protected void writeFieldName(JsonGenerator generator) throws IOException {
generator.writeFieldName(getFieldName());
}
/**
* Writes the field value to the generator.
*
* @param generator the generator to write JSON
* @throws IOException if an I/O error occurs
*/
protected abstract void writeFieldValue(JsonGenerator generator) throws IOException;
@Override
public String toStringSelf() {
final String fieldValueString = StructuredArguments.toString(getFieldValue());
/*
* Optimize for commonly used messageFormatPattern
*/
if (StructuredArguments.VALUE_ONLY_MESSAGE_FORMAT_PATTERN.equals(messageFormatPattern)) {
return fieldValueString;
}
if (StructuredArguments.DEFAULT_KEY_VALUE_MESSAGE_FORMAT_PATTERN.equals(messageFormatPattern)) {
return getFieldName()
+ "="
+ fieldValueString;
}
/*
* Custom messageFormatPattern
*/
return MessageFormatCache.INSTANCE.getMessageFormat(this.messageFormatPattern)
.format(new Object[] {getFieldName(), fieldValueString});
}
/**
* Return the value that should be included in the output of {@link #toString()}.
*
* @return the field value
*/
protected abstract Object getFieldValue();
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof SingleFieldAppendingMarker)) {
return false;
}
SingleFieldAppendingMarker other = (SingleFieldAppendingMarker) obj;
return this.fieldName.equals(other.fieldName);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + super.hashCode();
result = prime * result + this.fieldName.hashCode();
return result;
}
}