
com.yahoo.container.logging.JsonConnectionLogWriter Maven / Gradle / Ivy
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.logging;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yahoo.container.logging.ConnectionLogEntry.SslHandshakeFailure.ExceptionEntry;
import java.io.IOException;
import java.io.OutputStream;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* @author bjorncs
*/
class JsonConnectionLogWriter implements LogWriter {
private final JsonFactory jsonFactory = new JsonFactory(new ObjectMapper());
@Override
public void write(ConnectionLogEntry record, OutputStream outputStream) throws IOException {
try (JsonGenerator generator = createJsonGenerator(outputStream)) {
generator.writeStartObject();
generator.writeStringField("id", record.id());
generator.writeStringField("timestamp", record.timestamp().toString());
writeOptionalSeconds(generator, "duration", unwrap(record.durationSeconds()));
writeOptionalString(generator, "peerAddress", unwrap(record.peerAddress()));
writeOptionalInteger(generator, "peerPort", unwrap(record.peerPort()));
writeOptionalString(generator, "localAddress", unwrap(record.localAddress()));
writeOptionalInteger(generator, "localPort", unwrap(record.localPort()));
String proxyProtocolVersion = unwrap(record.proxyProtocolVersion());
String proxyProtocolRemoteAddress = unwrap(record.remoteAddress());
Integer proxyProtocolRemotePort = unwrap(record.remotePort());
if (isAnyValuePresent(proxyProtocolVersion, proxyProtocolRemoteAddress, proxyProtocolRemotePort)) {
generator.writeObjectFieldStart("proxyProtocol");
writeOptionalString(generator, "version", proxyProtocolVersion);
writeOptionalString(generator, "remoteAddress", proxyProtocolRemoteAddress);
writeOptionalInteger(generator, "remotePort", proxyProtocolRemotePort);
generator.writeEndObject();
}
String httpVersion = unwrap(record.httpProtocol());
Long httpBytesReceived = unwrap(record.httpBytesReceived());
Long httpBytesSent = unwrap(record.httpBytesSent());
Long httpRequests = unwrap(record.requests());
Long httpResponses = unwrap(record.responses());
if (isAnyValuePresent(httpVersion, httpBytesReceived, httpBytesSent, httpRequests, httpResponses)) {
generator.writeObjectFieldStart("http");
writeOptionalString(generator, "version", httpVersion);
writeOptionalLong(generator, "bytesReceived", httpBytesReceived);
writeOptionalLong(generator, "responses", httpResponses);
writeOptionalLong(generator, "bytesSent", httpBytesSent);
writeOptionalLong(generator, "requests", httpRequests);
generator.writeEndObject();
}
String sslProtocol = unwrap(record.sslProtocol());
String sslSessionId = unwrap(record.sslSessionId());
String sslCipherSuite = unwrap(record.sslCipherSuite());
String sslPeerSubject = unwrap(record.sslPeerSubject());
Instant sslPeerNotBefore = unwrap(record.sslPeerNotBefore());
Instant sslPeerNotAfter = unwrap(record.sslPeerNotAfter());
String sslSniServerName = unwrap(record.sslSniServerName());
String sslPeerIssuerSubject = unwrap(record.sslPeerIssuerSubject());
String sslPeerFingerprint = unwrap(record.sslPeerFingerprint());
ConnectionLogEntry.SslHandshakeFailure sslHandshakeFailure = unwrap(record.sslHandshakeFailure());
List sslSubjectAlternativeNames = record.sslSubjectAlternativeNames();
if (isAnyValuePresent(
sslProtocol, sslSessionId, sslCipherSuite, sslPeerSubject, sslPeerNotBefore, sslPeerNotAfter,
sslSniServerName, sslHandshakeFailure, sslPeerIssuerSubject, sslPeerFingerprint)) {
generator.writeObjectFieldStart("ssl");
writeOptionalString(generator, "protocol", sslProtocol);
writeOptionalString(generator, "sessionId", sslSessionId);
writeOptionalString(generator, "cipherSuite", sslCipherSuite);
writeOptionalString(generator, "peerSubject", sslPeerSubject);
writeOptionalString(generator, "peerIssuerSubject", sslPeerIssuerSubject);
writeOptionalTimestamp(generator, "peerNotBefore", sslPeerNotBefore);
writeOptionalTimestamp(generator, "peerNotAfter", sslPeerNotAfter);
writeOptionalString(generator, "peerFingerprint", sslPeerFingerprint);
writeOptionalString(generator, "sniServerName", sslSniServerName);
if (sslHandshakeFailure != null) {
generator.writeObjectFieldStart("handshake-failure");
generator.writeArrayFieldStart("exception");
for (ExceptionEntry entry : sslHandshakeFailure.exceptionChain()) {
generator.writeStartObject();
generator.writeStringField("cause", entry.name());
generator.writeStringField("message", entry.message());
generator.writeEndObject();
}
generator.writeEndArray();
generator.writeStringField("type", sslHandshakeFailure.type());
generator.writeEndObject();
}
if (!sslSubjectAlternativeNames.isEmpty()) {
generator.writeArrayFieldStart("san");
for (String sanEntry : sslSubjectAlternativeNames) {
generator.writeString(sanEntry);
}
generator.writeEndArray();
}
generator.writeEndObject();
}
}
}
private void writeOptionalString(JsonGenerator generator, String name, String value) throws IOException {
if (value != null) {
generator.writeStringField(name, value);
}
}
private void writeOptionalInteger(JsonGenerator generator, String name, Integer value) throws IOException {
if (value != null) {
generator.writeNumberField(name, value);
}
}
private void writeOptionalLong(JsonGenerator generator, String name, Long value) throws IOException {
if (value != null) {
generator.writeNumberField(name, value);
}
}
private void writeOptionalTimestamp(JsonGenerator generator, String name, Instant value) throws IOException {
if (value != null) {
generator.writeStringField(name, value.toString());
}
}
private void writeOptionalSeconds(JsonGenerator generator, String name, Double value) throws IOException {
if (value != null) {
FormatUtil.writeSecondsField(generator, name, value);
}
}
private static boolean isAnyValuePresent(Object... values) { return Arrays.stream(values).anyMatch(Objects::nonNull); }
private static T unwrap(Optional maybeValue) { return maybeValue.orElse(null); }
private JsonGenerator createJsonGenerator(OutputStream outputStream) throws IOException {
return jsonFactory.createGenerator(outputStream, JsonEncoding.UTF8)
.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false)
.configure(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM, false);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy