diff --git a/pom.xml b/pom.xml
index 913e5f3ee..36cbe7f67 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,9 +54,9 @@
${dropwizard.version}
- com.dcsquare
- dropwizard-papertrail
- 1.2
+ com.papertrailapp
+ logback-syslog4j
+ 1.0.0
org.bouncycastle
diff --git a/src/main/java/org/whispersystems/textsecuregcm/metrics/LoggingNetworkAppenderFactory.java b/src/main/java/org/whispersystems/textsecuregcm/metrics/LoggingNetworkAppenderFactory.java
new file mode 100644
index 000000000..1e7fa7cd1
--- /dev/null
+++ b/src/main/java/org/whispersystems/textsecuregcm/metrics/LoggingNetworkAppenderFactory.java
@@ -0,0 +1,121 @@
+package org.whispersystems.textsecuregcm.metrics;
+
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.papertrailapp.logback.Syslog4jAppender;
+import io.dropwizard.logging.AbstractAppenderFactory;
+import io.dropwizard.logging.async.AsyncAppenderFactory;
+import io.dropwizard.logging.filter.LevelFilterFactory;
+import io.dropwizard.logging.layout.LayoutFactory;
+import io.dropwizard.validation.PortRange;
+import org.hibernate.validator.constraints.NotEmpty;
+import org.productivity.java.syslog4j.impl.net.tcp.ssl.SSLTCPNetSyslogConfig;
+
+import javax.validation.constraints.NotNull;
+import java.util.TimeZone;
+
+@JsonTypeName("papertrail")
+public class LoggingNetworkAppenderFactory extends AbstractAppenderFactory {
+
+ @JsonProperty
+ @NotEmpty
+ private String ident;
+
+ @JsonProperty
+ @NotEmpty
+ private String host;
+
+ @JsonProperty
+ @PortRange(min = 1)
+ @NotNull
+ private Integer port;
+
+ @JsonProperty
+ private TimeZone timeZone = TimeZone.getTimeZone("UTC");
+
+ @JsonProperty
+ @NotEmpty
+ private String facility = "USER";
+
+ @JsonProperty
+ private boolean sendLocalName = true;
+
+ public String getIdent() {
+ return ident;
+ }
+
+ public void setIdent(final String ident) {
+ this.ident = ident;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(final String host) {
+ this.host = host;
+ }
+
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(final Integer port) {
+ this.port = port;
+ }
+
+ public TimeZone getTimeZone() {
+ return timeZone;
+ }
+
+ public void setTimeZone(final TimeZone timeZone) {
+ this.timeZone = timeZone;
+ }
+
+ public String getFacility() {
+ return facility;
+ }
+
+ public void setFacility(final String facility) {
+ this.facility = facility;
+ }
+
+ public boolean isSendLocalName() {
+ return sendLocalName;
+ }
+
+ public void setSendLocalName(final boolean sendLocalName) {
+ this.sendLocalName = sendLocalName;
+ }
+
+ @Override
+ public Appender build(LoggerContext context,
+ String applicationName,
+ LayoutFactory layoutFactory,
+ LevelFilterFactory levelFilterFactory,
+ AsyncAppenderFactory asyncAppenderFactory)
+ {
+ final Syslog4jAppender syslogAppender = new Syslog4jAppender<>();
+ syslogAppender.setContext(context);
+ syslogAppender.setLayout(buildLayout(context, layoutFactory));
+ syslogAppender.setName("SYSLOG-TLS");
+ final SSLTCPNetSyslogConfig syslogConfig = new SSLTCPNetSyslogConfig();
+
+ syslogConfig.setIdent(ident);
+ syslogConfig.setHost(host);
+ syslogConfig.setPort(port);
+ syslogConfig.setFacility(facility);
+ syslogConfig.setSendLocalName(sendLocalName);
+
+ syslogAppender.setSyslogConfig(syslogConfig);
+
+ syslogAppender.addFilter(levelFilterFactory.build(threshold));
+ syslogAppender.start();
+
+ return syslogAppender;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/META-INF/services/io.dropwizard.logging.AppenderFactory b/src/main/resources/META-INF/services/io.dropwizard.logging.AppenderFactory
new file mode 100644
index 000000000..8d6c78dac
--- /dev/null
+++ b/src/main/resources/META-INF/services/io.dropwizard.logging.AppenderFactory
@@ -0,0 +1 @@
+org.whispersystems.textsecuregcm.metrics.LoggingNetworkAppenderFactory
\ No newline at end of file