diff --git a/README.md b/README.md index 94b4fc2..bded513 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,14 @@ This client offers multiple ingestion methods optimized for various performance ## Documentation - [API Reference](https://javadoc.io/doc/io.greptime/ingester-protocol/latest/index.html) -- [Examples](https://github.com/GreptimeTeam/greptimedb-ingester-java/tree/main/ingester-example) +- [Examples](./ingester-example) ## Features - Writing data using - - [Regular Write API](https://github.com/GreptimeTeam/greptimedb-ingester-java/tree/main/ingester-example#regular-write-api) - - [Batching Write](https://github.com/GreptimeTeam/greptimedb-ingester-java/tree/main/ingester-example#batching-write) - - [Streaming Write](https://github.com/GreptimeTeam/greptimedb-ingester-java/tree/main/ingester-example#streaming-write) - - [Bulk Write API](https://github.com/GreptimeTeam/greptimedb-ingester-java/tree/main/ingester-example#bulk-write-api) + - [Regular Write API](./ingester-example#regular-write-api) + - [Batching Write](./ingester-example#batching-write) + - [Streaming Write](./ingester-example#streaming-write) + - [Bulk Write API](./ingester-example#bulk-write-api) - Management API client for managing - Health check - Authorizations @@ -100,6 +100,9 @@ This client offers multiple ingestion methods optimized for various performance - [Compression Options](#compression-options) - [Write Operation Comparison](#write-operation-comparison) - [Buffer Size Optimization](#buffer-size-optimization) +- [Export metrics](#export-metrics) +- [Build Requirements](#build-requirements) +- [Contributing](#contributing) ### Installation @@ -364,6 +367,12 @@ Table.TableBufferRoot table = bulkStreamWriter.tableBufferRoot(columnBufferSize) This option can significantly improve the speed of data conversion to the underlying format. For optimal performance, we recommend setting the column buffer size to 1024 or larger, depending on your specific workload characteristics and available memory. +### Export Metrics + +The ingester exposes comprehensive metrics that enable you to monitor its performance, health, and operational status. + +For detailed information about available metrics and their usage, refer to the [Ingester Prometheus Metrics](./ingester-prometheus-metrics/) documentation. + ### Build Requirements - Java 8+ diff --git a/ingester-example/src/main/java/io/greptime/bench/BatchingWriteBenchmark.java b/ingester-example/src/main/java/io/greptime/bench/BatchingWriteBenchmark.java index 36fd042..10e306e 100644 --- a/ingester-example/src/main/java/io/greptime/bench/BatchingWriteBenchmark.java +++ b/ingester-example/src/main/java/io/greptime/bench/BatchingWriteBenchmark.java @@ -21,6 +21,7 @@ import io.greptime.common.util.MetricsUtil; import io.greptime.common.util.ServiceLoader; import io.greptime.common.util.SystemPropertyUtil; +import io.greptime.metrics.ExporterOptions; import io.greptime.metrics.MetricsExporter; import io.greptime.models.Err; import io.greptime.models.Result; @@ -61,8 +62,8 @@ public static void main(String[] args) throws Exception { LOG.info("Max points per second: {}", maxPointsPerSecond); // Start a metrics exporter - MetricsExporter metricsExporter = new MetricsExporter(8080, MetricsUtil.metricRegistry()); - metricsExporter.init(null); + MetricsExporter metricsExporter = new MetricsExporter(MetricsUtil.metricRegistry()); + metricsExporter.init(ExporterOptions.newDefault()); GreptimeDB greptimeDB = DBConnector.connectTo(new String[] {endpoint}, dbName); diff --git a/ingester-example/src/main/java/io/greptime/bench/BulkWriteBenchmark.java b/ingester-example/src/main/java/io/greptime/bench/BulkWriteBenchmark.java index 204f74f..67e2998 100644 --- a/ingester-example/src/main/java/io/greptime/bench/BulkWriteBenchmark.java +++ b/ingester-example/src/main/java/io/greptime/bench/BulkWriteBenchmark.java @@ -22,6 +22,7 @@ import io.greptime.common.util.MetricsUtil; import io.greptime.common.util.ServiceLoader; import io.greptime.common.util.SystemPropertyUtil; +import io.greptime.metrics.ExporterOptions; import io.greptime.metrics.MetricsExporter; import io.greptime.models.Table; import io.greptime.models.TableSchema; @@ -55,8 +56,8 @@ public static void main(String[] args) throws Exception { LOG.info("Batch size: {}", batchSize); // Start a metrics exporter - MetricsExporter metricsExporter = new MetricsExporter(8080, MetricsUtil.metricRegistry()); - metricsExporter.init(null); + MetricsExporter metricsExporter = new MetricsExporter(MetricsUtil.metricRegistry()); + metricsExporter.init(ExporterOptions.newDefault()); GreptimeDB greptimeDB = DBConnector.connectTo(new String[] {endpoint}, dbName); diff --git a/ingester-example/src/main/java/io/greptime/bench/StreamingWriteBenchmark.java b/ingester-example/src/main/java/io/greptime/bench/StreamingWriteBenchmark.java index 7d99220..9fbd164 100644 --- a/ingester-example/src/main/java/io/greptime/bench/StreamingWriteBenchmark.java +++ b/ingester-example/src/main/java/io/greptime/bench/StreamingWriteBenchmark.java @@ -21,6 +21,7 @@ import io.greptime.common.util.MetricsUtil; import io.greptime.common.util.ServiceLoader; import io.greptime.common.util.SystemPropertyUtil; +import io.greptime.metrics.ExporterOptions; import io.greptime.metrics.MetricsExporter; import io.greptime.models.Table; import io.greptime.models.TableSchema; @@ -58,8 +59,8 @@ public static void main(String[] args) throws Exception { LOG.info("Max points per second: {}", maxPointsPerSecond); // Start a metrics exporter - MetricsExporter metricsExporter = new MetricsExporter(8080, MetricsUtil.metricRegistry()); - metricsExporter.init(null); + MetricsExporter metricsExporter = new MetricsExporter(MetricsUtil.metricRegistry()); + metricsExporter.init(ExporterOptions.newDefault()); GreptimeDB greptimeDB = DBConnector.connectTo(new String[] {endpoint}, dbName); diff --git a/ingester-prometheus-metrics/README.md b/ingester-prometheus-metrics/README.md new file mode 100644 index 0000000..1fe6aae --- /dev/null +++ b/ingester-prometheus-metrics/README.md @@ -0,0 +1,52 @@ +# Export Metrics + +Metrics monitoring is a critical component for ensuring optimal ingester performance and reliability. It provides: + +- Real-time visibility into ingester health and performance +- Proactive monitoring capabilities for maintaining system stability +- Rapid troubleshooting and issue resolution + +For detailed information about available metrics, including descriptions and usage guidelines, see our [comprehensive metrics documentation](../docs/metrics-display.md#list-of-metrics-constantly-updated). + +## Start Metrics Exporter + +To start an HTTP server that serves Prometheus metrics, initialize the metrics exporter before starting the GreptimeDB ingester: + +```java + MetricsExporter metricsExporter = new MetricsExporter(MetricsUtil.metricRegistry()); + metricsExporter.init(ExporterOptions.newDefault()); + // Start GreptimeDB ingester + // ... +``` + +## Get Metrics + +You can check the output of `curl http://:/metrics` by getting the latest metrics of the ingester. + +## Export Metrics to Prometheus + +The ingester supports exporting metrics to Prometheus. Before configuring export of metrics, you need to setup Prometheus by following their official [documentation](https://prometheus.io/docs/prometheus/latest/installation/). + +To scrape metrics from the ingester, write a Prometheus configuration file and save it as `prometheus.yml`: + +```yaml +global: + scrape_interval: 15s + +scrape_configs: + - job_name: 'greptimedb ingester' + static_configs: + # Assuming that the ingester is running locally. + # The default HTTP port of 8090. + - targets: ['localhost:8090'] +``` + +Start Prometheus using the configuration file: + +```bash +./prometheus --config.file=prometheus.yml +``` + +## Grafana Dashboard + +You can import dashboard via JSON model: [`greptimedb-ingester-dashboard.json`](../grafana/greptimedb-ingester-dashboard.json) diff --git a/ingester-prometheus-metrics/src/main/java/io/greptime/metrics/ExporterOptions.java b/ingester-prometheus-metrics/src/main/java/io/greptime/metrics/ExporterOptions.java new file mode 100644 index 0000000..9c4c288 --- /dev/null +++ b/ingester-prometheus-metrics/src/main/java/io/greptime/metrics/ExporterOptions.java @@ -0,0 +1,64 @@ +/* + * Copyright 2023 Greptime Team + * + * 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. + */ + +package io.greptime.metrics; + +import io.greptime.common.Copiable; +import io.greptime.common.Endpoint; + +/** + * Exporter options. + */ +public class ExporterOptions implements Copiable { + private Endpoint bind_addr; + private boolean deamon; + + public static ExporterOptions newDefault() { + ExporterOptions opts = new ExporterOptions(); + opts.bind_addr = new Endpoint("0.0.0.0", 8090); + opts.deamon = true; + return opts; + } + + public Endpoint getBindAddr() { + return bind_addr; + } + + public void setBindAddr(Endpoint bind_addr) { + this.bind_addr = bind_addr; + } + + public boolean isDeamon() { + return deamon; + } + + public void setDeamon(boolean deamon) { + this.deamon = deamon; + } + + @Override + public ExporterOptions copy() { + ExporterOptions opts = new ExporterOptions(); + opts.bind_addr = this.bind_addr; + opts.deamon = this.deamon; + return opts; + } + + @Override + public String toString() { + return "ExporterOptions{" + "bind_addr=" + bind_addr + ", deamon=" + deamon + '}'; + } +} diff --git a/ingester-prometheus-metrics/src/main/java/io/greptime/metrics/MetricsExporter.java b/ingester-prometheus-metrics/src/main/java/io/greptime/metrics/MetricsExporter.java index 03a83a2..f79aee7 100644 --- a/ingester-prometheus-metrics/src/main/java/io/greptime/metrics/MetricsExporter.java +++ b/ingester-prometheus-metrics/src/main/java/io/greptime/metrics/MetricsExporter.java @@ -17,6 +17,7 @@ package io.greptime.metrics; import com.codahale.metrics.MetricRegistry; +import io.greptime.common.Endpoint; import io.greptime.common.Lifecycle; import io.prometheus.client.CollectorRegistry; import io.prometheus.client.dropwizard.DropwizardExports; @@ -27,29 +28,31 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class MetricsExporter implements Lifecycle { +public class MetricsExporter implements Lifecycle { private static final Logger LOG = LoggerFactory.getLogger(MetricsExporter.class); private final CollectorRegistry prometheusMetricRegistry; - private final int port; private HTTPServer server; + private ExporterOptions opts; private final AtomicBoolean started = new AtomicBoolean(false); - public MetricsExporter(int port, MetricRegistry dropwizardMetricRegistry) { - this.port = port; + public MetricsExporter(MetricRegistry dropwizardMetricRegistry) { this.prometheusMetricRegistry = new CollectorRegistry(); this.prometheusMetricRegistry.register(new DropwizardExports(dropwizardMetricRegistry)); } @Override - public boolean init(Void opts) { + public boolean init(ExporterOptions opts) { if (this.started.compareAndSet(false, true)) { + this.opts = opts; try { - this.server = new HTTPServer(new InetSocketAddress(this.port), this.prometheusMetricRegistry, true); - LOG.info("Metrics exporter started at `http://localhost:{}/metrics`", this.port); + Endpoint bindAddr = opts.getBindAddr(); + InetSocketAddress socketAddress = new InetSocketAddress(bindAddr.getAddr(), bindAddr.getPort()); + this.server = new HTTPServer(socketAddress, this.prometheusMetricRegistry, opts.isDeamon()); + LOG.info("Metrics exporter started at `http://{}:{}/metrics`", bindAddr.getAddr(), bindAddr.getPort()); return true; } catch (IOException e) { this.started.set(false); @@ -69,4 +72,9 @@ public void shutdownGracefully() { } } } + + @Override + public String toString() { + return "MetricsExporter{" + "opts=" + opts + '}'; + } }