package com.hubspot.blazar.config; import java.net.InetAddress; import java.net.UnknownHostException; import javax.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeName; import com.getsentry.raven.logback.SentryAppender; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Appender; import io.dropwizard.logging.AbstractAppenderFactory; import io.dropwizard.logging.async.AsyncAppenderFactory; import io.dropwizard.logging.filter.LevelFilterFactory; import io.dropwizard.logging.layout.LayoutFactory; /** * This class configures sentry via a Logback appender the resource * file META-INF/services/io.dropwizard.logging.AppenderFactory is responsible * for telling Dropwizard's logging mechanics to create an appender using this class * provided that the logging configuration of type "sentry" is available. * * <p> * sentryDsn: string (Data Source Name) is the secret Sentry gives you to report exceptions with. * sentryRelease: string the version of blazar you are deploying. Sentry will tag exceptions using this release value * * This appender is only used if you configure the logging appender in the dropwizard config for sentry as follows: * {@Code * logging: * appenders: * - type: sentry * sentryDsn: http://some_Sentry_provided_DSN * sentryRelease: "PROD" * } * */ @JsonTypeName("sentry") public class SentryAppenderFactory extends AbstractAppenderFactory<ILoggingEvent> { private static final String APPENDER_NAME = "sentry-appender"; private final String sentryDsn; private final String blazarRelease; @JsonCreator public SentryAppenderFactory( @NotNull @JsonProperty("sentryDsn") String sentryDsn, @JsonProperty("blazarRelease") String blazarRelease ) { this.sentryDsn = sentryDsn; this.blazarRelease = blazarRelease; } public String getSentryDsn() { return sentryDsn; } public String getBlazarRelease() { return blazarRelease; } @Override public Appender<ILoggingEvent> build(LoggerContext context, String applicationName, LayoutFactory<ILoggingEvent> layoutFactory, LevelFilterFactory<ILoggingEvent> levelFilterFactory, AsyncAppenderFactory<ILoggingEvent> asyncAppenderFactory) { final SentryAppender appender = new SentryAppender(); appender.setName(APPENDER_NAME); appender.setDsn(sentryDsn); appender.setRelease(blazarRelease); appender.setServerName(getHostNameOrTaskId()); appender.setContext(context); appender.addFilter(levelFilterFactory.build(Level.ERROR)); getFilterFactories().stream().forEach(f -> appender.addFilter(f.build())); appender.start(); return wrapAsync(appender, asyncAppenderFactory, context); } private static String getHostNameOrTaskId() { // Try to use "TASK_HOST" provided by singularity deploy environment if (System.getenv().containsKey("TASK_HOST") ) { return System.getenv().get("TASK_HOST"); } // If not deployed in singularity try to fetch the hostname out of dns try { return InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { return "unknown-host"; } } }