net.logstash.logback.encoder.CompositeJsonEncoder 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.encoder;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import net.logstash.logback.composite.CompositeJsonFormatter;
import net.logstash.logback.composite.JsonProviders;
import net.logstash.logback.decorate.JsonFactoryDecorator;
import net.logstash.logback.decorate.JsonGeneratorDecorator;
import org.apache.commons.io.IOUtils;
import ch.qos.logback.core.encoder.Encoder;
import ch.qos.logback.core.encoder.EncoderBase;
import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
import ch.qos.logback.core.pattern.PatternLayoutBase;
import ch.qos.logback.core.spi.DeferredProcessingAware;
public abstract class CompositeJsonEncoder
extends EncoderBase {
private boolean immediateFlush = true;
private Encoder prefix;
private Encoder suffix;
private final CompositeJsonFormatter formatter;
private String lineSeparator = System.getProperty("line.separator");
private Charset charset;
public CompositeJsonEncoder() {
super();
this.formatter = createFormatter();
}
protected abstract CompositeJsonFormatter createFormatter();
@Override
public void init(OutputStream os) throws IOException {
initWrapped(prefix, os);
super.init(os);
initWrapped(suffix, os);
}
private void initWrapped(Encoder wrapped, OutputStream os) throws IOException {
if (wrapped != null) {
wrapped.init(os);
}
}
@Override
public void doEncode(Event event) throws IOException {
doEncodeWrapped(prefix, event);
formatter.writeEventToOutputStream(event, outputStream);
doEncodeWrapped(suffix, event);
if (this.lineSeparator != null) {
IOUtils.write(this.lineSeparator, outputStream, charset);
}
if (immediateFlush) {
outputStream.flush();
}
}
private void doEncodeWrapped(Encoder wrapped, Event event) throws IOException {
if (wrapped != null) {
wrapped.doEncode(event);
}
}
@Override
public void start() {
super.start();
formatter.setContext(getContext());
formatter.start();
charset = Charset.forName(formatter.getEncoding());
startWrapped(prefix);
startWrapped(suffix);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void startWrapped(Encoder wrapped) {
if (wrapped instanceof LayoutWrappingEncoder) {
/*
* Convenience hack to ensure the same charset is used in most cases.
*
* The charset for other encoders must be configured
* on the wrapped encoder configuration.
*/
LayoutWrappingEncoder layoutWrappedEncoder = (LayoutWrappingEncoder) wrapped;
layoutWrappedEncoder.setCharset(charset);
if (layoutWrappedEncoder.getLayout() instanceof PatternLayoutBase) {
/*
* Don't ensure exception output (for ILoggingEvents)
* or line separation (for IAccessEvents)
*/
PatternLayoutBase layout = (PatternLayoutBase) layoutWrappedEncoder.getLayout();
layout.setPostCompileProcessor(null);
/*
* The pattern will be re-parsed during start.
* Needed so that the pattern is re-parsed without
* the postCompileProcessor.
*/
layout.start();
}
}
if (wrapped != null && !wrapped.isStarted()) {
wrapped.start();
}
}
@Override
public void stop() {
super.stop();
formatter.stop();
stopWrapped(prefix);
stopWrapped(suffix);
}
private void stopWrapped(Encoder wrapped) {
if (wrapped != null && !wrapped.isStarted()) {
wrapped.stop();
}
}
@Override
public void close() throws IOException {
closeWrapped(prefix);
closeWrapped(suffix);
}
private void closeWrapped(Encoder wrapped) throws IOException {
if (wrapped != null && !wrapped.isStarted()) {
wrapped.close();
}
}
public JsonProviders getProviders() {
return formatter.getProviders();
}
public void setProviders(JsonProviders jsonProviders) {
formatter.setProviders(jsonProviders);
}
public boolean isImmediateFlush() {
return immediateFlush;
}
public void setImmediateFlush(boolean immediateFlush) {
this.immediateFlush = immediateFlush;
}
public JsonFactoryDecorator getJsonFactoryDecorator() {
return formatter.getJsonFactoryDecorator();
}
public void setJsonFactoryDecorator(JsonFactoryDecorator jsonFactoryDecorator) {
formatter.setJsonFactoryDecorator(jsonFactoryDecorator);
}
public JsonGeneratorDecorator getJsonGeneratorDecorator() {
return formatter.getJsonGeneratorDecorator();
}
public String getEncoding() {
return formatter.getEncoding();
}
/**
* The character encoding to use (default = "UTF-8").
* Must an encoding supported by {@link com.fasterxml.jackson.core.JsonEncoding}
*/
public void setEncoding(String encodingName) {
formatter.setEncoding(encodingName);
}
public void setJsonGeneratorDecorator(JsonGeneratorDecorator jsonGeneratorDecorator) {
formatter.setJsonGeneratorDecorator(jsonGeneratorDecorator);
}
public String getLineSeparator() {
return lineSeparator;
}
/**
* Sets which lineSeparator to use between events.
*
*
* The following values have special meaning:
*
* - null or empty string = no new line.
* - "SYSTEM" = operating system new line (default).
* - "UNIX" = unix line ending (\n).
* - "WINDOWS" = windows line ending (\r\n).
*
*
* Any other value will be used as given as the lineSeparator.
*/
public void setLineSeparator(String lineSeparator) {
this.lineSeparator = SeparatorParser.parseSeparator(lineSeparator);
}
protected CompositeJsonFormatter getFormatter() {
return formatter;
}
public Encoder getPrefix() {
return prefix;
}
public void setPrefix(Encoder prefix) {
this.prefix = prefix;
}
public Encoder getSuffix() {
return suffix;
}
public void setSuffix(Encoder suffix) {
this.suffix = suffix;
}
}