diff --git a/apiv3.properties b/apiv3.properties index 91d5af4..72ca81c 100644 --- a/apiv3.properties +++ b/apiv3.properties @@ -6,6 +6,9 @@ mongo.password= redis.address=209.222.96.50 redis.port=6379 http.port=80 +librato.email=cmcdonald.main@gmail.com +librato.apiToken=a818c3eca8a59d6d9cf76dc9f0d237c6aa97f257c482ce3363cf55a5431bc153 +librato.sourceIdentifier=apiv3-dev-01 mandrill.apiKey=0OYtwymqJP6oqvszeJu0vQ maxMind.userId=66817 maxMind.maxMindLicenseKey=8Aw9NsOUeOp7 diff --git a/pom.xml b/pom.xml index a2fcb16..60b4846 100644 --- a/pom.xml +++ b/pom.xml @@ -84,6 +84,11 @@ vertx-circuit-breaker 3.3.0 + + io.vertx + vertx-dropwizard-metrics + 3.3.0 + @@ -114,6 +119,13 @@ 2.7.0 + + + com.librato.metrics + metrics-librato + 4.1.2.5 + + com.warrenstrange diff --git a/src/main/java/net/frozenorb/apiv3/APIv3.java b/src/main/java/net/frozenorb/apiv3/APIv3.java index c63b3bf..ede4b58 100644 --- a/src/main/java/net/frozenorb/apiv3/APIv3.java +++ b/src/main/java/net/frozenorb/apiv3/APIv3.java @@ -1,5 +1,7 @@ package net.frozenorb.apiv3; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.SharedMetricRegistries; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.PropertyAccessor; @@ -9,6 +11,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.net.MediaType; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.librato.metrics.LibratoReporter; import com.mongodb.ConnectionString; import com.mongodb.MongoCredential; import com.mongodb.async.client.MongoClient; @@ -35,8 +38,10 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.frozenorb.apiv3.handler.ActorAttributeHandler; import net.frozenorb.apiv3.handler.AuthorizationHandler; +import net.frozenorb.apiv3.handler.MetricsHandler; import net.frozenorb.apiv3.model.*; import net.frozenorb.apiv3.route.GETDumpsType; +import net.frozenorb.apiv3.route.GETMetrics; import net.frozenorb.apiv3.route.GETWhoAmI; import net.frozenorb.apiv3.route.accessTokens.DELETEAccessTokensId; import net.frozenorb.apiv3.route.accessTokens.GETAccessTokens; @@ -121,6 +126,7 @@ public final class APIv3 extends AbstractVerticle { vertxInstance = vertx; setupConfig(); setupDatabase(); + setupMetrics(); setupHttpServer(); /*V2Importer converter = new V2Importer("mongodb://158.69.126.126", "minehq"); @@ -233,6 +239,19 @@ public final class APIv3 extends AbstractVerticle { return mongoJacksonMapper; } + private void setupMetrics() { + MetricRegistry registry = SharedMetricRegistries.getOrCreate("apiv3-registry"); + + LibratoReporter.enable( + LibratoReporter.builder( + registry, + config.getProperty("librato.email"), + config.getProperty("librato.apiToken"), + config.getProperty("librato.sourceIdentifier")), + 10, + TimeUnit.SECONDS); + } + private void setupHttpServer() { HttpServer webServer = vertx.createHttpServer( new HttpServerOptions() @@ -246,6 +265,7 @@ public final class APIv3 extends AbstractVerticle { http.route().handler(LoggerHandler.create(LoggerFormat.TINY)); http.route().handler(TimeoutHandler.create(TimeUnit.SECONDS.toMillis(5))); http.route().handler(new ActorAttributeHandler()); + http.route().handler(new MetricsHandler()); http.route().handler(new AuthorizationHandler()); http.route().method(HttpMethod.PUT).method(HttpMethod.POST).method(HttpMethod.DELETE).handler(BodyHandler.create()); http.exceptionHandler(Throwable::printStackTrace); @@ -346,6 +366,7 @@ public final class APIv3 extends AbstractVerticle { http.post("/users/:userId/verifyTotp").handler(new POSTUsersIdVerifyTotp()); http.get("/dumps/:dumpType").handler(new GETDumpsType()); + http.get("/metrics").handler(new GETMetrics()); http.get("/whoami").handler(new GETWhoAmI()); int port = Integer.parseInt(config.getProperty("http.port")); diff --git a/src/main/java/net/frozenorb/apiv3/Main.java b/src/main/java/net/frozenorb/apiv3/Main.java index a427611..3bc06c3 100644 --- a/src/main/java/net/frozenorb/apiv3/Main.java +++ b/src/main/java/net/frozenorb/apiv3/Main.java @@ -1,6 +1,8 @@ package net.frozenorb.apiv3; import io.vertx.core.Vertx; +import io.vertx.core.VertxOptions; +import io.vertx.ext.dropwizard.DropwizardMetricsOptions; final class Main { @@ -8,7 +10,9 @@ final class Main { System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "error"); System.setProperty("org.slf4j.simpleLogger.showThreadName", "false"); System.setProperty("vertx.logger-delegate-factory-class-name", "io.vertx.core.logging.SLF4JLogDelegateFactory"); - Vertx.vertx().deployVerticle(new APIv3()); + Vertx.vertx(new VertxOptions().setMetricsOptions( + new DropwizardMetricsOptions().setEnabled(true).setRegistryName("apiv3-registry") + )).deployVerticle(new APIv3()); } } \ No newline at end of file diff --git a/src/main/java/net/frozenorb/apiv3/handler/MetricsHandler.java b/src/main/java/net/frozenorb/apiv3/handler/MetricsHandler.java new file mode 100644 index 0000000..1cbb2b6 --- /dev/null +++ b/src/main/java/net/frozenorb/apiv3/handler/MetricsHandler.java @@ -0,0 +1,30 @@ +package net.frozenorb.apiv3.handler; + +import io.vertx.core.Handler; +import io.vertx.ext.web.RoutingContext; +import io.vertx.redis.RedisClient; +import io.vertx.redis.RedisOptions; +import net.frozenorb.apiv3.APIv3; + +public final class MetricsHandler implements Handler { + + private static final RedisClient redisClient = RedisClient.create(APIv3.getVertxInstance(), + new RedisOptions() + .setAddress(APIv3.getConfig().getProperty("redis.address")) + .setPort(Integer.parseInt(APIv3.getConfig().getProperty("redis.port"))) + ); + + @Override + public void handle(RoutingContext ctx) { + redisClient.incr("apiv3:requests:total", (totalUpdateResult) -> { + if (totalUpdateResult.failed()) { + totalUpdateResult.cause().printStackTrace(); + } + }); + + // we purposely just immediately go on, we don't really care if + // this fails and are fine to just go on without it. + ctx.next(); + } + +} \ No newline at end of file diff --git a/src/main/java/net/frozenorb/apiv3/route/GETMetrics.java b/src/main/java/net/frozenorb/apiv3/route/GETMetrics.java new file mode 100644 index 0000000..8bbbacf --- /dev/null +++ b/src/main/java/net/frozenorb/apiv3/route/GETMetrics.java @@ -0,0 +1,18 @@ +package net.frozenorb.apiv3.route; + +import io.vertx.core.Handler; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.dropwizard.MetricsService; +import io.vertx.ext.web.RoutingContext; +import net.frozenorb.apiv3.APIv3; + +public final class GETMetrics implements Handler { + + public void handle(RoutingContext ctx) { + MetricsService metricsService = MetricsService.create(APIv3.getVertxInstance()); + JsonObject metrics = metricsService.getMetricsSnapshot(APIv3.getVertxInstance()); + + APIv3.respondJson(ctx, 200, metrics); + } + +} \ No newline at end of file