Add JPA statistics support for eclipselink and hibernate (#2202)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-01-20 13:17:55 +02:00
committed by GitHub
parent 357c81fbf4
commit 1f71d6ddb0
10 changed files with 436 additions and 12 deletions

View File

@@ -869,8 +869,7 @@ public class RepositoryApplicationConfiguration {
*/
@Bean
@ConditionalOnMissingBean
// don't active the auto assign scheduler in test, otherwise it is hard to
// test
// don't active the auto assign scheduler in test, otherwise it is hard to test
@Profile("!test")
@ConditionalOnProperty(prefix = "hawkbit.autoassign.scheduler", name = "enabled", matchIfMissing = true)
AutoAssignScheduler autoAssignScheduler(final SystemManagement systemManagement,

View File

@@ -0,0 +1,91 @@
/**
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* 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/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.jpa.utils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.FunctionCounter;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.repository.jpa.Statistics;
import org.springframework.util.ObjectUtils;
/**
* (Experimental) Utility class to get some statistics.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class StatisticsUtils {
private static final ThreadLocal<Map<String, Double>> LAST_COUNTERS = ThreadLocal.withInitial(HashMap::new);
// for test purposes we may want to flush the statistics and to get diff from the last get int THIS thread
public static Map<String, Double> diff() {
final MeterRegistry meterRegistry = Statistics.getInstance().getMeterRegistry();
if (meterRegistry == null) {
// not a bean (i.e. no performance monitoring) is enabled or no meter registry available
return Map.of();
}
final Map<String, Double> last = LAST_COUNTERS.get();
final Map<String, Double> current = counters();
return current.entrySet().stream()
.filter(e -> e.getValue() != 0.0)
.filter(e -> e.getValue().doubleValue() != last.getOrDefault(e.getKey(), 0.0).doubleValue())
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue() - last.getOrDefault(e.getKey(), 0.0)));
}
// gets the jpa related counters
public static Map<String, Double> counters() {
final MeterRegistry meterRegistry = Statistics.getInstance().getMeterRegistry();
if (meterRegistry == null) {
// not a bean (i.e. no performance monitoring) is enabled or no meter registry available
return Map.of();
}
Statistics.flush();
final Map<String, Double> counters = new HashMap<>();
meterRegistry.forEachMeter(m -> {
final Meter.Id id = m.getId();
if (id.getName().startsWith(Statistics.METER_PREFIX)) {
final double value;
if (m instanceof Counter counter) {
value = counter.count();
} else if (m instanceof FunctionCounter functionCounter) {
value = functionCounter.count();
} else {
return;
}
final StringBuilder key = new StringBuilder(id.getName());
final List<Tag> tags = id.getTags();
if (!ObjectUtils.isEmpty(tags)) {
key.append(" [");
tags.forEach(tag -> key.append(tag.getKey()).append('=').append(tag.getValue()).append(", "));
key.setLength(key.length() - 2);
key.append(']');
}
counters.put(key.toString(), value);
}
});
LAST_COUNTERS.set(counters);
return counters;
}
}

View File

@@ -8,28 +8,45 @@
# SPDX-License-Identifier: EPL-2.0
#
# Debug utility functions - START
### Debug & Monitor Eclipselink - START
logging.level.org.eclipse.persistence=ERROR
#incomment to see the debug of persistence, e.g. to see the generated SQLs
## Uncomment to see the debug of persistence, e.g. to see the generated SQLs
#logging.level.org.eclipse.persistence=DEBUG
spring.jpa.properties.eclipselink.logging.level=FINE
spring.jpa.properties.eclipselink.logging.level.sql=FINE
spring.jpa.properties.eclipselink.logging.parameters=true
#spring.jpa.properties.eclipselink.logging.level=FINE
#spring.jpa.properties.eclipselink.logging.level.sql=FINE
#spring.jpa.properties.eclipselink.logging.parameters=true
## Enable EclipseLink performance monitor (monitoring and profile)
#spring.jpa.properties.eclipselink.profiler=PerformanceMonitor
### Debug & Monitor Eclipselink - END
### Debug & Monitor Hibernate - START
## Enable the generated SQLs logging
#logging.level.org.hibernate.SQL=TRACE
#logging.level.org.hibernate.stat=TRACE
## Enable Hibernate statistics
#spring.jpa.properties.hibernate.generate_statistics=true
## Disables info log messages from Hibernate statistics
logging.level.org.hibernate.engine.internal.StatisticalLoggingSessionEventListener=WARN
# Debug & Monitor Hibernate - END
#logging.level.org.springframework.security=TRACE
#logging.level.org.springframework.aop=TRACE
#spring.aop.proxy-target-class=true
#hibernate.generate_statistics=true
#logging.level.org.hibernate.SQL=TRACE
#logging.level.org.hibernate.stat=TRACE
# Debug utility functions - END
### Debug utility functions - END
# Switch to mysql
### Switch to MySQL or MariaDB - START
#spring.jpa.database=MYSQL
#spring.datasource.url=jdbc:mariadb://localhost:3306/hawkbit_test
#spring.datasource.driverClassName=org.mariadb.jdbc.Driver
#spring.datasource.username=root
#spring.datasource.password=
### Switch to MySQL or MariaDB - END
# enable / disable case sensitiveness of the DB when playing around
#hawkbit.rsql.caseInsensitiveDB=true