diff --git a/bundles/org.openhab.io.metrics/README.md b/bundles/org.openhab.io.metrics/README.md index b73fa1c97..5060d4504 100644 --- a/bundles/org.openhab.io.metrics/README.md +++ b/bundles/org.openhab.io.metrics/README.md @@ -46,7 +46,7 @@ For a start, the following formats are supported: ### Prometheus Once the IO addon is installed, the Prometheus endpoint will be available under: -_:8080/metrics/prometheus_ +_:8080/rest/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`): @@ -55,7 +55,7 @@ scrape_configs: - job_name: 'openhab' scrape_interval: 1m scheme: http - metrics_path: /metrics/prometheus + metrics_path: /rest/metrics/prometheus static_configs: - targets: - 'openhab.local:8080' diff --git a/bundles/org.openhab.io.metrics/pom.xml b/bundles/org.openhab.io.metrics/pom.xml index 2fe752a34..dab282a26 100644 --- a/bundles/org.openhab.io.metrics/pom.xml +++ b/bundles/org.openhab.io.metrics/pom.xml @@ -74,5 +74,11 @@ + + org.openhab.core.bundles + org.openhab.core.io.rest + ${project.version} + provided + diff --git a/bundles/org.openhab.io.metrics/src/main/java/org/openhab/io/metrics/MetricsRestController.java b/bundles/org.openhab.io.metrics/src/main/java/org/openhab/io/metrics/MetricsRestController.java index a4d2253be..b13b73ca4 100644 --- a/bundles/org.openhab.io.metrics/src/main/java/org/openhab/io/metrics/MetricsRestController.java +++ b/bundles/org.openhab.io.metrics/src/main/java/org/openhab/io/metrics/MetricsRestController.java @@ -12,7 +12,10 @@ */ package org.openhab.io.metrics; +import java.util.HashSet; +import java.util.Map; import java.util.Objects; +import java.util.Set; import javax.annotation.security.RolesAllowed; import javax.ws.rs.GET; @@ -23,8 +26,14 @@ 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.config.core.ConfigurableService; +import org.openhab.core.config.core.Configuration; import org.openhab.core.io.monitor.MeterRegistryProvider; +import org.openhab.core.io.rest.RESTConstants; +import org.openhab.io.metrics.exporters.InfluxMetricsExporter; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +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.JSONRequired; @@ -43,24 +52,27 @@ 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. + * 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("") +@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")") +@Path(MetricsRestController.PATH_METRICS) @JSONRequired @RolesAllowed({ Role.USER, Role.ADMIN }) @Tag(name = MetricsRestController.PATH_METRICS) @NonNullByDefault +@ConfigurableService(category = "io", label = "Metrics service", description_uri = "io:metrics") 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); + private final Set metricsExporters = new HashSet<>(); + private @Nullable MetricsConfiguration config; @GET @Path("/prometheus") @@ -79,5 +91,29 @@ public class MetricsRestController { meterRegistry = meterRegistryProvider.getOHMeterRegistry(); Objects.requireNonNull(meterRegistry).add(prometheusMeterRegistry); logger.debug("Core metrics registry retrieved and Prometheus registry added successfully."); + updateMeterRegistry(); + } + + @Activate + protected void activate(Map<@Nullable String, @Nullable Object> configuration) { + logger.info("Metrics service activated, serving the following URL(s): /rest/metrics/prometheus"); + metricsExporters.add(new InfluxMetricsExporter()); + updateConfig(configuration); + updateMeterRegistry(); + } + + @Modified + protected synchronized void modified(Map<@Nullable String, @Nullable Object> configuration) { + updateConfig(configuration); + } + + 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)); } } diff --git a/bundles/org.openhab.io.metrics/src/main/java/org/openhab/io/metrics/MetricsService.java b/bundles/org.openhab.io.metrics/src/main/java/org/openhab/io/metrics/MetricsService.java deleted file mode 100644 index 2c6ea5ffd..000000000 --- a/bundles/org.openhab.io.metrics/src/main/java/org/openhab/io/metrics/MetricsService.java +++ /dev/null @@ -1,117 +0,0 @@ -/** - * 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 restService = null; - private @Nullable MetricsConfiguration config; - @Reference - protected @NonNullByDefault({}) MetricsRestController metrics; - private Set 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 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)); - } -}