Java tutorial
package com.deblox.solacemonitor; /* Copyright 2015 Kegan Holtzhausen Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import com.deblox.Util; import io.netty.handler.codec.http.HttpHeaders; import io.vertx.core.AbstractVerticle; import io.vertx.core.Handler; import io.vertx.core.eventbus.EventBus; import io.vertx.core.Future; import io.vertx.core.http.HttpClient; import io.vertx.core.http.HttpClientRequest; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import java.util.*; import java.util.stream.Collectors; /** * Monitor some rest endpoints and put the results onto the EventBus for the clients */ public class MonitorVerticle extends AbstractVerticle { String server_version = "v1.2.8"; private static final Logger logger = LoggerFactory.getLogger(MonitorVerticle.class); EventBus eb; String uuid; HttpClient client; JsonObject config; String host; int port; String uri; String username; String password; String credentials; String method; Map<UUID, String> clients; /** * Start the verticle * * @param startFuture * @throws Exception */ public void start(Future<Void> startFuture) throws Exception { logger.info("starup with config: " + config().toString()); // read startup config config = config(); // vars host = config.getString("host", null); port = config.getInteger("port", 80); uri = config.getString("uri", "/"); username = config.getString("username", "DEFAULT_USERNAME"); password = config.getString("password", "DEFAULT_PASSWORD"); credentials = String.format("%s:%s", username, password); method = config.getString("method", "GET"); // map for connected clients clients = new HashMap<UUID, String>(); // generate a uuid uuid = UUID.randomUUID().toString(); // connect to the eventbus eb = vertx.eventBus(); // create a instance of http client client = vertx.createHttpClient(); // eventbus ping listner eb.consumer("ping-address", message -> { logger.info(uuid + ": replying"); message.reply("pong!"); }); // handler for requests for metrics eb.consumer("request-metrics", message -> { logger.info(uuid + ": requesting metrics"); try { getRest(message.body().toString(), event -> { logger.debug("response: " + event.toString()); if (config().getBoolean("convert_xml_response_to_json", false)) { message.reply(Util.xml2json(event.toString())); } else { message.reply(event.toString()); } }); } catch (Exception e) { logger.warn("unable to get metric"); e.printStackTrace(); } }); // returns a array of names for all metrics defined in config // used for setting up the client eb.consumer("request-config", message -> { String req = message.body().toString(); logger.debug("config request for: " + req); JsonObject response = new JsonObject(); // all = return a list of metrics if (req.equals("all")) { JsonArray results = new JsonArray(config.getJsonObject("metrics").stream() .filter(r -> ((JsonObject) r.getValue()).getBoolean("show_in_menu", true)) .map(r -> r.getKey()).sorted().collect(Collectors.toList())); response.put("metrics", results); } else { // get a specific metric's config response = config.getJsonObject("metrics").getJsonObject(req); response.put("topic", req); logger.debug(response.toString()); } message.reply(response); }); // register new clients eb.consumer("newclient", message -> { logger.info("new client: " + message.body().toString()); JsonObject client = new JsonObject(message.body().toString()); clients.remove(client.getString("uuid")); clients.put(UUID.fromString(client.getString("uuid")), client.getString("version")); }); // client ping maintains the clients map eb.consumer("client-ping", message -> { JsonObject client = new JsonObject(message.body().toString()); clients.remove(client.getString("uuid")); clients.put(UUID.fromString(client.getString("uuid")), client.getString("version")); }); // listen for broadcasts from other verticles / clients eb.consumer("broadcast", event -> { logger.info(event.body().toString()); JsonObject message = new JsonObject(event.body().toString()); broadcast(message.getString("topic", "unknown"), event.body().toString()); }); // create metric emitters Iterator iter = config.getJsonObject("metrics", new JsonObject()).iterator(); while (iter.hasNext()) { Map.Entry<String, JsonObject> metricConfig = (Map.Entry) iter.next(); logger.debug("registering metric: " + metricConfig.getKey()); int interval = metricConfig.getValue().getInteger("interval", 0); if (interval != 0) { vertx.setPeriodic(interval, tid -> { logger.debug("metric interval handler for " + metricConfig.getKey() + " every " + interval); try { getRest(metricConfig.getKey(), event -> { logger.debug("metric: " + event.toString()); JsonObject metricMessage = new JsonObject(); metricMessage.put("topic", metricConfig.getKey()); metricMessage.put("data", Util.xml2json(event.toString())); // get the config for the metric JsonObject msgConfig = config.getJsonObject("metrics") .getJsonObject(metricConfig.getKey()).getJsonObject("config", new JsonObject()); // get the view_format by name msgConfig.put("view_format", config.getJsonObject("views", new JsonObject()) .getJsonObject(msgConfig.getString("view", "default"))); // put the config into the message metricMessage.put("config", msgConfig); // publish the metric eb.publish(metricConfig.getKey(), metricMessage); }); } catch (Exception e) { logger.warn("unable to publish metric"); e.printStackTrace(); } }); } else { logger.warn("metric " + metricConfig.getKey() + " is disabled "); } } // after 10 seconds, announce the server version to all clients vertx.setTimer(10000, tid -> { broadcast("broadcast", "Server Startup " + config.getString("version", server_version)); }); // after 10 seconds, announce the server version to all clients vertx.setPeriodic(1000, tping -> { eb.publish("ping", new JsonObject().put("data", "ping")); }); // periodically nuke all the client sessions vertx.setPeriodic(config().getInteger("client_session_refresh", 300000), res -> { clients = new HashMap<UUID, String>(); }); // periodically log number of clients in the map vertx.setPeriodic(config().getInteger("client_session_show", 180000), res -> { logger.info(clients.size() + " connected clients"); }); startFuture.complete(); } /** * Broadcasts a message to all clients * * @param action the action name * @param msg the body / message */ public void broadcast(String action, String msg) { JsonObject message = new JsonObject(); message.put("action", action); message.put("data", msg); clients.forEach((k, v) -> { logger.info("sending broadcast to client: " + k + ": " + v); eb.send(k.toString(), message); }); } /** * Perform the actual rest call * * @param metricName the named metric as in conf.json * @param handler the handler to call with the results */ public void getRest(String metricName, Handler handler) { try { if (host == null) { logger.warn("no config"); } else { logger.debug(uuid + " getting metric: " + metricName + " from: " + host); HttpClientRequest req; // GET if (method.equals("GET")) { req = client.post(port, host, uri, resp -> { resp.bodyHandler(body -> { logger.debug("Response: " + body.toString()); handler.handle(body.toString()); }); }); // POST } else if (method.equals("POST")) { req = client.post(port, host, uri, resp -> { resp.bodyHandler(body -> { logger.debug("Response: " + body.toString()); handler.handle(body.toString()); }); }); // PUT } else if (method.equals("PUT")) { req = client.put(port, host, uri, resp -> { resp.bodyHandler(body -> { logger.debug("Response: " + body.toString()); handler.handle(body.toString()); }); }); // FTS } else { throw new Exception("method " + method + " is not supported"); } if (config.getBoolean("basic_auth", true)) { req.putHeader(HttpHeaders.Names.AUTHORIZATION, "Basic " + Base64.getEncoder().encodeToString(credentials.getBytes())); } req.end(config.getJsonObject("metrics").getJsonObject(metricName).getString("request")); } } catch (Exception e) { logger.warn(e.getMessage()); } } }