diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 00000000000..54051651ff6
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,34 @@
+{
+ "browser": true,
+
+ "bitwise":false,
+ "curly": true,
+ "eqnull": true,
+ "globalstrict": true,
+ "devel": true,
+ "eqeqeq": true,
+ "forin": false,
+ "immed": true,
+ "supernew": true,
+ "expr": true,
+ "indent": 2,
+ "latedef": true,
+ "newcap": true,
+ "noarg": true,
+ "noempty": true,
+ "undef": true,
+ "boss": true,
+ "trailing": false,
+ "laxbreak": true,
+ "laxcomma": true,
+ "sub": true,
+ "unused": true,
+
+ "maxlen": 140,
+
+ "globals": {
+ "define": true,
+ "require": true,
+ "Chromath": false
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index e69de29bb2d..520cc63dc16 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,44 @@
+
+
+## Grunt build system
+This grunt-based build system handles Kibana development environment setup for Marvel as well as building, packaging and distribution of the Marvel plugin. Note that you **must** run *grunt setup* before any other tasks as this build system reuses parts of the Kibana build system that must be fetched
+
+### Installing
+You will need node.js+npm and grunt. Node is available via brew, install grunt with the command below. Once grunt is installed you may run grunt tasks to setup your environment and build Marvel
+
+```npm install -g grunt```
+```npm install```
+
+### Tasks
+
+```grunt setup```
+
+**Run this first.** It will download the right Kibana version to ./vendor/kibana, copies the appropriate config.js to the right place and make any symlinks needed for a proper marvel/kibana environment
+
+```grunt server```
+
+Starts a web server on http://127.0.0.1:5601 pointing at the kibana directory, while also serving custom marvel panels
+
+```grunt jshint```
+
+Lints code without building
+
+```grunt build```
+
+Merges kibana and marvel code, builds Kibana and the plugin (via mvn) and puts them in ./build.
+
+```grunt package```
+
+Zips and tar+gzips the build in ./packages. Includes grunt build
+
+```grunt release```
+
+Uploads archives to download.elasticsearch.org/elasticsearch/marvel/marvel-VERSION.extention. Includes grunt build and grunt package. You will need S3 credentials in .aws-config.json. Format as so:
+
+```
+{
+ "key":"MY_KEY_HERE",
+ "secret":"your/long/secret/string"
+}
+
+```
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index bb0a2ebb7d6..00000000000
--- a/pom.xml
+++ /dev/null
@@ -1,135 +0,0 @@
-
-
- elasticsearch-marvel
- 4.0.0
- org.elasticsearch
- marvel
- 0.1.0-SNAPSHOT
- jar
- Elasticsearch Marvel
- 2013
-
-
- The Apache Software License, Version 2.0
- http://www.apache.org/licenses/LICENSE-2.0.txt
- repo
-
-
-
-
- org.sonatype.oss
- oss-parent
- 7
-
-
-
- 0.90.7-SNAPSHOT
-
-
-
-
- sonatype
- http://oss.sonatype.org/content/repositories/releases/
-
-
-
-
-
- org.elasticsearch
- elasticsearch
- ${elasticsearch.version}
- compile
-
-
-
- log4j
- log4j
- 1.2.17
- runtime
- true
-
-
-
- org.testng
- testng
- 6.8
- test
-
-
- org.hamcrest
- hamcrest-core
-
-
- junit
- junit
-
-
-
-
-
- org.hamcrest
- hamcrest-all
- 1.3
- test
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 2.3.2
-
-
- 1.6
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 2.11
-
-
- **/*Tests.java
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 2.1.2
-
-
- attach-sources
-
- jar
-
-
-
-
-
- maven-assembly-plugin
- 2.3
-
- false
- ${project.build.directory}/releases/
-
- ${basedir}/src/main/assemblies/plugin.xml
-
-
-
-
- package
-
- single
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/main/assemblies/plugin.xml b/src/main/assemblies/plugin.xml
deleted file mode 100644
index 2ccfc875e9c..00000000000
--- a/src/main/assemblies/plugin.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
- plugin
-
- zip
-
- false
-
-
- /
- true
- true
-
- org.elasticsearch:elasticsearch
-
-
-
-
\ No newline at end of file
diff --git a/src/main/java/org/elasticsearch/marvel/monitor/Plugin.java b/src/main/java/org/elasticsearch/marvel/monitor/Plugin.java
deleted file mode 100644
index 171d609a90e..00000000000
--- a/src/main/java/org/elasticsearch/marvel/monitor/Plugin.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.marvel.monitor;
-
-import org.elasticsearch.common.collect.ImmutableList;
-import org.elasticsearch.common.component.LifecycleComponent;
-import org.elasticsearch.common.inject.AbstractModule;
-import org.elasticsearch.common.inject.Module;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.plugins.AbstractPlugin;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-public class Plugin extends AbstractPlugin {
-
- public Plugin() {
- }
-
- @Override
- public String name() {
- return "Elasticsearch marvel - monitor";
- }
-
- @Override
- public String description() {
- return "Monitoring with an elastic sauce";
- }
-
- @Override
- public Collection modules(Settings settings) {
- Module m = new AbstractModule() {
-
- @Override
- protected void configure() {
- bind(StatsExportersService.class).asEagerSingleton();
- }
- };
- return ImmutableList.of(m);
- }
-
- @Override
- public Collection> services() {
- Collection> l = new ArrayList>();
- l.add(StatsExportersService.class);
- return l;
- }
-}
diff --git a/src/main/java/org/elasticsearch/marvel/monitor/StatsExportersService.java b/src/main/java/org/elasticsearch/marvel/monitor/StatsExportersService.java
deleted file mode 100644
index 0c3fdaeb030..00000000000
--- a/src/main/java/org/elasticsearch/marvel/monitor/StatsExportersService.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.marvel.monitor;
-import org.elasticsearch.ElasticSearchException;
-import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
-import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags;
-import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
-import org.elasticsearch.action.admin.indices.stats.ShardStats;
-import org.elasticsearch.client.Client;
-import org.elasticsearch.cluster.ClusterService;
-import org.elasticsearch.common.Nullable;
-import org.elasticsearch.common.collect.ImmutableSet;
-import org.elasticsearch.common.component.AbstractLifecycleComponent;
-import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.unit.TimeValue;
-import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
-import org.elasticsearch.common.util.concurrent.EsExecutors;
-import org.elasticsearch.discovery.Discovery;
-import org.elasticsearch.index.shard.ShardId;
-import org.elasticsearch.index.shard.service.IndexShard;
-import org.elasticsearch.indices.IndicesLifecycle;
-import org.elasticsearch.marvel.monitor.annotation.Annotation;
-import org.elasticsearch.marvel.monitor.annotation.ShardEventAnnotation;
-import org.elasticsearch.marvel.monitor.exporter.ESExporter;
-import org.elasticsearch.marvel.monitor.exporter.StatsExporter;
-import org.elasticsearch.indices.IndicesService;
-import org.elasticsearch.indices.InternalIndicesService;
-import org.elasticsearch.node.service.NodeService;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingDeque;
-
-public class StatsExportersService extends AbstractLifecycleComponent {
-
- private final InternalIndicesService indicesService;
- private final NodeService nodeService;
- private final ClusterService clusterService;
- private final Client client;
-
- private final IndicesLifecycle.Listener indicesLifeCycleListener;
-
- private volatile ExportingWorker exp;
- private volatile Thread thread;
- private final TimeValue interval;
-
- private Collection exporters;
-
- private final BlockingQueue pendingAnnotationsQueue;
-
- @Inject
- public StatsExportersService(Settings settings, IndicesService indicesService,
- NodeService nodeService, ClusterService clusterService,
- Client client,
- Discovery discovery) {
- super(settings);
- this.indicesService = (InternalIndicesService) indicesService;
- this.clusterService = clusterService;
- this.nodeService = nodeService;
- this.interval = componentSettings.getAsTime("interval", TimeValue.timeValueSeconds(5));
- this.client = client;
-
- StatsExporter esExporter = new ESExporter(settings.getComponentSettings(ESExporter.class), discovery);
- this.exporters = ImmutableSet.of(esExporter);
-
- indicesLifeCycleListener = new IndicesLifeCycleListener();
- pendingAnnotationsQueue = ConcurrentCollections.newBlockingQueue();
- }
-
- @Override
- protected void doStart() throws ElasticSearchException {
- for (StatsExporter e : exporters)
- e.start();
-
- this.exp = new ExportingWorker();
- this.thread = new Thread(exp, EsExecutors.threadName(settings, "monitor"));
- this.thread.setDaemon(true);
- this.thread.start();
-
- indicesService.indicesLifecycle().addListener(indicesLifeCycleListener);
- }
-
- @Override
- protected void doStop() throws ElasticSearchException {
- this.exp.closed = true;
- this.thread.interrupt();
- try {
- this.thread.join(60000);
- } catch (InterruptedException e) {
- // we don't care...
- }
- for (StatsExporter e : exporters)
- e.stop();
-
- indicesService.indicesLifecycle().removeListener(indicesLifeCycleListener);
-
- }
-
- @Override
- protected void doClose() throws ElasticSearchException {
- for (StatsExporter e : exporters)
- e.close();
- }
-
- class ExportingWorker implements Runnable {
-
- volatile boolean closed;
-
- @Override
- public void run() {
- while (!closed) {
- // sleep first to allow node to complete initialization before collecting the first start
- try {
- Thread.sleep(interval.millis());
- } catch (InterruptedException e) {
- // ignore, if closed, good....
- }
-
- // do the actual export..., go over the actual exporters list and...
- try {
- exportNodeStats();
-
- exportShardStats();
-
- exportAnnotations();
-
- if (clusterService.state().nodes().localNodeMaster()) {
- exportIndicesStats();
- }
- } catch (Throwable t) {
- logger.error("Background thread had an uncaught exception:", t);
- }
-
- }
-
- logger.debug("shutting down worker, exporting pending annotation");
- exportAnnotations();
-
- logger.debug("worker shutdown");
- }
-
- private void exportIndicesStats() {
- logger.debug("local node is master, exporting aggregated stats");
- IndicesStatsResponse indicesStatsResponse = client.admin().indices().prepareStats().all().get();
- for (StatsExporter e : exporters) {
- try {
- e.exportIndicesStats(indicesStatsResponse);
- } catch (Throwable t) {
- logger.error("StatsExporter [{}] has thrown an exception:", t, e.name());
- }
-
-
- }
- }
-
- private void exportAnnotations() {
- logger.debug("Exporting annotations");
- ArrayList annotationsList = new ArrayList(pendingAnnotationsQueue.size());
- pendingAnnotationsQueue.drainTo(annotationsList);
- Annotation[] annotations = new Annotation[annotationsList.size()];
- annotationsList.toArray(annotations);
-
- for (StatsExporter e : exporters) {
- try {
- e.exportAnnotations(annotations);
- } catch (Throwable t) {
- logger.error("StatsExporter [{}] has thrown an exception:", t, e.name());
- }
- }
- }
-
- private void exportShardStats() {
- logger.debug("Collecting shard stats");
- ShardStats[] shardStatsArray = indicesService.shardStats(CommonStatsFlags.ALL);
-
- logger.debug("Exporting shards stats");
- for (StatsExporter e : exporters) {
- try {
- e.exportShardStats(shardStatsArray);
- } catch (Throwable t) {
- logger.error("StatsExporter [{}] has thrown an exception:", t, e.name());
- }
- }
- }
-
- private void exportNodeStats() {
- logger.debug("Collecting node stats");
- NodeStats nodeStats = nodeService.stats();
-
- logger.debug("Exporting node stats");
- for (StatsExporter e : exporters) {
- try {
- e.exportNodeStats(nodeStats);
- } catch (Throwable t) {
- logger.error("StatsExporter [{}] has thrown an exception:", t, e.name());
- }
- }
- }
- }
-
-
- class IndicesLifeCycleListener extends IndicesLifecycle.Listener {
- @Override
- public void afterIndexShardStarted(IndexShard indexShard) {
- pendingAnnotationsQueue.add(new ShardEventAnnotation(System.currentTimeMillis(), ShardEventAnnotation.EventType.STARTED,
- indexShard.shardId(), indexShard.routingEntry()));
-
- }
-
- @Override
- public void beforeIndexShardCreated(ShardId shardId) {
- pendingAnnotationsQueue.add(new ShardEventAnnotation(System.currentTimeMillis(), ShardEventAnnotation.EventType.CREATED,
- shardId, null));
- }
-
- @Override
- public void beforeIndexShardClosed(ShardId shardId, @Nullable IndexShard indexShard) {
- pendingAnnotationsQueue.add(new ShardEventAnnotation(System.currentTimeMillis(), ShardEventAnnotation.EventType.CLOSED,
- indexShard.shardId(), indexShard.routingEntry()));
-
- }
- }
-}
diff --git a/src/main/java/org/elasticsearch/marvel/monitor/annotation/Annotation.java b/src/main/java/org/elasticsearch/marvel/monitor/annotation/Annotation.java
deleted file mode 100644
index 9d883db4ccc..00000000000
--- a/src/main/java/org/elasticsearch/marvel/monitor/annotation/Annotation.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.marvel.monitor.annotation;
-import org.elasticsearch.common.joda.Joda;
-import org.elasticsearch.common.joda.time.format.DateTimeFormatter;
-import org.elasticsearch.common.xcontent.ToXContent;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-
-import java.io.IOException;
-
-public abstract class Annotation {
-
- public final static DateTimeFormatter datePrinter = Joda.forPattern("date_time").printer();
-
- protected long timestamp;
-
- public Annotation(long timestamp) {
- this.timestamp = timestamp;
- }
-
- public long timestamp() {
- return timestamp;
- }
-
- /**
- * @return annotation's type as a short string without spaces
- */
- public abstract String type();
-
- /**
- * should return a short string based description of the annotation
- */
- abstract String conciseDescription();
-
- @Override
- public String toString() {
- return "[" + type() + "] annotation: [" + conciseDescription() + "]";
- }
-
- public XContentBuilder addXContentBody(XContentBuilder builder, ToXContent.Params params) throws IOException {
- builder.field("@timestamp", datePrinter.print(timestamp));
- builder.field("message", conciseDescription());
- return builder;
- }
-}
diff --git a/src/main/java/org/elasticsearch/marvel/monitor/annotation/ShardEventAnnotation.java b/src/main/java/org/elasticsearch/marvel/monitor/annotation/ShardEventAnnotation.java
deleted file mode 100644
index a99ae5bfdbf..00000000000
--- a/src/main/java/org/elasticsearch/marvel/monitor/annotation/ShardEventAnnotation.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.marvel.monitor.annotation;
-import org.elasticsearch.cluster.routing.ShardRouting;
-import org.elasticsearch.common.xcontent.ToXContent;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.index.shard.ShardId;
-
-import java.io.IOException;
-
-public class ShardEventAnnotation extends Annotation {
-
- private final ShardRouting shardRouting;
- private final ShardId shardId;
- private EventType event;
-
- public enum EventType {
- CREATED,
- STARTED,
- CLOSED
- }
-
-
- public ShardEventAnnotation(long timestamp, EventType event, ShardId shardId, ShardRouting shardRouting) {
- super(timestamp);
- this.event = event;
- this.shardId = shardId;
- this.shardRouting = shardRouting;
- }
-
- @Override
- public String type() {
- return "shard_event";
- }
-
- @Override
- String conciseDescription() {
- return "[" + event + "]" + (shardRouting != null ? shardRouting : shardId);
- }
-
- @Override
- public XContentBuilder addXContentBody(XContentBuilder builder, ToXContent.Params params) throws IOException {
- super.addXContentBody(builder, params);
- builder.field("event", event);
- builder.field("index", shardId.index());
- builder.field("shard_id", shardId.id());
- if (shardRouting != null) {
- builder.field("routing");
- shardRouting.toXContent(builder, params);
- }
-
- return builder;
- }
-}
diff --git a/src/main/java/org/elasticsearch/marvel/monitor/exporter/ESExporter.java b/src/main/java/org/elasticsearch/marvel/monitor/exporter/ESExporter.java
deleted file mode 100644
index 3233f4a389e..00000000000
--- a/src/main/java/org/elasticsearch/marvel/monitor/exporter/ESExporter.java
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.marvel.monitor.exporter;
-import org.elasticsearch.ElasticSearchException;
-import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
-import org.elasticsearch.action.admin.indices.stats.CommonStats;
-import org.elasticsearch.action.admin.indices.stats.IndexStats;
-import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
-import org.elasticsearch.action.admin.indices.stats.ShardStats;
-import org.elasticsearch.cluster.node.DiscoveryNode;
-import org.elasticsearch.cluster.routing.ShardRouting;
-import org.elasticsearch.common.collect.ImmutableMap;
-import org.elasticsearch.common.component.AbstractLifecycleComponent;
-import org.elasticsearch.common.joda.Joda;
-import org.elasticsearch.common.joda.time.format.DateTimeFormat;
-import org.elasticsearch.common.joda.time.format.DateTimeFormatter;
-import org.elasticsearch.common.logging.ESLogger;
-import org.elasticsearch.common.logging.ESLoggerFactory;
-import org.elasticsearch.common.network.NetworkUtils;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.transport.InetSocketTransportAddress;
-import org.elasticsearch.common.unit.TimeValue;
-import org.elasticsearch.common.xcontent.ToXContent;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.common.xcontent.XContentFactory;
-import org.elasticsearch.common.xcontent.XContentType;
-import org.elasticsearch.common.xcontent.smile.SmileXContent;
-import org.elasticsearch.discovery.Discovery;
-import org.elasticsearch.marvel.monitor.annotation.Annotation;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.InetAddress;
-import java.net.URL;
-import java.util.Map;
-
-public class ESExporter extends AbstractLifecycleComponent implements StatsExporter {
-
- final String[] hosts;
- final String indexPrefix;
- final DateTimeFormatter indexTimeFormatter;
- final int timeout;
-
- final Discovery discovery;
- final String hostname;
-
- // TODO: logger name is not good now. Figure out why.
- final ESLogger logger = ESLoggerFactory.getLogger(ESExporter.class.getName());
-
- public final static DateTimeFormatter defaultDatePrinter = Joda.forPattern("date_time").printer();
-
- boolean checkedForIndexTemplate = false;
-
- final NodeStatsRenderer nodeStatsRenderer;
- final ShardStatsRenderer shardStatsRenderer;
- final IndexStatsRenderer indexStatsRenderer;
- final IndicesStatsRenderer indicesStatsRenderer;
- final AnnotationsRenderer annotationsRenderer;
-
- public ESExporter(Settings settings, Discovery discovery) {
- super(settings);
-
- this.discovery = discovery;
- InetAddress address = NetworkUtils.getLocalAddress();
- this.hostname = address == null ? null : address.getHostName();
-
-
- hosts = settings.getAsArray("hosts", new String[]{"localhost:9200"});
- indexPrefix = settings.get("index.prefix", "marvel");
- String indexTimeFormat = settings.get("index.timeformat", "YYYY.MM.dd");
- indexTimeFormatter = DateTimeFormat.forPattern(indexTimeFormat).withZoneUTC();
-
- timeout = (int) settings.getAsTime("timeout", new TimeValue(6000)).seconds();
-
- nodeStatsRenderer = new NodeStatsRenderer();
- shardStatsRenderer = new ShardStatsRenderer();
- indexStatsRenderer = new IndexStatsRenderer();
- indicesStatsRenderer = new IndicesStatsRenderer();
- annotationsRenderer = new AnnotationsRenderer();
-
- logger.info("ESExporter initialized. Targets: {}, index prefix [{}], index time format [{}]", hosts, indexPrefix, indexTimeFormat);
- }
-
- @Override
- public String name() {
- return "ESExporter";
- }
-
-
- @Override
- public void exportNodeStats(NodeStats nodeStats) {
- nodeStatsRenderer.reset(nodeStats);
- exportXContent(nodeStatsRenderer);
- }
-
- @Override
- public void exportShardStats(ShardStats[] shardStatsArray) {
- shardStatsRenderer.reset(shardStatsArray);
- exportXContent(shardStatsRenderer);
- }
-
- @Override
- public void exportIndicesStats(IndicesStatsResponse indicesStats) {
- Map perIndexStats = indicesStats.getIndices();
- indexStatsRenderer.reset(perIndexStats.values().toArray(new IndexStats[perIndexStats.size()]));
- indicesStatsRenderer.reset(indicesStats.getTotal(), indicesStats.getPrimaries());
- logger.debug("exporting index_stats + indices_stats");
- HttpURLConnection conn = openExportingConnection();
- if (conn == null) {
- return;
- }
- try {
- addXContentRendererToConnection(conn, indexStatsRenderer);
- addXContentRendererToConnection(conn, indicesStatsRenderer);
- sendCloseExportingConnection(conn);
- } catch (IOException e) {
- logger.error("error sending data", e);
- return;
- }
- }
-
- @Override
- public void exportAnnotations(Annotation[] annotations) {
- annotationsRenderer.reset(annotations);
- exportXContent(annotationsRenderer);
- }
-
-
- private HttpURLConnection openExportingConnection() {
- if (!checkedForIndexTemplate) {
- if (!checkForIndexTemplate()) {
- logger.debug("no template defined yet. skipping");
- return null;
- }
- }
-
- logger.trace("setting up an export connection");
- HttpURLConnection conn = openConnection("POST", "/_bulk", XContentType.SMILE.restContentType());
- if (conn == null) {
- logger.error("could not connect to any configured elasticsearch instances: [{}]", hosts);
- }
- return conn;
- }
-
- private void addXContentRendererToConnection(HttpURLConnection conn,
- MultiXContentRenderer renderer) throws IOException {
- OutputStream os = conn.getOutputStream();
- // TODO: find a way to disable builder's substream flushing or something neat solution
- for (int i = 0; i < renderer.length(); i++) {
- XContentBuilder builder = XContentFactory.smileBuilder(os);
- builder.startObject().startObject("index")
- .field("_index", getIndexName()).field("_type", renderer.type(i)).endObject().endObject();
- builder.flush();
- os.write(SmileXContent.smileXContent.streamSeparator());
-
- builder = XContentFactory.smileBuilder(os);
- builder.humanReadable(false);
- renderer.render(i, builder);
- builder.flush();
- os.write(SmileXContent.smileXContent.streamSeparator());
- }
- }
-
- private void sendCloseExportingConnection(HttpURLConnection conn) throws IOException {
- logger.trace("sending exporting content");
- OutputStream os = conn.getOutputStream();
- os.close();
-
- if (conn.getResponseCode() != 200) {
- logConnectionError("remote target didn't respond with 200 OK", conn);
- } else {
- conn.getInputStream().close(); // close and release to connection pool.
- }
- }
-
- private void exportXContent(MultiXContentRenderer xContentRenderer) {
- if (xContentRenderer.length() == 0) {
- return;
- }
-
- HttpURLConnection conn = openExportingConnection();
- if (conn == null) {
- return;
- }
- try {
- addXContentRendererToConnection(conn, xContentRenderer);
- sendCloseExportingConnection(conn);
- } catch (IOException e) {
- logger.error("error sending data", e);
- return;
- }
-
- }
-
- @Override
- protected void doStart() throws ElasticSearchException {
- }
-
-
- @Override
- protected void doStop() throws ElasticSearchException {
- }
-
- @Override
- protected void doClose() throws ElasticSearchException {
- }
-
-
- private String getIndexName() {
- return indexPrefix + "-" + indexTimeFormatter.print(System.currentTimeMillis());
-
- }
-
-
- private HttpURLConnection openConnection(String method, String uri) {
- return openConnection(method, uri, null);
- }
-
- private HttpURLConnection openConnection(String method, String uri, String contentType) {
- for (String host : hosts) {
- try {
- URL templateUrl = new URL("http://" + host + uri);
- HttpURLConnection conn = (HttpURLConnection) templateUrl.openConnection();
- conn.setRequestMethod(method);
- conn.setConnectTimeout(timeout);
- if (contentType != null) {
- conn.setRequestProperty("Content-Type", XContentType.SMILE.restContentType());
- }
- conn.setUseCaches(false);
- if (method.equalsIgnoreCase("POST") || method.equalsIgnoreCase("PUT")) {
- conn.setDoOutput(true);
- }
- conn.connect();
-
- return conn;
- } catch (IOException e) {
- logger.error("error connecting to [{}]", e, host);
- }
- }
-
- return null;
- }
-
- private boolean checkForIndexTemplate() {
- try {
-
-
- String templateName = "marvel.monitor." + indexPrefix;
-
- logger.debug("checking of target has template [{}]", templateName);
- // DO HEAD REQUEST, when elasticsearch supports it
- HttpURLConnection conn = openConnection("GET", "/_template/" + templateName);
- if (conn == null) {
- logger.error("Could not connect to any configured elasticsearch instances: [{}]", hosts);
- return false;
- }
-
- boolean hasTemplate = conn.getResponseCode() == 200;
-
- // nothing there, lets create it
- if (!hasTemplate) {
- logger.debug("no template found in elasticsearch for [{}]. Adding...", templateName);
- conn = openConnection("PUT", "/_template/" + templateName, XContentType.SMILE.restContentType());
- OutputStream os = conn.getOutputStream();
- XContentBuilder builder = XContentFactory.smileBuilder(os);
- builder.startObject();
- builder.field("template", indexPrefix + "*");
- builder.startObject("mappings").startObject("_default_");
- builder.startArray("dynamic_templates").startObject().startObject("string_fields")
- .field("match", "*")
- .field("match_mapping_type", "string")
- .startObject("mapping").field("index", "not_analyzed").endObject()
- .endObject().endObject().endArray();
- builder.endObject().endObject(); // mapping + root object.
- builder.close();
- os.close();
-
- if (conn.getResponseCode() != 200) {
- logConnectionError("error adding index template to elasticsearch", conn);
- }
- conn.getInputStream().close(); // close and release to connection pool.
-
- }
- checkedForIndexTemplate = true;
- } catch (IOException e) {
- logger.error("error when checking/adding template to elasticsearch", e);
- return false;
- }
- return true;
- }
-
- private void logConnectionError(String msg, HttpURLConnection conn) {
- InputStream inputStream = conn.getErrorStream();
- java.util.Scanner s = new java.util.Scanner(inputStream, "UTF-8").useDelimiter("\\A");
- String err = s.hasNext() ? s.next() : "";
- try {
- logger.error("{} response code [{} {}]. content: {}", msg, conn.getResponseCode(), conn.getResponseMessage(), err);
- } catch (IOException e) {
- logger.error("connection had an error while reporting the error. tough life.");
- }
- }
-
- interface MultiXContentRenderer {
-
- int length();
-
- String type(int i);
-
- void render(int index, XContentBuilder builder) throws IOException;
- }
-
-
- private void addNodeInfo(XContentBuilder builder) throws IOException {
- addNodeInfo(builder, "node");
- }
-
- private void addNodeInfo(XContentBuilder builder, String fieldname) throws IOException {
- builder.startObject(fieldname);
- DiscoveryNode node = discovery.localNode();
- builder.field("id", node.id());
- builder.field("name", node.name());
- builder.field("transport_address", node.address());
-
- if (node.address().uniqueAddressTypeId() == 1) { // InetSocket
- InetSocketTransportAddress address = (InetSocketTransportAddress) node.address();
- InetAddress inetAddress = address.address().getAddress();
- if (inetAddress != null) {
- builder.field("ip", inetAddress.getHostAddress());
- }
- }
-
- if (hostname != null) {
- builder.field("hostname", hostname);
- }
-
- if (!node.attributes().isEmpty()) {
- builder.startObject("attributes");
- for (Map.Entry attr : node.attributes().entrySet()) {
- builder.field(attr.getKey(), attr.getValue());
- }
- builder.endObject();
- }
- builder.endObject();
- }
-
-
- class NodeStatsRenderer implements MultiXContentRenderer {
-
- NodeStats stats;
- ToXContent.MapParams xContentParams = new ToXContent.MapParams(
- ImmutableMap.of("node_info_format", "none", "load_average_format", "hash"));
-
- public void reset(NodeStats stats) {
- this.stats = stats;
- }
-
- @Override
- public int length() {
- return 1;
- }
-
- @Override
- public String type(int i) {
- return "node_stats";
- }
-
- @Override
- public void render(int index, XContentBuilder builder) throws IOException {
- builder.startObject();
- builder.field("@timestamp", defaultDatePrinter.print(stats.getTimestamp()));
- addNodeInfo(builder);
- stats.toXContent(builder, xContentParams);
- builder.endObject();
- }
- }
-
- class ShardStatsRenderer implements MultiXContentRenderer {
-
- ShardStats[] stats;
- long collectionTime;
- ToXContent.Params xContentParams = ToXContent.EMPTY_PARAMS;
-
- public void reset(ShardStats[] stats) {
- this.stats = stats;
- collectionTime = System.currentTimeMillis();
- }
-
- @Override
- public int length() {
- return stats == null ? 0 : stats.length;
- }
-
- @Override
- public String type(int i) {
- return "shard_stats";
- }
-
- @Override
- public void render(int index, XContentBuilder builder) throws IOException {
- builder.startObject();
- builder.field("@timestamp", defaultDatePrinter.print(collectionTime));
- ShardRouting shardRouting = stats[index].getShardRouting();
- builder.field("index", shardRouting.index());
- builder.field("shard_id", shardRouting.id());
- builder.field("shard_state", shardRouting.state());
- builder.field("primary", shardRouting.primary());
- addNodeInfo(builder);
- stats[index].getStats().toXContent(builder, xContentParams);
- builder.endObject();
- }
- }
-
- class IndexStatsRenderer implements MultiXContentRenderer {
-
- IndexStats[] stats;
- long collectionTime;
- ToXContent.Params xContentParams = ToXContent.EMPTY_PARAMS;
-
- public void reset(IndexStats[] stats) {
- this.stats = stats;
- collectionTime = System.currentTimeMillis();
- }
-
- @Override
- public int length() {
- return stats == null ? 0 : stats.length;
- }
-
- @Override
- public String type(int i) {
- return "index_stats";
- }
-
- @Override
- public void render(int index, XContentBuilder builder) throws IOException {
- builder.startObject();
- builder.field("@timestamp", defaultDatePrinter.print(collectionTime));
- IndexStats indexStats = stats[index];
- builder.field("index", indexStats.getIndex());
- addNodeInfo(builder, "_source_node");
- builder.startObject("primaries");
- indexStats.getPrimaries().toXContent(builder, xContentParams);
- builder.endObject();
- builder.startObject("total");
- indexStats.getTotal().toXContent(builder, xContentParams);
- builder.endObject();
- builder.endObject();
- }
- }
-
- class IndicesStatsRenderer implements MultiXContentRenderer {
-
- CommonStats totalStats;
- CommonStats primariesStats;
- long collectionTime;
- ToXContent.Params xContentParams = ToXContent.EMPTY_PARAMS;
-
- public void reset(CommonStats totalStats, CommonStats primariesStats) {
- this.totalStats = totalStats;
- this.primariesStats = primariesStats;
- collectionTime = System.currentTimeMillis();
- }
-
- @Override
- public int length() {
- return totalStats == null ? 0 : 1;
- }
-
- @Override
- public String type(int i) {
- return "indices_stats";
- }
-
- @Override
- public void render(int index, XContentBuilder builder) throws IOException {
- assert index == 0;
- builder.startObject();
- builder.field("@timestamp", defaultDatePrinter.print(collectionTime));
- addNodeInfo(builder, "_source_node");
- builder.startObject("primaries");
- primariesStats.toXContent(builder, xContentParams);
- builder.endObject();
- builder.startObject("total");
- totalStats.toXContent(builder, xContentParams);
- builder.endObject();
- builder.endObject();
- }
- }
-
-
- class AnnotationsRenderer implements MultiXContentRenderer {
-
- Annotation[] annotations;
- ToXContent.Params xContentParams = ToXContent.EMPTY_PARAMS;
-
- public void reset(Annotation[] annotations) {
- this.annotations = annotations;
- }
-
- @Override
- public int length() {
- return annotations == null ? 0 : annotations.length;
- }
-
- @Override
- public String type(int i) {
- return annotations[i].type();
- }
-
-
- @Override
- public void render(int index, XContentBuilder builder) throws IOException {
- builder.startObject();
- addNodeInfo(builder, "node");
- annotations[index].addXContentBody(builder, xContentParams);
- builder.endObject();
- }
- }
-
-}
-
diff --git a/src/main/java/org/elasticsearch/marvel/monitor/exporter/StatsExporter.java b/src/main/java/org/elasticsearch/marvel/monitor/exporter/StatsExporter.java
deleted file mode 100644
index ffec9d567f9..00000000000
--- a/src/main/java/org/elasticsearch/marvel/monitor/exporter/StatsExporter.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.marvel.monitor.exporter;
-import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
-import org.elasticsearch.action.admin.indices.stats.CommonStats;
-import org.elasticsearch.action.admin.indices.stats.IndexStats;
-import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
-import org.elasticsearch.action.admin.indices.stats.ShardStats;
-import org.elasticsearch.common.component.LifecycleComponent;
-import org.elasticsearch.marvel.monitor.annotation.Annotation;
-
-import java.util.Map;
-
-public interface StatsExporter extends LifecycleComponent {
-
- String name();
-
- void exportNodeStats(NodeStats nodeStats);
-
- void exportShardStats(ShardStats[] shardStatsArray);
-
- void exportIndicesStats(IndicesStatsResponse indicesStats);
-
- void exportAnnotations(Annotation[] annotations);
-}
diff --git a/src/main/resources/es-plugin.properties b/src/main/resources/es-plugin.properties
deleted file mode 100644
index 72b2c0afd39..00000000000
--- a/src/main/resources/es-plugin.properties
+++ /dev/null
@@ -1 +0,0 @@
-plugin=org.elasticsearch.marvel.monitor.Plugin
\ No newline at end of file