All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zalando.logbook.json.FastJsonHttpLogFormatter Maven / Gradle / Ivy

The newest version!
package org.zalando.logbook.json;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import org.apiguardian.api.API;
import org.zalando.logbook.ContentType;
import org.zalando.logbook.Correlation;
import org.zalando.logbook.HttpLogFormatter;
import org.zalando.logbook.HttpMessage;
import org.zalando.logbook.HttpRequest;
import org.zalando.logbook.HttpResponse;
import org.zalando.logbook.Precorrelation;

import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
import java.util.Map;

import static org.apiguardian.api.API.Status.STABLE;

/**
 * A custom {@link HttpLogFormatter} that produces JSON objects.
 */
@API(status = STABLE)
@AllArgsConstructor
public final class FastJsonHttpLogFormatter implements HttpLogFormatter {

    private final JsonFactory factory;

    private final JsonFieldWriter delegate;

    public FastJsonHttpLogFormatter() {
        this(new ObjectMapper());
    }

    public FastJsonHttpLogFormatter(final ObjectMapper mapper) {
        this(mapper, new DefaultJsonFieldWriter());
    }

    public FastJsonHttpLogFormatter(final ObjectMapper mapper, final JsonFieldWriter writer) {
        this(mapper.getFactory(), writer);
    }

    @FunctionalInterface
    private interface Formatter {
        void format(C correlation, H message, JsonGenerator generator) throws IOException;
    }

    @Override
    public String format(
            final Precorrelation precorrelation,
            final HttpRequest request) throws IOException {

        return format(precorrelation, request, delegate::write);
    }

    @Override
    public String format(
            final Correlation correlation,
            final HttpResponse response) throws IOException {

        return format(correlation, response, delegate::write);
    }

    private  String format(
            final C correlation,
            final H message,
            final Formatter formatter) throws IOException {

        final StringWriter writer = new StringWriter(message.getBody().length + 2048);

        try (final JsonGenerator generator = factory.createGenerator(writer)) {
            generator.writeStartObject();
            formatter.format(correlation, message, generator);
            delegate.write(message, generator);
            generator.writeEndObject();
        }

        return writer.toString();
    }

    private static class DefaultJsonFieldWriter implements JsonFieldWriter {

        @Override
        public  void write(M message, JsonGenerator generator) throws IOException {
            writeHeaders(message, generator);
            writeBody(message, generator);
        }

        private void writeHeaders(
                final HttpMessage message,
                final JsonGenerator generator) throws IOException {

            final Map> headers = message.getHeaders();

            if (headers.isEmpty()) {
                return;
            }

            // implementation note:
            // for some unclear reason, manually iterating over the headers
            // while writing performs worse than letting Jackson do the job.
            generator.writeObjectField("headers", headers);
        }

        private void writeBody(
                final HttpMessage message,
                final JsonGenerator generator) throws IOException {

            final String body = message.getBodyAsString();

            if (body.isEmpty()) {
                return;
            }
            generator.writeFieldName("body");

            final String contentType = message.getContentType();

            if (ContentType.isJsonMediaType(contentType)) {
                generator.writeRawValue(body);
            } else {
                generator.writeString(body);
            }
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy