You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ro...@apache.org on 2022/01/16 16:14:25 UTC
[iotdb] branch master updated: [IOTDB-2191] Use IoTDB itself to collect runtime metrics (#4634)
This is an automated email from the ASF dual-hosted git repository.
rong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 478b9bd [IOTDB-2191] Use IoTDB itself to collect runtime metrics (#4634)
478b9bd is described below
commit 478b9bd1bbe0c0dc8575fb3eac98e01750040651
Author: Xieqijun <44...@users.noreply.github.com>
AuthorDate: Mon Jan 17 00:13:54 2022 +0800
[IOTDB-2191] Use IoTDB itself to collect runtime metrics (#4634)
---
docs/UserGuide/System-Tools/Metric-Tool.md | 2 +-
docs/zh/UserGuide/System-Tools/Metric-Tool.md | 2 +-
metrics/ReadMe.md | 1 +
.../reporter/prometheus/PrometheusReporter.java | 4 +-
.../main/assembly/resources/conf/iotdb-metric.yml | 3 +-
.../apache/iotdb/metrics/utils/ReporterType.java | 2 +-
.../iotdb/metrics/config/MetricConfigTest.java | 9 +-
.../src/{main => }/test/resources/iotdb-metric.yml | 3 +-
.../org.apache.iotdb.metrics.MetricManager | 2 +-
server/pom.xml | 5 +
.../java/org/apache/iotdb/db/conf/IoTDBConfig.java | 8 -
.../reporter/DropwizardIoTDBReporter.java | 74 +++++++
.../metrics/dropwizard/reporter/IoTDBReporter.java | 233 +++++++++++++++++++++
.../org/apache/iotdb/db/metrics/metricsUtils.java | 61 ++++++
.../micrometer/registry/IoTDBMeterRegistry.java | 150 +++++++++++++
.../micrometer/registry/IoTDBRegistryConfig.java | 16 +-
.../reporter/MicrometerIoTDBReporter.java | 94 +++++++++
.../services/org.apache.iotdb.metrics.Reporter | 3 +-
18 files changed, 641 insertions(+), 31 deletions(-)
diff --git a/docs/UserGuide/System-Tools/Metric-Tool.md b/docs/UserGuide/System-Tools/Metric-Tool.md
index 6f35665..0da55f6 100644
--- a/docs/UserGuide/System-Tools/Metric-Tool.md
+++ b/docs/UserGuide/System-Tools/Metric-Tool.md
@@ -198,7 +198,7 @@ The metrics collection switch is disabled by default,you need to enable it fro
# whether enable the module
enableMetric: false
-# Multiple reporter, options: [jmx, prometheus]
+# Multiple reporter, options: [jmx, prometheus, iotdb]. iotdb is off by default.
metricReporterList:
- jmx
- prometheus
diff --git a/docs/zh/UserGuide/System-Tools/Metric-Tool.md b/docs/zh/UserGuide/System-Tools/Metric-Tool.md
index 06108d2..0ec988d 100644
--- a/docs/zh/UserGuide/System-Tools/Metric-Tool.md
+++ b/docs/zh/UserGuide/System-Tools/Metric-Tool.md
@@ -196,7 +196,7 @@ metric采集默认是关闭的,需要先到conf/iotdb-metric.yml中打开后
# 是否启动监控模块,默认为false
enableMetric: false
-# 数据提供方式,对外部通过jmx和prometheus协议提供metrics的数据, 可选参数:[jmx, prometheus]
+# 数据提供方式,对外部通过jmx和prometheus协议提供metrics的数据, 可选参数:[jmx, prometheus, iotdb],iotdb是默认关闭的。
metricReporterList:
- jmx
- prometheus
diff --git a/metrics/ReadMe.md b/metrics/ReadMe.md
index ff1edb0..39c2be2 100644
--- a/metrics/ReadMe.md
+++ b/metrics/ReadMe.md
@@ -27,6 +27,7 @@ Metric Module
- In each implementation, you can use many types of reporter to report the details of metric
- Jmx Reporter
- Prometheus Reporter
+ - IoTDB Reporter
- [1. Design](#1-design)
- [1.1. Over all Design for acquisition System](#11-over-all-design-for-acquisition-system)
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/prometheus/PrometheusReporter.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/prometheus/PrometheusReporter.java
index c7a7e15..3a5561f 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/prometheus/PrometheusReporter.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/prometheus/PrometheusReporter.java
@@ -24,7 +24,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
-import java.util.Collections;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.ScheduledExecutorService;
@@ -161,8 +160,7 @@ public class PrometheusReporter extends ScheduledReporter {
RATE_UNIT,
DURATION_UNIT,
executor,
- shutdownExecutorOnStop,
- Collections.<MetricAttribute>emptySet());
+ shutdownExecutorOnStop);
this.prometheus = prometheus;
this.prefix = prefix;
}
diff --git a/metrics/interface/src/main/assembly/resources/conf/iotdb-metric.yml b/metrics/interface/src/main/assembly/resources/conf/iotdb-metric.yml
index cc5aee2..4255289 100644
--- a/metrics/interface/src/main/assembly/resources/conf/iotdb-metric.yml
+++ b/metrics/interface/src/main/assembly/resources/conf/iotdb-metric.yml
@@ -20,7 +20,8 @@
# whether enable the module
enableMetric: false
-# Multiple reporter, options: [jmx, prometheus]
+# Multiple reporter, options: [jmx, prometheus, iotdb]
+# iotdb is off by default
metricReporterList:
- jmx
- prometheus
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java
index 06792ba..0c9443c 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java
@@ -24,7 +24,7 @@ public enum ReporterType {
// why all below are in lower case.
jmx,
prometheus,
- internal;
+ iotdb;
@Override
public String toString() {
diff --git a/metrics/interface/src/main/test/org/apache/iotdb/metrics/config/MetricConfigTest.java b/metrics/interface/src/test/java/org/apache/iotdb/metrics/config/MetricConfigTest.java
similarity index 86%
rename from metrics/interface/src/main/test/org/apache/iotdb/metrics/config/MetricConfigTest.java
rename to metrics/interface/src/test/java/org/apache/iotdb/metrics/config/MetricConfigTest.java
index 1d8e9eb..a3aa295 100644
--- a/metrics/interface/src/main/test/org/apache/iotdb/metrics/config/MetricConfigTest.java
+++ b/metrics/interface/src/test/java/org/apache/iotdb/metrics/config/MetricConfigTest.java
@@ -21,12 +21,12 @@ package org.apache.iotdb.metrics.config;
import org.apache.iotdb.metrics.utils.PredefinedMetric;
import org.apache.iotdb.metrics.utils.ReporterType;
+
import org.junit.Assert;
import org.junit.Test;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
-import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -36,14 +36,14 @@ public class MetricConfigTest {
@Test
public void yamlConfigTest() {
- String url = this.getClass().getClassLoader().getResource("resources/iotdb-metric.yml").getPath();
+ String url = this.getClass().getClassLoader().getResource("iotdb-metric.yml").getPath();
System.out.println(url);
MetricConfig metricConfig = MetricConfigDescriptor.getInstance().getMetricConfig();
Constructor constructor = new Constructor(MetricConfig.class);
Yaml yaml = new Yaml(constructor);
if (url != null) {
- try (InputStream inputStream = new FileInputStream(new File(url))) {
+ try (InputStream inputStream = new FileInputStream(url)) {
metricConfig = (MetricConfig) yaml.load(inputStream);
} catch (IOException e) {
Assert.fail();
@@ -52,7 +52,8 @@ public class MetricConfigTest {
List<ReporterType> lists = metricConfig.getMetricReporterList();
Assert.assertEquals(lists.size(), 2);
- Assert.assertEquals(metricConfig.getPrometheusReporterConfig().getPrometheusExporterPort(), "9091");
+ Assert.assertEquals(
+ metricConfig.getPrometheusReporterConfig().getPrometheusExporterPort(), "9091");
List<PredefinedMetric> predefinedMetrics = metricConfig.getPredefinedMetrics();
Assert.assertEquals(predefinedMetrics.size(), 1);
}
diff --git a/metrics/interface/src/main/test/resources/iotdb-metric.yml b/metrics/interface/src/test/resources/iotdb-metric.yml
similarity index 92%
rename from metrics/interface/src/main/test/resources/iotdb-metric.yml
rename to metrics/interface/src/test/resources/iotdb-metric.yml
index 44c93ae..4bf2fbe 100644
--- a/metrics/interface/src/main/test/resources/iotdb-metric.yml
+++ b/metrics/interface/src/test/resources/iotdb-metric.yml
@@ -20,7 +20,8 @@
# whether enable the module
enableMetric: true
-# can be multiple reporter, e.g., jmx,prometheus,iotdb
+# can be multiple reporter, e.g., jmx,prometheus,iotdb.
+# iotdb is off by default
metricReporterList:
- jmx
- prometheus
diff --git a/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager b/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
index 235ab43..6af7c7a 100644
--- a/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
+++ b/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
@@ -15,4 +15,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-org.apache.iotdb.metrics.micrometer.MicrometerMetricManager
\ No newline at end of file
+org.apache.iotdb.metrics.micrometer.MicrometerMetricManager
diff --git a/server/pom.xml b/server/pom.xml
index 8530d66..df1d03b 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -232,6 +232,11 @@
<artifactId>micrometer-metrics</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.iotdb</groupId>
+ <artifactId>dropwizard-metrics</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
index 48fe306..658cc52 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
@@ -2185,14 +2185,6 @@ public class IoTDBConfig {
this.thriftServerAwaitTimeForStopService = thriftServerAwaitTimeForStopService;
}
- public int getQueryCacheSizeInMetric() {
- return queryCacheSizeInMetric;
- }
-
- public void setQueryCacheSizeInMetric(int queryCacheSizeInMetric) {
- this.queryCacheSizeInMetric = queryCacheSizeInMetric;
- }
-
public boolean isEnableMQTTService() {
return enableMQTTService;
}
diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/DropwizardIoTDBReporter.java b/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/DropwizardIoTDBReporter.java
new file mode 100644
index 0000000..e35d033
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/DropwizardIoTDBReporter.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.iotdb.db.metrics.dropwizard.reporter;
+
+import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.Reporter;
+import org.apache.iotdb.metrics.config.MetricConfig;
+import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
+import org.apache.iotdb.metrics.dropwizard.DropwizardMetricManager;
+import org.apache.iotdb.metrics.utils.ReporterType;
+
+import com.codahale.metrics.MetricFilter;
+
+import java.util.concurrent.TimeUnit;
+
+public class DropwizardIoTDBReporter implements Reporter {
+
+ private MetricManager dropwizardMetricManager = null;
+ private IoTDBReporter ioTDBReporter;
+
+ private static final MetricConfig metricConfig =
+ MetricConfigDescriptor.getInstance().getMetricConfig();
+
+ @Override
+ public boolean start() {
+ if (!metricConfig.getEnableMetric()) {
+ return false;
+ }
+ ioTDBReporter =
+ IoTDBReporter.forRegistry(
+ ((DropwizardMetricManager) dropwizardMetricManager).getMetricRegistry())
+ .prefixedWith("dropwizard:")
+ .filter(MetricFilter.ALL)
+ .build();
+ ioTDBReporter.start(metricConfig.getPushPeriodInSecond(), TimeUnit.SECONDS);
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ if (ioTDBReporter == null) {
+ return false;
+ }
+ ioTDBReporter.stop();
+ return true;
+ }
+
+ @Override
+ public ReporterType getReporterType() {
+ return ReporterType.iotdb;
+ }
+
+ @Override
+ public void setMetricManager(MetricManager metricManager) {
+ this.dropwizardMetricManager = metricManager;
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/IoTDBReporter.java b/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/IoTDBReporter.java
new file mode 100644
index 0000000..acb05ae
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/IoTDBReporter.java
@@ -0,0 +1,233 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.iotdb.db.metrics.dropwizard.reporter;
+
+import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.exception.StorageEngineException;
+import org.apache.iotdb.db.exception.metadata.IllegalPathException;
+import org.apache.iotdb.db.exception.metadata.StorageGroupNotSetException;
+import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.metadata.path.PartialPath;
+import org.apache.iotdb.db.metrics.metricsUtils;
+import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
+import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.db.service.basic.ServiceProvider;
+import org.apache.iotdb.db.utils.DataTypeUtils;
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricFilter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.ScheduledReporter;
+import com.codahale.metrics.Snapshot;
+import com.codahale.metrics.Timer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class IoTDBReporter extends ScheduledReporter {
+
+ private static final TimeUnit DURATION_UNIT = TimeUnit.MILLISECONDS;
+ private static final TimeUnit RATE_UNIT = TimeUnit.SECONDS;
+ private final String prefix;
+ private static final Logger LOGGER = LoggerFactory.getLogger(IoTDBReporter.class);
+ private final ServiceProvider serviceProvider;
+ private final int rpcPort;
+ private final String address;
+
+ protected IoTDBReporter(
+ MetricRegistry registry,
+ String prefix,
+ MetricFilter filter,
+ ScheduledExecutorService executor,
+ boolean shutdownExecutorOnStop) {
+ super(
+ registry,
+ "iotdb-reporter",
+ filter,
+ RATE_UNIT,
+ DURATION_UNIT,
+ executor,
+ shutdownExecutorOnStop);
+ this.prefix = prefix;
+ IoTDBConfig ioTDBConfig = IoTDBDescriptor.getInstance().getConfig();
+ rpcPort = ioTDBConfig.getRpcPort();
+ address = ioTDBConfig.getRpcAddress();
+ serviceProvider = IoTDB.serviceProvider;
+ }
+
+ public static class Builder {
+ private final MetricRegistry metricRegistry;
+ private String prefix;
+ private MetricFilter metricFilter;
+ private ScheduledExecutorService executorService;
+ private boolean shutdownExecutorOnStop;
+
+ private Builder(MetricRegistry metricRegistry) {
+ this.metricRegistry = metricRegistry;
+ this.prefix = null;
+ this.metricFilter = MetricFilter.ALL;
+ this.executorService = null;
+ this.shutdownExecutorOnStop = true;
+ }
+
+ public Builder shutdownExecutorOnStop(boolean shutdownExecutorOnStop) {
+ this.shutdownExecutorOnStop = shutdownExecutorOnStop;
+ return this;
+ }
+
+ public Builder scheduleOn(ScheduledExecutorService executorService) {
+ this.executorService = executorService;
+ return this;
+ }
+
+ public Builder prefixedWith(String prefix) {
+ this.prefix = prefix;
+ return this;
+ }
+
+ public Builder filter(MetricFilter metricFilter) {
+ this.metricFilter = metricFilter;
+ return this;
+ }
+
+ public IoTDBReporter build() {
+ return new IoTDBReporter(
+ metricRegistry, prefix, metricFilter, executorService, shutdownExecutorOnStop);
+ }
+ }
+
+ @Override
+ public void report(
+ SortedMap<String, Gauge> gauges,
+ SortedMap<String, Counter> counters,
+ SortedMap<String, Histogram> histograms,
+ SortedMap<String, Meter> meters,
+ SortedMap<String, Timer> timers) {
+ for (Map.Entry<String, Gauge> entry : gauges.entrySet()) {
+ sendGauge(entry.getKey(), entry.getValue());
+ }
+ for (Map.Entry<String, Counter> entry : counters.entrySet()) {
+ sendCounter(entry.getKey(), entry.getValue());
+ }
+ for (Map.Entry<String, Histogram> entry : histograms.entrySet()) {
+ sendHistogram(entry.getKey(), entry.getValue());
+ }
+ for (Map.Entry<String, Meter> entry : meters.entrySet()) {
+ sendMeter(entry.getKey(), entry.getValue());
+ }
+ for (Map.Entry<String, Timer> entry : timers.entrySet()) {
+ sendTimer(entry.getKey(), entry.getValue());
+ }
+ }
+
+ private void sendTimer(String name, Timer timer) {
+ writeSnapshotAndCount(
+ prefixed(name), timer.getSnapshot(), timer.getCount(), 1.0D / TimeUnit.SECONDS.toNanos(1L));
+ }
+
+ private void sendMeter(String name, Meter meter) {
+ double value = meter.getCount();
+ updateValue(prefixed(name), metricsUtils.emptyMap(), value);
+ }
+
+ private void sendHistogram(String name, Histogram histogram) {
+ writeSnapshotAndCount(prefixed(name), histogram.getSnapshot(), histogram.getCount(), 1.0);
+ }
+
+ private void sendCounter(String name, Counter counter) {
+ double value = counter.getCount();
+ updateValue(prefixed(name), metricsUtils.emptyMap(), value);
+ }
+
+ private void sendGauge(String name, Gauge gauge) {
+ Object obj = gauge.getValue();
+ double value;
+ if (obj instanceof Number) {
+ value = ((Number) obj).doubleValue();
+ updateValue(prefixed(name), metricsUtils.emptyMap(), value);
+ } else if (obj instanceof Boolean) {
+ value = ((Boolean) obj) ? 1 : 0;
+ updateValue(prefixed(name), metricsUtils.emptyMap(), value);
+ } else {
+ LOGGER.warn("Invalid type for Gauge {}: {}", name, obj.getClass().getName());
+ }
+ }
+
+ private void writeSnapshotAndCount(String name, Snapshot snapshot, long count, double factor) {
+ updateValue(name, metricsUtils.mapOf("quantile", "0.5"), snapshot.getMedian() * factor);
+ updateValue(
+ name, metricsUtils.mapOf("quantile", "0.75"), snapshot.get75thPercentile() * factor);
+ updateValue(
+ name, metricsUtils.mapOf("quantile", "0.95"), snapshot.get95thPercentile() * factor);
+ updateValue(
+ name, metricsUtils.mapOf("quantile", "0.98"), snapshot.get98thPercentile() * factor);
+ updateValue(
+ name, metricsUtils.mapOf("quantile", "0.99"), snapshot.get99thPercentile() * factor);
+ updateValue(
+ name, metricsUtils.mapOf("quantile", "0.999"), snapshot.get999thPercentile() * factor);
+ updateValue(name + "_min", metricsUtils.emptyMap(), snapshot.getMin());
+ updateValue(name + "_max", metricsUtils.emptyMap(), snapshot.getMax());
+ updateValue(name + "_median", metricsUtils.emptyMap(), snapshot.getMedian());
+ updateValue(name + "_mean", metricsUtils.emptyMap(), snapshot.getMean());
+ updateValue(name + "_stddev", metricsUtils.emptyMap(), snapshot.getStdDev());
+ updateValue(name + "_count", metricsUtils.emptyMap(), count);
+ }
+
+ private void updateValue(String name, Map<String, String> labels, double value) {
+ try {
+ InsertRowPlan insertRowPlan =
+ new InsertRowPlan(
+ new PartialPath(metricsUtils.generatePath(address, rpcPort, name, labels)),
+ System.currentTimeMillis(),
+ new String[] {"value"},
+ DataTypeUtils.getValueBuffer(
+ new ArrayList<>(Arrays.asList(TSDataType.DOUBLE)),
+ new ArrayList<>(Arrays.asList(value))),
+ false);
+ serviceProvider.executeNonQuery(insertRowPlan);
+ } catch (IllegalPathException
+ | IoTDBConnectionException
+ | QueryProcessException
+ | StorageGroupNotSetException
+ | StorageEngineException e) {
+ LOGGER.error("illegal insertRowPlan,reason:" + e.getMessage());
+ }
+ }
+
+ private String prefixed(String name) {
+ return prefix == null ? name : (prefix + name);
+ }
+
+ public static Builder forRegistry(MetricRegistry metricRegistry) {
+ return new Builder(metricRegistry);
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/metricsUtils.java b/server/src/main/java/org/apache/iotdb/db/metrics/metricsUtils.java
new file mode 100644
index 0000000..bc5b13a
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/metricsUtils.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.iotdb.db.metrics;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class metricsUtils {
+
+ public static String generatePath(
+ String address, int rpcPort, String name, Map<String, String> labels) {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder
+ .append("root._metric.\"")
+ .append(address)
+ .append(":")
+ .append(rpcPort)
+ .append("\"")
+ .append(".")
+ .append("\"")
+ .append(name)
+ .append("\"");
+ for (Map.Entry<String, String> entry : labels.entrySet()) {
+ stringBuilder
+ .append(".")
+ .append("\"")
+ .append(entry.getKey())
+ .append("=")
+ .append(entry.getValue())
+ .append("\"");
+ }
+ return stringBuilder.toString();
+ }
+
+ public static Map<String, String> emptyMap() {
+ return Collections.emptyMap();
+ }
+
+ public static Map<String, String> mapOf(String key, String value) {
+ HashMap<String, String> result = new HashMap<>();
+ result.put(key, value);
+ return result;
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBMeterRegistry.java b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBMeterRegistry.java
new file mode 100644
index 0000000..fd511cf
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBMeterRegistry.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.iotdb.db.metrics.micrometer.registry;
+
+import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.exception.StorageEngineException;
+import org.apache.iotdb.db.exception.metadata.IllegalPathException;
+import org.apache.iotdb.db.exception.metadata.StorageGroupNotSetException;
+import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.metadata.path.PartialPath;
+import org.apache.iotdb.db.metrics.metricsUtils;
+import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
+import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.db.service.basic.ServiceProvider;
+import org.apache.iotdb.db.utils.DataTypeUtils;
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.distribution.HistogramSnapshot;
+import io.micrometer.core.instrument.step.StepMeterRegistry;
+import io.micrometer.core.instrument.step.StepRegistryConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public class IoTDBMeterRegistry extends StepMeterRegistry {
+ private static final Logger logger = LoggerFactory.getLogger(IoTDBMeterRegistry.class);
+ private final ServiceProvider serviceProvider;
+ private final int rpcPort;
+ private final String address;
+
+ public IoTDBMeterRegistry(StepRegistryConfig config, Clock clock) {
+ super(config, clock);
+ IoTDBConfig ioTDBConfig = IoTDBDescriptor.getInstance().getConfig();
+ rpcPort = ioTDBConfig.getRpcPort();
+ address = ioTDBConfig.getRpcAddress();
+ serviceProvider = IoTDB.serviceProvider;
+ }
+
+ @Override
+ protected void publish() {
+ getMeters()
+ .forEach(
+ meter -> {
+ Meter.Id id = meter.getId();
+ String name = id.getName();
+ List<Tag> tags = id.getTags();
+ Map<String, String> labels = tagsConvertToMap(tags);
+ meter.use(
+ gauge -> {
+ updateValue(name, labels, gauge.value());
+ },
+ counter -> {
+ updateValue(name, labels, counter.count());
+ },
+ timer -> {
+ writeSnapshotAndCount(name, labels, timer.takeSnapshot());
+ },
+ summary -> {
+ writeSnapshotAndCount(name, labels, summary.takeSnapshot());
+ },
+ longTaskTimer -> {
+ updateValue(name, labels, (double) longTaskTimer.activeTasks());
+ },
+ timeGauge -> {
+ updateValue(name, labels, timeGauge.value(getBaseTimeUnit()));
+ },
+ functionCounter -> {
+ updateValue(name, labels, functionCounter.count());
+ },
+ functionTimer -> {
+ updateValue(name, labels, functionTimer.count());
+ },
+ m -> {
+ logger.debug("unknown meter:" + meter);
+ });
+ });
+ }
+
+ private void writeSnapshotAndCount(
+ String name, Map<String, String> labels, HistogramSnapshot snapshot) {
+ updateValue(name + "_max", labels, snapshot.max());
+ updateValue(name + "_mean", labels, snapshot.mean());
+ updateValue(name + "_total", labels, snapshot.total());
+ updateValue(name + "_count", labels, (double) snapshot.count());
+ }
+
+ private Map<String, String> tagsConvertToMap(List<Tag> tags) {
+ Map<String, String> labels = new HashMap<>();
+ for (Tag tag : tags) {
+ labels.put(tag.getKey(), tag.getValue());
+ }
+ return labels;
+ }
+
+ private void updateValue(String name, Map<String, String> labels, Double value) {
+ if (value != null) {
+ try {
+ InsertRowPlan insertRowPlan =
+ new InsertRowPlan(
+ new PartialPath(metricsUtils.generatePath(address, rpcPort, name, labels)),
+ System.currentTimeMillis(),
+ new String[] {"value"},
+ DataTypeUtils.getValueBuffer(
+ new ArrayList<>(Arrays.asList(TSDataType.DOUBLE)),
+ new ArrayList<>(Arrays.asList(value))),
+ false);
+ serviceProvider.executeNonQuery(insertRowPlan);
+ } catch (IllegalPathException
+ | IoTDBConnectionException
+ | QueryProcessException
+ | StorageGroupNotSetException
+ | StorageEngineException e) {
+ logger.error("illegal insertRowPlan,reason:" + e.getMessage());
+ }
+ }
+ }
+
+ @Override
+ protected TimeUnit getBaseTimeUnit() {
+ return TimeUnit.MILLISECONDS;
+ }
+}
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBRegistryConfig.java
similarity index 74%
copy from metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java
copy to server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBRegistryConfig.java
index 06792ba..3546726 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBRegistryConfig.java
@@ -17,17 +17,15 @@
* under the License.
*/
-package org.apache.iotdb.metrics.utils;
+package org.apache.iotdb.db.metrics.micrometer.registry;
-public enum ReporterType {
- // The name of ReporterType should same as value of metricReporterList in iotdb-metric.yml, that's
- // why all below are in lower case.
- jmx,
- prometheus,
- internal;
+import io.micrometer.core.instrument.step.StepRegistryConfig;
+
+public interface IoTDBRegistryConfig extends StepRegistryConfig {
+ IoTDBRegistryConfig DEFAULT = k -> null;
@Override
- public String toString() {
- return name();
+ default String prefix() {
+ return "iotdb";
}
}
diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/reporter/MicrometerIoTDBReporter.java b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/reporter/MicrometerIoTDBReporter.java
new file mode 100644
index 0000000..dc8be1b
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/reporter/MicrometerIoTDBReporter.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.iotdb.db.metrics.micrometer.reporter;
+
+import org.apache.iotdb.db.metrics.micrometer.registry.IoTDBMeterRegistry;
+import org.apache.iotdb.db.metrics.micrometer.registry.IoTDBRegistryConfig;
+import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.Reporter;
+import org.apache.iotdb.metrics.utils.ReporterType;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Metrics;
+import io.micrometer.core.instrument.util.NamedThreadFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class MicrometerIoTDBReporter implements Reporter {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MicrometerIoTDBReporter.class);
+ private MetricManager metricManager;
+
+ @Override
+ public boolean start() {
+ try {
+ Set<MeterRegistry> meterRegistrySet =
+ Metrics.globalRegistry.getRegistries().stream()
+ .filter(reporter -> reporter instanceof IoTDBMeterRegistry)
+ .collect(Collectors.toSet());
+ IoTDBMeterRegistry ioTDBMeterRegistry;
+ if (meterRegistrySet.size() == 0) {
+ ioTDBMeterRegistry = new IoTDBMeterRegistry(IoTDBRegistryConfig.DEFAULT, Clock.SYSTEM);
+ Metrics.addRegistry(ioTDBMeterRegistry);
+ } else {
+ ioTDBMeterRegistry = (IoTDBMeterRegistry) meterRegistrySet.toArray()[0];
+ }
+ ioTDBMeterRegistry.start(new NamedThreadFactory("iotdb-metrics-publisher"));
+ } catch (Exception e) {
+ LOGGER.error("Failed to start Micrometer IoTDBReporter, because {}", e.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ try {
+ Set<MeterRegistry> meterRegistrySet =
+ Metrics.globalRegistry.getRegistries().stream()
+ .filter(reporter -> reporter instanceof IoTDBMeterRegistry)
+ .collect(Collectors.toSet());
+ for (MeterRegistry meterRegistry : meterRegistrySet) {
+ if (!meterRegistry.isClosed()) {
+ meterRegistry.close();
+ Metrics.removeRegistry(meterRegistry);
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.error("Failed to stop Micrometer IoTDBReporter, because {}", e.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public ReporterType getReporterType() {
+ return ReporterType.iotdb;
+ }
+
+ @Override
+ public void setMetricManager(MetricManager metricManager) {
+ this.metricManager = metricManager;
+ }
+}
diff --git a/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager b/server/src/main/resources/META-INF/services/org.apache.iotdb.metrics.Reporter
similarity index 84%
copy from metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
copy to server/src/main/resources/META-INF/services/org.apache.iotdb.metrics.Reporter
index 235ab43..13407ce 100644
--- a/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
+++ b/server/src/main/resources/META-INF/services/org.apache.iotdb.metrics.Reporter
@@ -15,4 +15,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-org.apache.iotdb.metrics.micrometer.MicrometerMetricManager
\ No newline at end of file
+org.apache.iotdb.db.metrics.micrometer.reporter.MicrometerIoTDBReporter
+org.apache.iotdb.db.metrics.dropwizard.reporter.DropwizardIoTDBReporter