Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<sureFireForks11>false</sureFireForks11>
<!--java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory -->
<!--java11.build.outputDirectory>${project.build.directory}/classes-java11</java11.build.outputDirectory -->
<artifact.classifier />
<artifact.classifier/>

<!-- When releasing a new version, this property controls whether the staged artifacts will be automatically
released in Nexus. If this is set to false (-DautoReleaseStagedArtifacts=false), artifacts will need to
Expand Down Expand Up @@ -304,10 +304,9 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<version>3.14.0</version>
<configuration>
<source>11</source>
<target>11</target>
<release>11</release>
<compilerArgs>-Xlint</compilerArgs>
</configuration>
</plugin>
Expand Down Expand Up @@ -577,7 +576,8 @@
com.zaxxer.hikari.metrics,
com.zaxxer.hikari.metrics.dropwizard,
com.zaxxer.hikari.metrics.micrometer,
com.zaxxer.hikari.metrics.prometheus
com.zaxxer.hikari.metrics.prometheus,
com.zaxxer.hikari.metrics.jfr,
</Export-Package>
<Private-Package>com.zaxxer.hikari.*</Private-Package>
<Include-Resource>{maven-resources}</Include-Resource>
Expand All @@ -593,6 +593,7 @@
javax.sql.rowset,
javax.sql.rowset.serial,
javax.sql.rowset.spi,
jdk.jfr,
com.codahale.metrics;resolution:=optional,
com.codahale.metrics.health;resolution:=optional,
io.dropwizard.metrics5;resolution:=optional,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Copyright (C) 2025 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.zaxxer.hikari.metrics.jfr;

import com.zaxxer.hikari.metrics.IMetricsTracker;
import com.zaxxer.hikari.metrics.PoolStats;
import com.zaxxer.hikari.metrics.jfr.events.*;
import jdk.jfr.Event;
import jdk.jfr.FlightRecorder;

import java.util.*;

