package org.cloudname.log; import org.cloudname.log.pb.Timber; import static org.cloudname.log.pb.Timber.ConsistencyLevel; import com.google.protobuf.ByteString; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.logging.LogRecord; import java.util.logging.Level; import java.io.ByteArrayOutputStream; import java.io.PrintStream; /** * This utility class converts log messages to Timber.LogEvent * instances. * * @author borud */ public class Converter { private static String hostName; private String serviceName; // I am not a big fan of static sections, but there seems to be no // intelligent way to do this. static { try { hostName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { hostName = null; } } /** * Create a Converter for a given service. * * @param serviceName the name of the service we are logging on * behalf of. */ public Converter(String serviceName) { this.serviceName = serviceName; } /** * Create a Timber.LogEvent from a LogRecord. * * <p> * TODO(borud): we need a better way of defining the type (setType()). * TODO(borud): add encoding of nested exception. * * @param rec the LogRecord we wish to convert * @return a Timber.LogEvent instance. */ public Timber.LogEvent convertFrom(LogRecord rec) { Timber.LogEvent.Builder eventBuilder = Timber.LogEvent.newBuilder() .setTimestamp(rec.getMillis()) .setConsistencyLevel(ConsistencyLevel.BESTEFFORT) .setLevel(rec.getLevel().intValue()) .setHost(hostName) .setServiceName(serviceName) .setSource(rec.getSourceClassName() + "#" + rec.getSourceMethodName()) .setPid(0) .setTid(rec.getThreadID()) .setType("T") .addPayload( Timber.Payload.newBuilder() .setName("msg") .setPayload(ByteString.copyFromUtf8(rec.getMessage()))); // Check if we have an exception Throwable cause = rec.getThrown(); if (cause != null) { // Awkward ByteArrayOutputStream os = new ByteArrayOutputStream(); cause.printStackTrace(new PrintStream(os)); eventBuilder.addPayload( Timber.Payload.newBuilder() .setName("exception") .setContentType("application/java-exception") .setPayload(ByteString.copyFrom(os.toByteArray())) ); } return eventBuilder.build(); } }