diff --git a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java index 4fb95bfcd..10195ba8c 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java +++ b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java @@ -17,16 +17,15 @@ package org.whispersystems.textsecuregcm; import com.fasterxml.jackson.annotation.JsonProperty; +import org.whispersystems.textsecuregcm.configuration.DirectoryConfiguration; import org.whispersystems.textsecuregcm.configuration.FederationConfiguration; import org.whispersystems.textsecuregcm.configuration.GraphiteConfiguration; import org.whispersystems.textsecuregcm.configuration.MemcacheConfiguration; import org.whispersystems.textsecuregcm.configuration.MessageStoreConfiguration; -import org.whispersystems.textsecuregcm.configuration.MetricsConfiguration; import org.whispersystems.textsecuregcm.configuration.NexmoConfiguration; import org.whispersystems.textsecuregcm.configuration.PushConfiguration; import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration; import org.whispersystems.textsecuregcm.configuration.RedPhoneConfiguration; -import org.whispersystems.textsecuregcm.configuration.DirectoryConfiguration; import org.whispersystems.textsecuregcm.configuration.S3Configuration; import org.whispersystems.textsecuregcm.configuration.TwilioConfiguration; import org.whispersystems.textsecuregcm.configuration.WebsocketConfiguration; @@ -91,10 +90,6 @@ public class WhisperServerConfiguration extends Configuration { @JsonProperty private GraphiteConfiguration graphite = new GraphiteConfiguration(); - @Valid - @JsonProperty - private MetricsConfiguration viz = new MetricsConfiguration(); - @Valid @JsonProperty private WebsocketConfiguration websocket = new WebsocketConfiguration(); @@ -160,10 +155,6 @@ public class WhisperServerConfiguration extends Configuration { return graphite; } - public MetricsConfiguration getMetricsConfiguration() { - return viz; - } - public RedPhoneConfiguration getRedphoneConfiguration() { return redphone; } diff --git a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index 992d23ff8..6b3766f27 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -229,13 +229,6 @@ public class WhisperServerService extends Application initializeNexmoSmsSender(NexmoConfiguration configuration) { diff --git a/src/main/java/org/whispersystems/textsecuregcm/configuration/MetricsConfiguration.java b/src/main/java/org/whispersystems/textsecuregcm/configuration/MetricsConfiguration.java deleted file mode 100644 index 7594473b0..000000000 --- a/src/main/java/org/whispersystems/textsecuregcm/configuration/MetricsConfiguration.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.whispersystems.textsecuregcm.configuration; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class MetricsConfiguration { - - @JsonProperty - private String token; - - @JsonProperty - private String host; - - @JsonProperty - private boolean enabled = false; - - public String getHost() { - return host; - } - - public String getToken() { - return token; - } - - public boolean isEnabled() { - return enabled && token != null && host != null; - } -} diff --git a/src/main/java/org/whispersystems/textsecuregcm/metrics/JsonMetricsReporter.java b/src/main/java/org/whispersystems/textsecuregcm/metrics/JsonMetricsReporter.java index 68197cdd5..2f74b3d36 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/metrics/JsonMetricsReporter.java +++ b/src/main/java/org/whispersystems/textsecuregcm/metrics/JsonMetricsReporter.java @@ -27,25 +27,25 @@ import java.util.SortedMap; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; -/** - * Adapted from MetricsServlet. - */ public class JsonMetricsReporter extends ScheduledReporter { - private final Logger logger = LoggerFactory.getLogger(JsonMetricsReporter.class); + private static final Pattern SIMPLE_NAMES = Pattern.compile("[^a-zA-Z0-9_.\\-~]"); + + private final Logger logger = LoggerFactory.getLogger(JsonMetricsReporter.class); private final JsonFactory factory = new JsonFactory(); - private final String table; - private final String sunnylabsHost; + private final String token; + private final String hostname; private final String host; - public JsonMetricsReporter(MetricRegistry registry, String token, String sunnylabsHost) + public JsonMetricsReporter(MetricRegistry registry, String token, String hostname, + MetricFilter filter, TimeUnit rateUnit, TimeUnit durationUnit) throws UnknownHostException { - super(registry, "jsonmetrics-reporter", MetricFilter.ALL, TimeUnit.SECONDS, TimeUnit.MILLISECONDS); - this.table = token; - this.sunnylabsHost = sunnylabsHost; - this.host = InetAddress.getLocalHost().getHostName(); + super(registry, "json-reporter", filter, rateUnit, durationUnit); + this.token = token; + this.hostname = hostname; + this.host = InetAddress.getLocalHost().getHostName(); } @Override @@ -57,7 +57,7 @@ public class JsonMetricsReporter extends ScheduledReporter { { try { logger.debug("Reporting metrics..."); - URL url = new URL("https", sunnylabsHost, 443, "/report/metrics?t=" + table + "&h=" + host); + URL url = new URL("https", hostname, 443, String.format("/report/metrics?t=%s&h=%s", token, host)); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); @@ -175,10 +175,66 @@ public class JsonMetricsReporter extends ScheduledReporter { json.writeNumberField("m15", convertRate(meter.getFifteenMinuteRate())); } - private static final Pattern SIMPLE_NAMES = Pattern.compile("[^a-zA-Z0-9_.\\-~]"); private String sanitize(String metricName) { return SIMPLE_NAMES.matcher(metricName).replaceAll("_"); } + public static Builder forRegistry(MetricRegistry registry) { + return new Builder(registry); + } + + public static class Builder { + + private final MetricRegistry registry; + private MetricFilter filter = MetricFilter.ALL; + private TimeUnit rateUnit = TimeUnit.SECONDS; + private TimeUnit durationUnit = TimeUnit.MILLISECONDS; + private String token; + private String hostname; + + private Builder(MetricRegistry registry) { + this.registry = registry; + this.rateUnit = TimeUnit.SECONDS; + this.durationUnit = TimeUnit.MILLISECONDS; + this.filter = MetricFilter.ALL; + } + + public Builder convertRatesTo(TimeUnit rateUnit) { + this.rateUnit = rateUnit; + return this; + } + + public Builder convertDurationsTo(TimeUnit durationUnit) { + this.durationUnit = durationUnit; + return this; + } + + public Builder filter(MetricFilter filter) { + this.filter = filter; + return this; + } + + public Builder withToken(String token) { + this.token = token; + return this; + } + + public Builder withHostname(String hostname) { + this.hostname = hostname; + return this; + } + + public JsonMetricsReporter build() throws UnknownHostException { + if (hostname == null) { + throw new IllegalArgumentException("No hostname specified!"); + } + + if (token == null) { + throw new IllegalArgumentException("No token specified!"); + } + + return new JsonMetricsReporter(registry, token, hostname, filter, rateUnit, durationUnit); + } + } } \ No newline at end of file diff --git a/src/main/java/org/whispersystems/textsecuregcm/metrics/JsonMetricsReporterFactory.java b/src/main/java/org/whispersystems/textsecuregcm/metrics/JsonMetricsReporterFactory.java new file mode 100644 index 000000000..110d2fb20 --- /dev/null +++ b/src/main/java/org/whispersystems/textsecuregcm/metrics/JsonMetricsReporterFactory.java @@ -0,0 +1,38 @@ +package org.whispersystems.textsecuregcm.metrics; + +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.ScheduledReporter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeName; + +import javax.validation.constraints.NotNull; +import java.net.UnknownHostException; + +import io.dropwizard.metrics.BaseReporterFactory; + +@JsonTypeName("json") +public class JsonMetricsReporterFactory extends BaseReporterFactory { + + @JsonProperty + @NotNull + private String hostname; + + @JsonProperty + @NotNull + private String token; + + @Override + public ScheduledReporter build(MetricRegistry metricRegistry) { + try { + return JsonMetricsReporter.forRegistry(metricRegistry) + .withHostname(hostname) + .withToken(token) + .convertRatesTo(getRateUnit()) + .convertDurationsTo(getDurationUnit()) + .filter(getFilter()) + .build(); + } catch (UnknownHostException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/src/main/resources/META-INF/services/io.dropwizard.metrics.ReporterFactory b/src/main/resources/META-INF/services/io.dropwizard.metrics.ReporterFactory new file mode 100644 index 000000000..bdc070f96 --- /dev/null +++ b/src/main/resources/META-INF/services/io.dropwizard.metrics.ReporterFactory @@ -0,0 +1 @@ +org.whispersystems.textsecuregcm.metrics.JsonMetricsReporterFactory \ No newline at end of file