public class JFREventMetricsTracker implements IMetricsTracker {

private final String poolName;
private final PoolStats poolStats;
private final Map<Class<? extends Event>, Runnable> periodicEvents = new HashMap<>();

JFREventMetricsTracker(final String poolName, final PoolStats poolStats) {
this.poolName = Objects.requireNonNull(poolName, "Missing pool name");
this.poolStats = Objects.requireNonNull(poolStats, "Missing pool stats");
this.periodicEvents.put(ConnectionsActive.class, () -> {
ConnectionsActive event = new ConnectionsActive();
if (event.isEnabled()) {
event.poolName = this.poolName;
event.activeConnections = this.poolStats.getActiveConnections();
event.commit();
}
});
this.periodicEvents.put(ConnectionsIdle.class, () -> {
ConnectionsIdle event = new ConnectionsIdle();
if (event.isEnabled()) {
event.poolName = this.poolName;
event.idleConnections = this.poolStats.getIdleConnections();
event.commit();
}
});
this.periodicEvents.put(ConnectionsMax.class, () -> {
ConnectionsMax event = new ConnectionsMax();
if (event.isEnabled()) {
event.poolName = this.poolName;
event.maxConnections = this.poolStats.getMaxConnections();
event.commit();
}
});
this.periodicEvents.put(ConnectionsMin.class, () -> {
ConnectionsMin event = new ConnectionsMin();
if (event.isEnabled()) {
event.poolName = this.poolName;
event.minConnections = this.poolStats.getMinConnections();
event.commit();
}
});
this.periodicEvents.put(ConnectionsTotal.class, () -> {
ConnectionsTotal event = new ConnectionsTotal();
if (event.isEnabled()) {
event.poolName = this.poolName;
event.totalConnections = this.poolStats.getTotalConnections();
event.commit();
}
});
this.periodicEvents.put(ThreadsPending.class, () -> {
ThreadsPending event = new ThreadsPending();
if (event.isEnabled()) {
event.poolName = this.poolName;
event.threadsPending = this.poolStats.getPendingThreads();
event.commit();
}
});
registerEventClasses(periodicEvents.keySet(), ConnectionAcquired.class, ConnectionCreated.class, ConnectionTimeout.class, ConnectionUsage.class);
addPeriodicEvents(periodicEvents);
}

@SafeVarargs
private static void registerEventClasses(Set<Class<? extends Event>> events, Class<? extends Event> ... additional) {
events.forEach(FlightRecorder::register);
Arrays.stream(additional).forEach(FlightRecorder::register);
}

private static void addPeriodicEvents(Map<Class<? extends Event>, Runnable> periodicEvents) {
periodicEvents.forEach(FlightRecorder::addPeriodicEvent);
}

@Override
public void recordConnectionCreatedMillis(long connectionCreatedMillis) {
ConnectionCreated event = new ConnectionCreated();
if (event.isEnabled()) {
event.poolName = this.poolName;
event.connectionCreatedMillis = connectionCreatedMillis;
event.commit();
}
}

@Override
public void recordConnectionAcquiredNanos(long elapsedAcquiredNanos) {
ConnectionAcquired event = new ConnectionAcquired();
if (event.isEnabled()) {
event.poolName = this.poolName;
event.elapsedAcquiredNanos = elapsedAcquiredNanos;
event.commit();
}
}

@Override
public void recordConnectionUsageMillis(long elapsedBorrowedMillis) {
ConnectionUsage event = new ConnectionUsage();
if (event.isEnabled()) {
event.poolName = this.poolName;
event.elapsedBorrowedMillis = elapsedBorrowedMillis;
event.commit();
}
}

@Override
public void recordConnectionTimeout() {
ConnectionTimeout event = new ConnectionTimeout();
if (event.isEnabled()) {
event.poolName = this.poolName;
event.commit();
}
}

@Override
public void close() {
this.periodicEvents.values().forEach(FlightRecorder::removePeriodicEvent);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2025 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.zaxxer.hikari.metrics.jfr;

import com.zaxxer.hikari.metrics.IMetricsTracker;
import com.zaxxer.hikari.metrics.MetricsTrackerFactory;
import com.zaxxer.hikari.metrics.PoolStats;

public class JFREventMetricsTrackerFactory implements MetricsTrackerFactory {

@Override
public IMetricsTracker create(String poolName, PoolStats poolStats) {
return new JFREventMetricsTracker(poolName, poolStats);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2025 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.zaxxer.hikari.metrics.jfr.events;

import jdk.jfr.*;

@StackTrace(false)
@Category({"HikariCP"})
public class ConnectionAcquired extends Event {

@Label("Pool name")
@Name("pool")
public String poolName;

@Label("Connection acquisition time")
@Name("hikaricp_connection_acquisition_time")
@Timespan(Timespan.NANOSECONDS)
public long elapsedAcquiredNanos;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2025 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.zaxxer.hikari.metrics.jfr.events;

import jdk.jfr.*;

@StackTrace(false)
@Category({"HikariCP"})
public class ConnectionCreated extends Event {

@Label("Pool name")
@Name("pool")
public String poolName;

@Label("Connection creation time")
@Name("hikaricp_connection_creation_time")
@Timespan(Timespan.MILLISECONDS)
public long connectionCreatedMillis;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2025 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.zaxxer.hikari.metrics.jfr.events;

import jdk.jfr.*;

@StackTrace(false)
@Category({"HikariCP"})
public class ConnectionTimeout extends Event {

@Label("Pool name")
@Name("pool")
public String poolName;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2025 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.zaxxer.hikari.metrics.jfr.events;

import jdk.jfr.*;

@StackTrace(false)
@Category({"HikariCP"})
public class ConnectionUsage extends Event {

@Label("Pool name")
@Name("pool")
public String poolName;

@Label("Connection usage time")
@Name("hikaricp_connection_usage_time")
@Timespan(Timespan.MILLISECONDS)
public long elapsedBorrowedMillis;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2025 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.zaxxer.hikari.metrics.jfr.events;

import jdk.jfr.*;

@StackTrace(false)
@Period("1 s")
@Category({"HikariCP"})
public class ConnectionsActive extends Event {

@Label("Pool name")
@Name("pool")
public String poolName;

@Label("Connections active")
@Name("hikaricp_connections_active")
public int activeConnections;

}
Loading