This is an automated email from the ASF dual-hosted git repository. andy pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/jena.git
commit e65489642ac3402ef23e7a3c4361d47a489213a4 Author: Andy Seaborne <[email protected]> AuthorDate: Fri Jun 13 09:06:30 2025 +0100 Remove micrometer gauges when data service removed --- .../jena/fuseki/metrics/FusekiRequestsMetrics.java | 28 ++++++++++++++-------- .../org/apache/jena/fuseki/server/DataService.java | 16 +++++++++---- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/FusekiRequestsMetrics.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/FusekiRequestsMetrics.java index f8a8a3dcff..88efb82199 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/FusekiRequestsMetrics.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/metrics/FusekiRequestsMetrics.java @@ -17,7 +17,9 @@ */ package org.apache.jena.fuseki.metrics; +import java.util.HashSet; import java.util.List; +import java.util.Set; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; @@ -35,24 +37,30 @@ public class FusekiRequestsMetrics implements MeterBinder { @Override public void bindTo(MeterRegistry registry) { DataService dataService = dataAccessPoint.getDataService(); + Set<Gauge> gauges = new HashSet<>(); + for (Operation operation : dataService.getOperations()) { List<Endpoint> endpoints = dataService.getEndpoints( operation ); for (Endpoint endpoint : endpoints) { CounterSet counters = endpoint.getCounters(); for (CounterName counterName : counters.counters()) { Counter counter = counters.get( counterName ); - - Gauge.builder( - "fuseki_" + counterName.getFullName(), counter, Counter::value ) - .tags( new String[] { - "dataset", dataAccessPoint.getName(), - "endpoint", endpoint.getName(), - "operation", operation.getName(), - "description", operation.getDescription() - } ) - .register( registry ); + Gauge gauge = + Gauge.builder( + "fuseki_" + counterName.getFullName(), counter, Counter::value ) + .tags( new String[] { + "dataset", dataAccessPoint.getName(), + "endpoint", endpoint.getName(), + "operation", operation.getName(), + "description", operation.getDescription() + } ) + .register( registry ); + gauges.add(gauge); } } } + dataService.addShutdownHandler(dataSrv->{ + gauges.forEach(registry::remove); + }); } } diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java index d6753933b9..f16ad4fe16 100644 --- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java +++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java @@ -58,14 +58,15 @@ public class DataService { * associated with. This is mainly for checking and development. * Usually, one {@code DataService} is associated with one {@link DataAccessPoint}. */ - private List<DataAccessPoint> dataAccessPoints = new ArrayList<>(1); + private List<DataAccessPoint> dataAccessPoints = new ArrayList<>(1); + private List<Consumer<DataService>> shutdownHandlers = new ArrayList<>(5); - private volatile DataServiceStatus state = UNINITIALIZED; + private volatile DataServiceStatus state = UNINITIALIZED; // DataService-level counters. - private final CounterSet counters = new CounterSet(); - private final AtomicBoolean offlineInProgress = new AtomicBoolean(false); - private final AtomicBoolean acceptingRequests = new AtomicBoolean(true); + private final CounterSet counters = new CounterSet(); + private final AtomicBoolean offlineInProgress = new AtomicBoolean(false); + private final AtomicBoolean acceptingRequests = new AtomicBoolean(true); private DispatchFunction plainOperationChooser; @@ -251,10 +252,15 @@ public class DataService { } } + public void addShutdownHandler(Consumer<DataService> action ) { + shutdownHandlers.add(action); + } + /** Shutdown and never use again. */ public synchronized void shutdown() { if ( state == CLOSING ) return; + shutdownHandlers.forEach(action->action.accept(this)); expel(dataset); dataset = null; state = CLOSED;
