HHH-17336 - JFR events - Session open, Session close
https://hibernate.atlassian.net/browse/HHH-17336
This commit is contained in:
parent
9d515dd182
commit
9ce2d25041
|
@ -89,6 +89,8 @@ dependencies {
|
||||||
|
|
||||||
testImplementation testLibs.byteman
|
testImplementation testLibs.byteman
|
||||||
|
|
||||||
|
testImplementation testLibs.jfrUnit
|
||||||
|
|
||||||
testRuntimeOnly testLibs.log4j2
|
testRuntimeOnly testLibs.log4j2
|
||||||
testRuntimeOnly libs.byteBuddy
|
testRuntimeOnly libs.byteBuddy
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||||
|
*/
|
||||||
|
package org.hibernate.event.jfr;
|
||||||
|
|
||||||
|
import jdk.jfr.Category;
|
||||||
|
import jdk.jfr.Description;
|
||||||
|
import jdk.jfr.Event;
|
||||||
|
import jdk.jfr.Label;
|
||||||
|
import jdk.jfr.Name;
|
||||||
|
import jdk.jfr.StackTrace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Name(SessionClosedEvent.NAME)
|
||||||
|
@Label("Session Closed")
|
||||||
|
@Category("Hibernate ORM")
|
||||||
|
@Description("Hibernate Session closed")
|
||||||
|
@StackTrace(false)
|
||||||
|
public class SessionClosedEvent extends Event {
|
||||||
|
public static final String NAME = "org.hibernate.orm.SessionClosed";
|
||||||
|
|
||||||
|
@Label("Session Identifier" )
|
||||||
|
public String sessionIdentifier;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return NAME + "(" + sessionIdentifier + ")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||||
|
*/
|
||||||
|
package org.hibernate.event.jfr;
|
||||||
|
|
||||||
|
import jdk.jfr.Category;
|
||||||
|
import jdk.jfr.Description;
|
||||||
|
import jdk.jfr.Event;
|
||||||
|
import jdk.jfr.Label;
|
||||||
|
import jdk.jfr.Name;
|
||||||
|
import jdk.jfr.StackTrace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Name(SessionOpenEvent.NAME)
|
||||||
|
@Label("Session Opened")
|
||||||
|
@Category("Hibernate ORM")
|
||||||
|
@Description("Hibernate Session opened")
|
||||||
|
@StackTrace(false)
|
||||||
|
public class SessionOpenEvent extends Event {
|
||||||
|
public static final String NAME = "org.hibernate.orm.SessionOpened";
|
||||||
|
|
||||||
|
@Label("Session Identifier" )
|
||||||
|
public String sessionIdentifier;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return NAME + "(" + sessionIdentifier + ")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,6 +69,8 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.engine.spi.Status;
|
import org.hibernate.engine.spi.Status;
|
||||||
import org.hibernate.engine.transaction.spi.TransactionImplementor;
|
import org.hibernate.engine.transaction.spi.TransactionImplementor;
|
||||||
import org.hibernate.engine.transaction.spi.TransactionObserver;
|
import org.hibernate.engine.transaction.spi.TransactionObserver;
|
||||||
|
import org.hibernate.event.jfr.SessionClosedEvent;
|
||||||
|
import org.hibernate.event.jfr.SessionOpenEvent;
|
||||||
import org.hibernate.event.spi.AutoFlushEvent;
|
import org.hibernate.event.spi.AutoFlushEvent;
|
||||||
import org.hibernate.event.spi.AutoFlushEventListener;
|
import org.hibernate.event.spi.AutoFlushEventListener;
|
||||||
import org.hibernate.event.spi.ClearEvent;
|
import org.hibernate.event.spi.ClearEvent;
|
||||||
|
@ -228,6 +230,11 @@ public class SessionImpl
|
||||||
public SessionImpl(SessionFactoryImpl factory, SessionCreationOptions options) {
|
public SessionImpl(SessionFactoryImpl factory, SessionCreationOptions options) {
|
||||||
super( factory, options );
|
super( factory, options );
|
||||||
|
|
||||||
|
final SessionOpenEvent sessionOpenEvent = new SessionOpenEvent();
|
||||||
|
if ( sessionOpenEvent.isEnabled() ) {
|
||||||
|
sessionOpenEvent.begin();
|
||||||
|
}
|
||||||
|
|
||||||
persistenceContext = createPersistenceContext();
|
persistenceContext = createPersistenceContext();
|
||||||
actionQueue = createActionQueue();
|
actionQueue = createActionQueue();
|
||||||
|
|
||||||
|
@ -272,6 +279,14 @@ public class SessionImpl
|
||||||
if ( log.isTraceEnabled() ) {
|
if ( log.isTraceEnabled() ) {
|
||||||
log.tracef( "Opened Session [%s] at timestamp: %s", getSessionIdentifier(), currentTimeMillis() );
|
log.tracef( "Opened Session [%s] at timestamp: %s", getSessionIdentifier(), currentTimeMillis() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( sessionOpenEvent.isEnabled() ) {
|
||||||
|
sessionOpenEvent.end();
|
||||||
|
if ( sessionOpenEvent.shouldCommit() ) {
|
||||||
|
sessionOpenEvent.sessionIdentifier = getSessionIdentifier().toString();
|
||||||
|
sessionOpenEvent.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FlushMode getInitialFlushMode() {
|
private FlushMode getInitialFlushMode() {
|
||||||
|
@ -413,6 +428,11 @@ public class SessionImpl
|
||||||
log.tracef( "Closing session [%s]", getSessionIdentifier() );
|
log.tracef( "Closing session [%s]", getSessionIdentifier() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final SessionClosedEvent sessionClosedEvent = new SessionClosedEvent();
|
||||||
|
if ( sessionClosedEvent.isEnabled() ) {
|
||||||
|
sessionClosedEvent.begin();
|
||||||
|
}
|
||||||
|
|
||||||
// todo : we want this check if usage is JPA, but not native Hibernate usage
|
// todo : we want this check if usage is JPA, but not native Hibernate usage
|
||||||
final SessionFactoryImplementor sessionFactory = getSessionFactory();
|
final SessionFactoryImplementor sessionFactory = getSessionFactory();
|
||||||
if ( sessionFactory.getSessionFactoryOptions().isJpaBootstrap() ) {
|
if ( sessionFactory.getSessionFactoryOptions().isJpaBootstrap() ) {
|
||||||
|
@ -435,6 +455,14 @@ public class SessionImpl
|
||||||
if ( statistics.isStatisticsEnabled() ) {
|
if ( statistics.isStatisticsEnabled() ) {
|
||||||
statistics.closeSession();
|
statistics.closeSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( sessionClosedEvent.isEnabled() ) {
|
||||||
|
sessionClosedEvent.end();
|
||||||
|
if ( sessionClosedEvent.shouldCommit() ) {
|
||||||
|
sessionClosedEvent.sessionIdentifier = getSessionIdentifier().toString();
|
||||||
|
sessionClosedEvent.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTransactionInProgressAndNotMarkedForRollback() {
|
private boolean isTransactionInProgressAndNotMarkedForRollback() {
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.event.jfr;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.event.jfr.SessionClosedEvent;
|
||||||
|
import org.hibernate.event.jfr.SessionOpenEvent;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import jdk.jfr.consumer.RecordedEvent;
|
||||||
|
import org.moditect.jfrunit.EnableEvent;
|
||||||
|
import org.moditect.jfrunit.JfrEventTest;
|
||||||
|
import org.moditect.jfrunit.JfrEvents;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@JfrEventTest
|
||||||
|
@DomainModel
|
||||||
|
@SessionFactory
|
||||||
|
public class SessionEventTests {
|
||||||
|
public JfrEvents jfrEvents = new JfrEvents();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableEvent(SessionOpenEvent.NAME)
|
||||||
|
@EnableEvent(SessionClosedEvent.NAME)
|
||||||
|
public void testSessionOpenEvent(SessionFactoryScope scope) {
|
||||||
|
final String openedSessionIdentifier = scope.fromSession( (session) -> {
|
||||||
|
final List<RecordedEvent> events = jfrEvents.events().filter( recordedEvent -> recordedEvent.hasField("sessionIdentifier" ) ).toList();
|
||||||
|
assertThat( events ).hasSize( 1 );
|
||||||
|
final RecordedEvent event = events.get( 0 );
|
||||||
|
assertThat( event.getEventType().getName() ).isEqualTo( SessionOpenEvent.NAME );
|
||||||
|
assertThat( event.getString( "sessionIdentifier" ) ).isEqualTo( session.getSessionIdentifier().toString() );
|
||||||
|
|
||||||
|
jfrEvents.reset();
|
||||||
|
|
||||||
|
return event.getString( "sessionIdentifier" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
final List<RecordedEvent> events = jfrEvents.events().filter( recordedEvent -> recordedEvent.hasField("sessionIdentifier" ) ).toList();
|
||||||
|
assertThat( events ).hasSize( 1 );
|
||||||
|
final RecordedEvent event = events.get( 0 );
|
||||||
|
assertThat( event.getEventType().getName() ).isEqualTo( SessionClosedEvent.NAME );
|
||||||
|
assertThat( event.getString( "sessionIdentifier" ) ).isEqualTo( openedSessionIdentifier );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
/**
|
||||||
|
* Tests for Hibernate's JFR events. Well the events are roduced on Java 11, the JfrUnit
|
||||||
|
* framewqork used in testing only works on JDK 16+.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.event.jfr;
|
|
@ -177,6 +177,8 @@ dependencyResolutionManagement {
|
||||||
def wildFlyTxnClientVersion = version "wildFlyTxnClient", "2.0.0.Final"
|
def wildFlyTxnClientVersion = version "wildFlyTxnClient", "2.0.0.Final"
|
||||||
def xapoolVersion = version "xapool", "1.5.0"
|
def xapoolVersion = version "xapool", "1.5.0"
|
||||||
|
|
||||||
|
def jfrUnitVersion = version "jfrUnit", "1.0.0.Alpha2"
|
||||||
|
|
||||||
library( "junit5Api", "org.junit.jupiter", "junit-jupiter-api" ).versionRef( junit5Version )
|
library( "junit5Api", "org.junit.jupiter", "junit-jupiter-api" ).versionRef( junit5Version )
|
||||||
library( "junit5Engine", "org.junit.jupiter", "junit-jupiter-engine" ).versionRef( junit5Version )
|
library( "junit5Engine", "org.junit.jupiter", "junit-jupiter-engine" ).versionRef( junit5Version )
|
||||||
library( "junit5Params", "org.junit.jupiter", "junit-jupiter-params" ).versionRef( junit5Version )
|
library( "junit5Params", "org.junit.jupiter", "junit-jupiter-params" ).versionRef( junit5Version )
|
||||||
|
@ -206,6 +208,8 @@ dependencyResolutionManagement {
|
||||||
library( "wildFlyTxnClient", "org.wildfly.transaction", "wildfly-transaction-client-jakarta" ).versionRef( wildFlyTxnClientVersion )
|
library( "wildFlyTxnClient", "org.wildfly.transaction", "wildfly-transaction-client-jakarta" ).versionRef( wildFlyTxnClientVersion )
|
||||||
|
|
||||||
library( "weld", "org.jboss.weld.se", "weld-se-shaded" ).versionRef( weldVersion )
|
library( "weld", "org.jboss.weld.se", "weld-se-shaded" ).versionRef( weldVersion )
|
||||||
|
|
||||||
|
library( "jfrUnit", "org.moditect.jfrunit", "jfrunit-core" ).versionRef( jfrUnitVersion )
|
||||||
}
|
}
|
||||||
dbLibs {
|
dbLibs {
|
||||||
def h2Version = version "h2", overrideableVersion( "gradle.libs.versions.h2", "2.2.224" )
|
def h2Version = version "h2", overrideableVersion( "gradle.libs.versions.h2", "2.2.224" )
|
||||||
|
|
Loading…
Reference in New Issue