Skip to content

Commit

Permalink
[PLM-Jersey-Monitoring] Adding new metrics: Grizzly, HikariDB
Browse files Browse the repository at this point in the history
  • Loading branch information
wlatif authored and Wail-LT committed Oct 14, 2024
1 parent 543465e commit 3706925
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import javax.sql.DataSource;

import com.coreoz.plume.db.transaction.DataSourceProvider;
import com.coreoz.plume.db.transaction.HikariDataSourceProvider;
import com.google.inject.AbstractModule;

public class DataSourceModule extends AbstractModule {

@Override
protected void configure() {
bind(DataSource.class).toProvider(DataSourceProvider.class);
}
@Override
protected void configure() {
bind(DataSourceProvider.class).to(HikariDataSourceProvider.class);
bind(DataSource.class).toProvider(DataSourceProvider.class);
}

}
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
package com.coreoz.plume.db.transaction;

import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.inject.Singleton;

import javax.sql.DataSource;

/**
* Expose a {@link DataSource} Object through dependency injection.
*/
@Singleton
public class DataSourceProvider implements Provider<DataSource> {

private final DataSource dataSource;

@Inject
public DataSourceProvider(TransactionManager transactionManager) {
this.dataSource = transactionManager.dataSource();
}

@Override
public DataSource get() {
return dataSource;
}

public interface DataSourceProvider extends Provider<DataSource> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.coreoz.plume.db.transaction;

import com.typesafe.config.Config;
import com.zaxxer.hikari.HikariDataSource;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;

/**
* Expose a {@link HikariDataSource} Object through dependency injection.
*/
@Singleton
public class HikariDataSourceProvider implements DataSourceProvider {

private final HikariDataSource dataSource;

@Inject
public HikariDataSourceProvider(Config config) {
this(config, "db");
}

public HikariDataSourceProvider(Config config, String prefix) {
this.dataSource = HikariDataSources.fromConfig(config, prefix + ".hikari");
}

@Override
public HikariDataSource get() {
return dataSource;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
public class HikariDataSources {

public static DataSource fromConfig(Config config, String prefix) {
public static HikariDataSource fromConfig(Config config, String prefix) {
return new HikariDataSource(createHikariConfig(config, prefix));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ public class TransactionManager {

private final DataSource dataSource;

@Inject
@Inject
public TransactionManager(DataSource dataSource) {
this.dataSource = dataSource;
}

public TransactionManager(Config config) {
this(config, "db");
}
Expand All @@ -29,10 +33,6 @@ public TransactionManager(Config config, String prefix) {
this(HikariDataSources.fromConfig(config, prefix + ".hikari"));
}

public TransactionManager(DataSource dataSource) {
this.dataSource = dataSource;
}

// API

public DataSource dataSource() {
Expand Down
18 changes: 18 additions & 0 deletions plume-web-jersey-monitoring/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@
<groupId>com.coreoz</groupId>
<artifactId>plume-web-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.coreoz</groupId>
<artifactId>plume-db</artifactId>
Expand Down Expand Up @@ -84,6 +89,19 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<!-- Tests -->
<dependency>
<groupId>com.coreoz</groupId>
<artifactId>plume-db-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.14.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.coreoz.plume.jersey.monitoring.utils.metrics;

import com.codahale.metrics.Gauge;
import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.MetricSet;
import com.codahale.metrics.jvm.MemoryUsageGaugeSet;
import com.codahale.metrics.jvm.ThreadStatesGaugeSet;
import com.coreoz.plume.jersey.grizzly.GrizzlyThreadPoolProbe;
import com.zaxxer.hikari.HikariDataSource;

import jakarta.inject.Provider;
import java.util.Map;
Expand All @@ -27,6 +30,20 @@ public MetricsCheckBuilder registerJvmMetrics() {
return this;
}

public MetricsCheckBuilder registerGrizzlyMetrics(GrizzlyThreadPoolProbe grizzlyThreadPoolProbe) {
this.metricRegistry.register("http-pool.max-size", (Gauge<Integer>) grizzlyThreadPoolProbe::getPoolMaxSize);
this.metricRegistry.register("http-pool.current-size", (Gauge<Integer>) grizzlyThreadPoolProbe::getTasksWaitingSize);
this.metricRegistry.register("http-pool.waiting-size", (Gauge<Integer>) grizzlyThreadPoolProbe::getTasksWaitingSize);
this.metricRegistry.register("http-pool.usage-size", (Gauge<Integer>) grizzlyThreadPoolProbe::getPoolUsageSize);
this.metricRegistry.register("http-pool.usage", (Gauge<Float>) () -> ((float) grizzlyThreadPoolProbe.getPoolUsageSize()) / ((float)grizzlyThreadPoolProbe.getPoolMaxSize()));
return this;
}

public MetricsCheckBuilder registerHikariMetrics(HikariDataSource hikariDataSource) {
hikariDataSource.setMetricRegistry(this.metricRegistry);
return this;
}

public Provider<Map<String, Metric>> build() {
return this::getMetrics;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
db.hikari."dataSourceClassName"="org.h2.jdbcx.JdbcDataSource"
db.hikari."dataSource.url"="jdbc:h2:mem:test"
db.hikari."dataSource.user"=sa
db.hikari."dataSource.password"=sa
db.hikari.minimumIdle=1
db.hikari.maximumPoolSize=1
13 changes: 13 additions & 0 deletions plume-web-jersey-monitoring/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<root level="INFO">
<appender-ref ref="STDOUT" />
</root>

</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.coreoz.plume.jersey.monitoring.utils.metrics;

import com.codahale.metrics.Gauge;
import com.codahale.metrics.Metric;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.MetricSet;
import com.coreoz.plume.jersey.grizzly.GrizzlyThreadPoolProbe;
import com.zaxxer.hikari.HikariDataSource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Map;

class MetricsCheckBuilderTest {

private MetricsCheckBuilder metricsCheckBuilder;

@BeforeEach
void setUp() {
metricsCheckBuilder = new MetricsCheckBuilder();
}

@Test
void registerMetric_should_registerSingleMetric() {
Metric mockMetric = mock(Metric.class);

metricsCheckBuilder.registerMetric("custom-metric", mockMetric);

Map<String, Metric> registeredMetrics = metricsCheckBuilder.build().get();
assertTrue(registeredMetrics.containsKey("custom-metric"));
assertEquals(mockMetric, registeredMetrics.get("custom-metric"));
}

@Test
void registerMetric_should_registerMetricSet() {
MetricSet mockMetricSet = mock(MetricSet.class);
Map<String, Metric> mockMetrics = Map.of("metric1", mock(Metric.class), "metric2", mock(Metric.class));
when(mockMetricSet.getMetrics()).thenReturn(mockMetrics);

metricsCheckBuilder.registerMetric("custom-metric-set", mockMetricSet);

Map<String, Metric> registeredMetrics = metricsCheckBuilder.build().get();
assertTrue(registeredMetrics.containsKey("custom-metric-set.metric1"));
assertTrue(registeredMetrics.containsKey("custom-metric-set.metric2"));
}

@Test
void registerJvmMetrics_should_registerJvmMetricsCorrectly() {
metricsCheckBuilder.registerJvmMetrics();

Map<String, Metric> registeredMetrics = metricsCheckBuilder.build().get();
assertTrue(registeredMetrics.containsKey("memory-usage.heap.max"));
assertTrue(registeredMetrics.containsKey("thread-states.runnable.count"));
}

@Test
void registerGrizzlyMetrics_should_registerGrizzlyMetricsCorrectly() {
GrizzlyThreadPoolProbe mockProbe = mock(GrizzlyThreadPoolProbe.class);
when(mockProbe.getPoolMaxSize()).thenReturn(100);
when(mockProbe.getTasksWaitingSize()).thenReturn(10);
when(mockProbe.getPoolUsageSize()).thenReturn(50);

metricsCheckBuilder.registerGrizzlyMetrics(mockProbe);

Map<String, Metric> registeredMetrics = metricsCheckBuilder.build().get();
assertTrue(registeredMetrics.containsKey("http-pool.max-size"));
assertTrue(registeredMetrics.containsKey("http-pool.current-size"));
assertTrue(registeredMetrics.containsKey("http-pool.waiting-size"));
assertTrue(registeredMetrics.containsKey("http-pool.usage-size"));
assertTrue(registeredMetrics.containsKey("http-pool.usage"));

Gauge<Integer> maxSizeGauge = (Gauge<Integer>) registeredMetrics.get("http-pool.max-size");
assertEquals(100, maxSizeGauge.getValue());

Gauge<Integer> waitingSizeGauge = (Gauge<Integer>) registeredMetrics.get("http-pool.waiting-size");
assertEquals(10, waitingSizeGauge.getValue());

Gauge<Float> usageGauge = (Gauge<Float>) registeredMetrics.get("http-pool.usage");
assertEquals(0.5f, usageGauge.getValue(), 0.01);
}

@Test
void registerHikariMetrics_should_registerHikariMetricsCorrectly() {
HikariDataSource mockDataSource = mock(HikariDataSource.class);

metricsCheckBuilder.registerHikariMetrics(mockDataSource);

verify(mockDataSource).setMetricRegistry(any(MetricRegistry.class));
}

@Test
void build_should_returnAllRegisteredMetrics() {
Metric mockMetric1 = mock(Metric.class);
Metric mockMetric2 = mock(Metric.class);

metricsCheckBuilder
.registerMetric("metric1", mockMetric1)
.registerMetric("metric2", mockMetric2);

Map<String, Metric> registeredMetrics = metricsCheckBuilder.build().get();
assertEquals(2, registeredMetrics.size());
assertTrue(registeredMetrics.containsKey("metric1"));
assertTrue(registeredMetrics.containsKey("metric2"));
}
}
Loading

0 comments on commit 3706925

Please sign in to comment.