mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[io.metrics] initial contribution (#9890)
Signed-off-by: Robert Bach <openhab@mortalsilence.net>
This commit is contained in:
parent
53d168991c
commit
fc81909596
@ -313,6 +313,7 @@
|
|||||||
/bundles/org.openhab.io.homekit/ @beowulfe @yfre
|
/bundles/org.openhab.io.homekit/ @beowulfe @yfre
|
||||||
/bundles/org.openhab.io.hueemulation/ @davidgraeff @digitaldan
|
/bundles/org.openhab.io.hueemulation/ @davidgraeff @digitaldan
|
||||||
/bundles/org.openhab.io.imperihome/ @pdegeus
|
/bundles/org.openhab.io.imperihome/ @pdegeus
|
||||||
|
/bundles/org.openhab.io.metrics/ @pravussum
|
||||||
/bundles/org.openhab.io.neeo/ @tmrobert8
|
/bundles/org.openhab.io.neeo/ @tmrobert8
|
||||||
/bundles/org.openhab.io.openhabcloud/ @kaikreuzer
|
/bundles/org.openhab.io.openhabcloud/ @kaikreuzer
|
||||||
/bundles/org.openhab.persistence.dynamodb/ @ssalonen
|
/bundles/org.openhab.persistence.dynamodb/ @ssalonen
|
||||||
|
@ -1536,6 +1536,11 @@
|
|||||||
<artifactId>org.openhab.io.imperihome</artifactId>
|
<artifactId>org.openhab.io.imperihome</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.io.metrics</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openhab.addons.bundles</groupId>
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
<artifactId>org.openhab.io.neeo</artifactId>
|
<artifactId>org.openhab.io.neeo</artifactId>
|
||||||
|
13
bundles/org.openhab.io.metrics/NOTICE
Normal file
13
bundles/org.openhab.io.metrics/NOTICE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
This content is produced and maintained by the openHAB project.
|
||||||
|
|
||||||
|
* Project home: https://www.openhab.org
|
||||||
|
|
||||||
|
== Declared Project Licenses
|
||||||
|
|
||||||
|
This program and the accompanying materials are made available under the terms
|
||||||
|
of the Eclipse Public License 2.0 which is available at
|
||||||
|
https://www.eclipse.org/legal/epl-2.0/.
|
||||||
|
|
||||||
|
== Source Code
|
||||||
|
|
||||||
|
https://github.com/openhab/openhab-addons
|
99
bundles/org.openhab.io.metrics/README.md
Normal file
99
bundles/org.openhab.io.metrics/README.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# Metrics service
|
||||||
|
|
||||||
|
The metrics service provides
|
||||||
|
|
||||||
|
* an additional REST endpoint to retrieve openHAB core metrics from. This can be used as scrape target for pull-based monitoring systems like [Prometheus](https://prometheus.io/).
|
||||||
|
* optionally configurable services to export openHAB core metrics to push-based monitoring systems like [InfluxDB](https://www.influxdata.com/).
|
||||||
|
|
||||||
|
## Precondition
|
||||||
|
|
||||||
|
The openHAB core metrics must be available (OH version >= 3.1.0 M2 is necessary).
|
||||||
|
|
||||||
|
## Provided metrics
|
||||||
|
|
||||||
|
Currently the following metrics are provided:
|
||||||
|
|
||||||
|
- openHAB events counts (per topic)
|
||||||
|
- openHAB bundle states
|
||||||
|
- openHAB thing states
|
||||||
|
- openHAB rule runs (per rule)
|
||||||
|
- openHAB threadpool stats (per scheduler)
|
||||||
|
- JVM stats including metrics of
|
||||||
|
- class loader
|
||||||
|
- memory
|
||||||
|
- GarbageCollector
|
||||||
|
- OS (system load, CPU)
|
||||||
|
- thread metrics
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The configuration for the metrics service is available in the openHAB UI under Settings | Other Services | Metrics service.
|
||||||
|
Support for pull-based monitoring systems (e. g. Prometheus) is always enabled, since it doesn't imply any significant overhead when not used.
|
||||||
|
Support for push-based monitoring systems (e. g. InfluxDB) have to be enabled separately.
|
||||||
|
|
||||||
|
The following configuration parameters can be set:
|
||||||
|
|
||||||
|
|Config param|Description|Default value|
|
||||||
|
|--|--|--|
|
||||||
|
|influxMetricsEnabled|Enable the Influx (www.influxdata.com) metrics. Further configuration of the InfluxDB instance necessary.|false|
|
||||||
|
|
||||||
|
Refer to the corresponding monitoring system sections for monitoring system specific configuration parameters.
|
||||||
|
|
||||||
|
### Supported monitoring systems
|
||||||
|
|
||||||
|
For a start, the following formats are supported:
|
||||||
|
|
||||||
|
### Prometheus
|
||||||
|
|
||||||
|
Once the IO addon is installed, the Prometheus endpoint will be available under:
|
||||||
|
_<openhab_host>:8080/metrics/prometheus_
|
||||||
|
|
||||||
|
Refer to the [Prometheus](https://prometheus.io/) documentation on how to setup a Prometheus instance and add a scrape configuration. A typical scrape config could look like this (excerpt from `/etc/prometheus/prometheus.yml`):
|
||||||
|
|
||||||
|
````shell
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: 'openhab'
|
||||||
|
scrape_interval: 1m
|
||||||
|
scheme: http
|
||||||
|
metrics_path: /metrics/prometheus
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- 'openhab.local:8080'
|
||||||
|
````
|
||||||
|
|
||||||
|
Replace `openhab.local` by the openhab host.
|
||||||
|
|
||||||
|
#### Available configuration parameters
|
||||||
|
|
||||||
|
There are no Prometheus specific configuration paramters.
|
||||||
|
|
||||||
|
### InfluxDB
|
||||||
|
|
||||||
|
The InfluxDB exporter service will start as soon as the _influxMetricsEnabled_ configuration parameter is set to true.
|
||||||
|
|
||||||
|
#### Available configuration parameters
|
||||||
|
|
||||||
|
|Config param|Description|Default value|
|
||||||
|
|--|--|--|
|
||||||
|
|influxURL|The URL of the InfluxDB instance. Defaults to http://localhost:8086|http://localhost:8086|
|
||||||
|
|influxDB|The name of the database to use. Defaults to "openhab".|openhab|
|
||||||
|
|influxUsername|InfluxDB user name|n/a|
|
||||||
|
|influxPassword|The InfluxDB password (no default).|n/a|
|
||||||
|
|influxUpdateIntervalInSeconds|Controls how often metrics are exported to InfluxDB (in seconds). Defaults to 300|300|
|
||||||
|
|
||||||
|
## Additional metric formats
|
||||||
|
|
||||||
|
The metrics service was implemented using [Micrometer](https://micrometer.io), which supports a number of [monitoring systems](https://micrometer.io/docs)
|
||||||
|
It should be possible to add any of these, especially the ones using a pull mechanism ("scraping") like Prometheus does.
|
||||||
|
|
||||||
|
## Grafana
|
||||||
|
|
||||||
|
You can now visualize the results in Grafana. Micrometer provides a public [Grafana dashboard here](https://grafana.com/grafana/dashboards/4701).
|
||||||
|
I adapted it a little bit to include the openHAB metrics. You can download it here [Dashboard](docs/dashboard.json).
|
||||||
|
This has been tested with Prometheus - for other monitoring systems adaptions to the dashboard might be necessary.
|
||||||
|
|
||||||
|
Here are some screenshots:
|
||||||
|
|
||||||
|
![Grafana (1)](docs/grafana-1.png)
|
||||||
|
![Grafana (2)](docs/grafana-2.png)
|
||||||
|
![Grafana (3)](docs/grafana-3.png)
|
4574
bundles/org.openhab.io.metrics/docs/dashboard.json
Normal file
4574
bundles/org.openhab.io.metrics/docs/dashboard.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
bundles/org.openhab.io.metrics/docs/grafana-1.png
Normal file
BIN
bundles/org.openhab.io.metrics/docs/grafana-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 291 KiB |
BIN
bundles/org.openhab.io.metrics/docs/grafana-2.png
Normal file
BIN
bundles/org.openhab.io.metrics/docs/grafana-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 221 KiB |
BIN
bundles/org.openhab.io.metrics/docs/grafana-3.png
Normal file
BIN
bundles/org.openhab.io.metrics/docs/grafana-3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 133 KiB |
78
bundles/org.openhab.io.metrics/pom.xml
Normal file
78
bundles/org.openhab.io.metrics/pom.xml
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||||
|
<version>3.1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>org.openhab.io.metrics</artifactId>
|
||||||
|
|
||||||
|
<name>openHAB Add-ons :: Bundles :: IO :: Metrics Service</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<micrometer.version>1.6.3</micrometer.version>
|
||||||
|
<bnd.importpackage>io.micrometer.core.*;resolution:=optional;ch.qos.logback.*;resolution:=optional,com.codahale.*;resolution:=optional,com.github.benmanes.caffeine.*;resolution:=optional;com.mongodb.*;resolution:=optional,com.netflix.*;resolution:=optional;com.sun.management.*;resolution:=optional,io.netty.*;resolution:=optional;javax.annotation.meta.*;resolution:=optional,javax.cache.*;resolution:=optional,javax.persistence.*;resolution:=optional,net.sf.ehcache.*;resolution:=optional,okhttp3.*;resolution:=optional,org.apache.catalina.*;resolution:=optional,org.apache.http.*;resolution:=optional,org.apache.kafka.*;resolution:=optional,org.apache.logging.*;resolution:=optional,org.aspectj.*;resolution:=optional,org.hibernate.*;resolution:=optional,org.jooq.*;resolution:=optional,org.reactivestreams.*;resolution:=optional,reactor.*;resolution:=optional,rx.*;resolution:=optional</bnd.importpackage>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.micrometer</groupId>
|
||||||
|
<artifactId>micrometer-core</artifactId>
|
||||||
|
<version>${micrometer.version}</version>
|
||||||
|
<scope>provided</scope><!-- is already included in the openhab.core.io.monitor dependency -->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hdrhistogram</groupId>
|
||||||
|
<artifactId>HdrHistogram</artifactId>
|
||||||
|
<version>2.1.12</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.latencyutils</groupId>
|
||||||
|
<artifactId>LatencyUtils</artifactId>
|
||||||
|
<version>2.0.3</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>HdrHistogram</artifactId>
|
||||||
|
<groupId>org.hdrhistogram</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.micrometer</groupId>
|
||||||
|
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||||
|
<version>${micrometer.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.prometheus</groupId>
|
||||||
|
<artifactId>simpleclient_common</artifactId>
|
||||||
|
<version>0.9.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.prometheus</groupId>
|
||||||
|
<artifactId>simpleclient</artifactId>
|
||||||
|
<version>0.9.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.micrometer</groupId>
|
||||||
|
<artifactId>micrometer-registry-influx</artifactId>
|
||||||
|
<version>${micrometer.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
11
bundles/org.openhab.io.metrics/src/main/feature/feature.xml
Normal file
11
bundles/org.openhab.io.metrics/src/main/feature/feature.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<features name="org.openhab.io.metrics-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||||
|
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||||
|
|
||||||
|
<feature name="openhab-misc-metrics" description="Metrics Service" version="${project.version}">
|
||||||
|
<feature>openhab-runtime-base</feature>
|
||||||
|
<feature>openhab-core-model-item</feature>
|
||||||
|
<feature>openhab-core-base</feature>
|
||||||
|
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.io.metrics/${project.version}</bundle>
|
||||||
|
</feature>
|
||||||
|
</features>
|
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.io.metrics;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link MetricsConfiguration} class holds the configuration for the metrics service
|
||||||
|
*
|
||||||
|
* @author Robert Bach - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class MetricsConfiguration {
|
||||||
|
public boolean influxMetricsEnabled = false;
|
||||||
|
public String influxURL = "http://localhost:8086";
|
||||||
|
public String influxDB = "openhab";
|
||||||
|
public @Nullable String influxPassword = null;
|
||||||
|
public @Nullable String influxUsername = null;
|
||||||
|
public Integer influxUpdateIntervalInSeconds = 300;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "MetricsConfiguration{" + "influxMetricsEnabled=" + influxMetricsEnabled + ", influxURL='" + influxURL
|
||||||
|
+ '\'' + ", influxDB='" + influxDB + '\'' + ", influxPassword='" + influxPassword + '\''
|
||||||
|
+ ", influxUsername='" + influxUsername + '\'' + ", influxUpdateIntervalInSeconds="
|
||||||
|
+ influxUpdateIntervalInSeconds + '}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.io.metrics;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link MetricsExporter} provides the interface for components exporting metrics to push based monitoring systems.
|
||||||
|
*
|
||||||
|
* @author Robert Bach - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public abstract class MetricsExporter {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(MetricsExporter.class);
|
||||||
|
private boolean active = false;
|
||||||
|
protected @Nullable CompositeMeterRegistry meterRegistry = null;
|
||||||
|
protected @Nullable MetricsConfiguration config = null;
|
||||||
|
|
||||||
|
protected abstract void start(CompositeMeterRegistry meterRegistry, MetricsConfiguration metricsConfiguration);
|
||||||
|
|
||||||
|
protected abstract void shutdown();
|
||||||
|
|
||||||
|
protected abstract boolean isEnabled(MetricsConfiguration config);
|
||||||
|
|
||||||
|
public void updateExporterState(@Nullable MetricsConfiguration config) {
|
||||||
|
this.config = config;
|
||||||
|
if (config != null && isEnabled(config) && meterRegistry != null) {
|
||||||
|
if (!active) {
|
||||||
|
logger.debug("Activating exporter {} ", this.getClass().getSimpleName());
|
||||||
|
active = true;
|
||||||
|
start(Objects.requireNonNull(meterRegistry), config);
|
||||||
|
} else {
|
||||||
|
logger.trace("Exporter {} already active.", this.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (active) {
|
||||||
|
logger.debug("Shutting down exporter {} ", this.getClass().getSimpleName());
|
||||||
|
shutdown();
|
||||||
|
active = false;
|
||||||
|
} else {
|
||||||
|
logger.trace("Exporter {} already shut down.", this.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMeterRegistry(@Nullable CompositeMeterRegistry meterRegistry) {
|
||||||
|
this.meterRegistry = meterRegistry;
|
||||||
|
updateExporterState(config);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.io.metrics;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import javax.annotation.security.RolesAllowed;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.core.auth.Role;
|
||||||
|
import org.openhab.core.io.monitor.MeterRegistryProvider;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
|
||||||
|
import io.micrometer.prometheus.PrometheusConfig;
|
||||||
|
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * The {@link MetricsRestController} class implements the REST endpoints for all pull based monitoring systems.
|
||||||
|
*
|
||||||
|
* @author Robert Bach - Initial contribution
|
||||||
|
*/
|
||||||
|
@Component(immediate = true, service = MetricsRestController.class)
|
||||||
|
@JaxrsResource
|
||||||
|
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + MetricsService.METRICS_APP_NAME + ")")
|
||||||
|
@Path("")
|
||||||
|
@JSONRequired
|
||||||
|
@RolesAllowed({ Role.USER, Role.ADMIN })
|
||||||
|
@Tag(name = MetricsRestController.PATH_METRICS)
|
||||||
|
@NonNullByDefault
|
||||||
|
public class MetricsRestController {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(MetricsRestController.class);
|
||||||
|
public static final String PATH_METRICS = "metrics";
|
||||||
|
private @Nullable CompositeMeterRegistry meterRegistry = null;
|
||||||
|
private final PrometheusMeterRegistry prometheusMeterRegistry = new PrometheusMeterRegistry(
|
||||||
|
PrometheusConfig.DEFAULT);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/prometheus")
|
||||||
|
@Produces(MediaType.TEXT_PLAIN)
|
||||||
|
@Operation(operationId = "getPrometheusMetrics", summary = "Gets openHAB system and core metrics in a Prometheus compatible format.", responses = {
|
||||||
|
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = String.class))) })
|
||||||
|
public String getPrometheusMetrics() {
|
||||||
|
return prometheusMeterRegistry.scrape();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Reference
|
||||||
|
public void setMeterRegistryProvider(MeterRegistryProvider meterRegistryProvider) {
|
||||||
|
if (meterRegistry != null) {
|
||||||
|
Objects.requireNonNull(meterRegistry).remove(prometheusMeterRegistry);
|
||||||
|
}
|
||||||
|
meterRegistry = meterRegistryProvider.getOHMeterRegistry();
|
||||||
|
Objects.requireNonNull(meterRegistry).add(prometheusMeterRegistry);
|
||||||
|
logger.debug("Core metrics registry retrieved and Prometheus registry added successfully.");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.io.metrics;
|
||||||
|
|
||||||
|
import java.util.Dictionary;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Application;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.core.config.core.ConfigurableService;
|
||||||
|
import org.openhab.core.config.core.Configuration;
|
||||||
|
import org.openhab.core.io.monitor.MeterRegistryProvider;
|
||||||
|
import org.openhab.io.metrics.exporters.InfluxMetricsExporter;
|
||||||
|
import org.osgi.framework.BundleContext;
|
||||||
|
import org.osgi.framework.FrameworkUtil;
|
||||||
|
import org.osgi.framework.ServiceRegistration;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Deactivate;
|
||||||
|
import org.osgi.service.component.annotations.Modified;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||||
|
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link MetricsService} class implements the central component controlling the different metric endpoints/syncers.
|
||||||
|
*
|
||||||
|
* @author Robert Bach - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(immediate = true, service = MetricsService.class)
|
||||||
|
@ConfigurableService(category = "io", label = "Metrics service", description_uri = "io:metrics")
|
||||||
|
public class MetricsService {
|
||||||
|
public static final String METRICS_APP_NAME = "Metrics";
|
||||||
|
public static final String ROOT = "/metrics";
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(MetricsService.class);
|
||||||
|
private @Nullable ServiceRegistration<Application> restService = null;
|
||||||
|
private @Nullable MetricsConfiguration config;
|
||||||
|
@Reference
|
||||||
|
protected @NonNullByDefault({}) MetricsRestController metrics;
|
||||||
|
private Set<MetricsExporter> metricsExporters = new HashSet<>();
|
||||||
|
private @Nullable CompositeMeterRegistry meterRegistry = null;
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
protected void activate(Map<@Nullable String, @Nullable Object> configuration) {
|
||||||
|
MetricsRestApplication app = new MetricsRestApplication();
|
||||||
|
BundleContext context = FrameworkUtil.getBundle(getClass()).getBundleContext();
|
||||||
|
restService = context.registerService(Application.class, app, getServiceProperties());
|
||||||
|
logger.info("Metrics service available under {}.", ROOT);
|
||||||
|
metricsExporters.add(new InfluxMetricsExporter());
|
||||||
|
updateConfig(configuration);
|
||||||
|
updateMeterRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Modified
|
||||||
|
protected synchronized void modified(Map<@Nullable String, @Nullable Object> configuration) {
|
||||||
|
updateConfig(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deactivate
|
||||||
|
protected void deactivate() {
|
||||||
|
if (restService != null) {
|
||||||
|
Objects.requireNonNull(restService).unregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<@Nullable String, @Nullable String> getServiceProperties() {
|
||||||
|
Dictionary<@Nullable String, @Nullable String> dict = new Hashtable<>();
|
||||||
|
dict.put(JaxrsWhiteboardConstants.JAX_RS_APPLICATION_BASE, ROOT);
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JaxrsName(METRICS_APP_NAME)
|
||||||
|
private class MetricsRestApplication extends Application {
|
||||||
|
@NonNullByDefault({})
|
||||||
|
@Override
|
||||||
|
public Set<Object> getSingletons() {
|
||||||
|
return Set.of(metrics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Reference
|
||||||
|
public void setMeterRegistryProvider(MeterRegistryProvider meterRegistryProvider) {
|
||||||
|
meterRegistry = meterRegistryProvider.getOHMeterRegistry();
|
||||||
|
updateMeterRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateConfig(@Nullable Map<@Nullable String, @Nullable Object> configuration) {
|
||||||
|
this.config = new Configuration(configuration).as(MetricsConfiguration.class);
|
||||||
|
logger.debug("Configuration: {}", this.config);
|
||||||
|
this.metricsExporters.forEach(e -> e.updateExporterState(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateMeterRegistry() {
|
||||||
|
this.metricsExporters.forEach(e -> e.setMeterRegistry(meterRegistry));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.io.metrics.exporters;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.io.metrics.MetricsConfiguration;
|
||||||
|
import org.openhab.io.metrics.MetricsExporter;
|
||||||
|
|
||||||
|
import io.micrometer.core.instrument.Clock;
|
||||||
|
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
|
||||||
|
import io.micrometer.influx.InfluxConfig;
|
||||||
|
import io.micrometer.influx.InfluxMeterRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link InfluxMetricsExporter} class implements a MetricsExporter for InfluxDB
|
||||||
|
*
|
||||||
|
* @author Robert Bach - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class InfluxMetricsExporter extends MetricsExporter {
|
||||||
|
|
||||||
|
private @Nullable InfluxMeterRegistry influxMeterRegistry = null;
|
||||||
|
private @Nullable CompositeMeterRegistry meterRegistry = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(CompositeMeterRegistry meterRegistry, MetricsConfiguration metricsConfiguration) {
|
||||||
|
influxMeterRegistry = new InfluxMeterRegistry(getInfluxConfig(metricsConfiguration), Clock.SYSTEM);
|
||||||
|
meterRegistry.add(influxMeterRegistry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if (influxMeterRegistry != null) {
|
||||||
|
Objects.requireNonNull(influxMeterRegistry).stop();
|
||||||
|
}
|
||||||
|
if (meterRegistry != null) {
|
||||||
|
Objects.requireNonNull(meterRegistry).remove(influxMeterRegistry);
|
||||||
|
meterRegistry = null;
|
||||||
|
}
|
||||||
|
influxMeterRegistry = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private InfluxConfig getInfluxConfig(MetricsConfiguration metricsConfiguration) {
|
||||||
|
return new InfluxConfig() {
|
||||||
|
@Override
|
||||||
|
public Duration step() {
|
||||||
|
return Duration.ofSeconds(metricsConfiguration.influxUpdateIntervalInSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String uri() {
|
||||||
|
return metricsConfiguration.influxURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String db() {
|
||||||
|
return metricsConfiguration.influxDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public String userName() {
|
||||||
|
return metricsConfiguration.influxUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public String password() {
|
||||||
|
return metricsConfiguration.influxPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@io.micrometer.core.lang.Nullable
|
||||||
|
@Nullable
|
||||||
|
public String get(@Nullable String k) {
|
||||||
|
return null; // accept the rest of the defaults
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isEnabled(MetricsConfiguration config) {
|
||||||
|
return config.influxMetricsEnabled;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<config-description:config-descriptions
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
|
||||||
|
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0
|
||||||
|
https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||||
|
<config-description uri="io:metrics">
|
||||||
|
<parameter name="influxMetricsEnabled" type="boolean">
|
||||||
|
<label>Influx Metrics</label>
|
||||||
|
<description>Enable the Influx (www.influxdata.com) Metrics. Further Configuration of the InfluxDB Instance
|
||||||
|
Necessary.</description>
|
||||||
|
<default>false</default>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="influxURL" type="text">
|
||||||
|
<label>InfluxDB URL</label>
|
||||||
|
<description>The URL of the InfluxDB Instance. Defaults to http://localhost:8086</description>
|
||||||
|
<default>http://localhost:8086</default>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="influxDB" type="text">
|
||||||
|
<label>InfluxDB Database Name</label>
|
||||||
|
<description>The Name of the Database to Use. Defaults to "openhab".</description>
|
||||||
|
<default>openhab</default>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="influxUsername" type="text">
|
||||||
|
<label>InfluxDB User Name</label>
|
||||||
|
<description>The InfluxDB User Name (No Default).</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="influxPassword" type="text">
|
||||||
|
<label>InfluxDB Password</label>
|
||||||
|
<description>The InfluxDB Password (No Default).</description>
|
||||||
|
<context>password</context>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="influxUpdateIntervalInSeconds" type="integer" unit="s" min="1">
|
||||||
|
<label>InfluxDB Update Interval in Seconds</label>
|
||||||
|
<description>Controls How Often Metrics Are Exported to InfluxDB (in Seconds). Defaults to 300</description>
|
||||||
|
<default>300</default>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</config-description:config-descriptions>
|
@ -25,6 +25,7 @@
|
|||||||
<module>org.openhab.io.homekit</module>
|
<module>org.openhab.io.homekit</module>
|
||||||
<module>org.openhab.io.hueemulation</module>
|
<module>org.openhab.io.hueemulation</module>
|
||||||
<module>org.openhab.io.imperihome</module>
|
<module>org.openhab.io.imperihome</module>
|
||||||
|
<module>org.openhab.io.metrics</module>
|
||||||
<module>org.openhab.io.neeo</module>
|
<module>org.openhab.io.neeo</module>
|
||||||
<module>org.openhab.io.openhabcloud</module>
|
<module>org.openhab.io.openhabcloud</module>
|
||||||
<!-- transformations -->
|
<!-- transformations -->
|
||||||
|
Loading…
Reference in New Issue
Block a user