All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jio.jdbc.JfrEventDecorator Maven / Gradle / Ivy

package jio.jdbc;

import java.util.List;
import jio.ExceptionFun;

import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import jio.IO;
import jio.jdbc.TxExecutedEvent.RESULT;

/**
 * Utility class for decorating operations with Java Flight Recorder (JFR) events.
 */
class JfrEventDecorator {

  private JfrEventDecorator() {
  }

  /**
   * Wraps the provided operation with JFR events if enabled.
   *
   * @param op        The operation to wrap.
   * @param sql       The SQL statement associated with the operation.
   * @param enableJFR Indicates whether to enable JFR events.
   * @param label     The label to identify the statement
   * @return The result of the operation.
   * @throws Exception If an exception occurs during the operation.
   */
  static int decorateUpdateStm(Callable op,
                               String sql,
                               boolean enableJFR,
                               String label)
      throws Exception {
    if (enableJFR) {
      UpdateStmExecutedEvent event = new UpdateStmExecutedEvent();
      event.begin();
      try {
        var n = op.call();
        event.end();
        event.rowsAffected = n;
        event.result = EntitiesFoundEvent.RESULT.SUCCESS.name();
        return n;
      } catch (Exception e) {
        event.end();
        event.sql = sql;
        event.result = EntitiesFoundEvent.RESULT.FAILURE.name();
        event.exception = ExceptionFun.findUltimateCause(e)
                                      .toString();

        throw e;
      } finally {
        if (event.shouldCommit()) {
          event.label = label;
          event.commit();
        }
      }
    } else {
      return op.call();
    }
  }

  /**
   * Wraps the provided operation with JFR events if enabled.
   *
   * @param op        The operation to wrap.
   * @param sql       The SQL statement associated with the operation.
   * @param enableJFR Indicates whether to enable JFR events.
   * @param label     The label to identify the insert statement
   * @return The result of the operation.
   * @throws Exception If an exception occurs during the operation.
   */
  static  O decorateInsertOneStm(Callable op,
                                    String sql,
                                    boolean enableJFR,
                                    String label)
      throws Exception {
    if (enableJFR) {
      UpdateStmExecutedEvent event = new UpdateStmExecutedEvent();
      event.begin();
      try {
        var result = op.call();
        event.end();
        event.rowsAffected = 1;
        event.result = UpdateStmExecutedEvent.RESULT.SUCCESS.name();
        return result;
      } catch (Exception e) {
        event.end();
        event.sql = sql;
        event.result = UpdateStmExecutedEvent.RESULT.FAILURE.name();
        event.exception = ExceptionFun.findUltimateCause(e)
                                      .toString();
        throw e;
      } finally {
        if (event.shouldCommit()) {
          event.label = label;
          event.commit();
        }
      }
    } else {
      return op.call();
    }
  }

  /**
   * Wraps the provided operation with JFR events if enabled.
   *
   * @param        The type of the operation result.
   * @param op        The operation to wrap.
   * @param sql       The SQL statement associated with the operation.
   * @param enableJFR Indicates whether to enable JFR events.
   * @param label     The label to identify the query
   * @param fetchSize the fetchSize used to fetch record from the DB and load them into the ResultSet
   * @return The result of the operation.
   * @throws Exception If an exception occurs during the operation.
   */
  static  List decorateQueryStm(Callable> op,
                                      String sql,
                                      boolean enableJFR,
                                      String label,
                                      int fetchSize)
      throws Exception {
    if (enableJFR) {
      EntitiesFoundEvent event = new EntitiesFoundEvent();
      event.begin();
      try {
        var result = op.call();
        event.end();
        if (event.shouldCommit()) {
          event.label = label;
          event.fetchSize = fetchSize;
          event.result = EntitiesFoundEvent.RESULT.SUCCESS.name();
          event.rowsReturned = result.size();
          event.commit();
        }
        return result;
      } catch (Exception e) {
        event.end();
        if (event.shouldCommit()) {
          event.label = label;
          event.fetchSize = fetchSize;
          event.sql = sql;
          event.result = EntitiesFoundEvent.RESULT.FAILURE.name();
          event.exception = ExceptionFun.findUltimateCause(e)
                                        .toString();
          event.commit();
        }
        throw e;
      }
    } else {
      return op.call();
    }
  }

  /**
   * Wraps the provided operation with JFR events if enabled.
   *
   * @param op        The operation to wrap.
   * @param sql       The SQL statement associated with the operation.
   * @param enableJFR Indicates whether to enable JFR events.
   * @param        The type of the operation result.
   * @param label     The label to identify the statement
   * @return The result of the operation.
   * @throws Exception If an exception occurs during the operation.
   */
  static  O decorateQueryOneStm(Callable op,
                                   String sql,
                                   boolean enableJFR,
                                   String label) throws Exception {
    if (enableJFR) {
      EntitiesFoundEvent event = new EntitiesFoundEvent();
      event.begin();
      try {
        var result = op.call();
        event.end();
        if (event.shouldCommit()) {
          event.label = label;
          event.fetchSize = 1;
          event.result = EntitiesFoundEvent.RESULT.SUCCESS.name();
          event.rowsReturned = result == null ? 0 : 1;
          event.commit();
        }

        return result;
      } catch (Exception e) {
        event.end();
        if (event.shouldCommit()) {
          event.label = label;
          event.fetchSize = 1;
          event.sql = sql;
          event.result = EntitiesFoundEvent.RESULT.FAILURE.name();
          event.exception = ExceptionFun.findUltimateCause(e)
                                        .toString();
          event.commit();
        }
        throw e;
      }
    } else {
      return op.call();
    }
  }


  /**
   * Wraps the provided batch operation with JFR events if enabled.
   *
   * @param op        The batch to wrap.
   * @param sql       The SQL statement associated with the operation.
   * @param enableJFR Indicates whether to enable JFR events.
   * @param label     The label to identify the statement
   * @return The result of the operation.
   * @throws Exception If an exception occurs during the operation.
   */
  static BatchResult decorateBatch(Callable op,
                                   String sql,
                                   boolean enableJFR,
                                   String label)
      throws Exception {
    if (enableJFR) {
      BatchExecutedEvent event = new BatchExecutedEvent();
      event.begin();
      try {
        var result = op.call();
        event.end();
        if (event.shouldCommit()) {
          event.label = label;
          switch (result) {
            case BatchSuccess success -> {
              event.rowsAffected = success.rowsAffected();
              event.result = BatchExecutedEvent.RESULT.SUCCESS.name();
            }
            case BatchPartialSuccess partialSuccess -> {
              event.batchSize = partialSuccess.batchSize();
              event.totalStms = partialSuccess.totalStms();
              event.executedBatches = partialSuccess.executedBatches();
              event.sql = sql;
              event.result = BatchExecutedEvent.RESULT.PARTIAL_SUCCESS.name();
              event.exception = partialSuccess.errors()
                                              .stream()
                                              .map(ExceptionFun::findUltimateCause)
                                              .map(Throwable::toString)
                                              .collect(Collectors.joining());
            }
            case BatchFailure failure -> {
              event.batchSize = failure.batchSize();
              event.totalStms = failure.totalStms();
              event.executedBatches = failure.executedBatches();
              event.sql = sql;
              event.result = BatchExecutedEvent.RESULT.FAILURE.name();
              event.exception = ExceptionFun.findUltimateCause(failure.error())
                                            .toString();
            }
          }

          event.commit();

        }
        return result;

      } catch (Exception e) {
        event.end();
        if (event.shouldCommit()) {
          event.label = label;
          event.sql = sql;
          event.result = BatchExecutedEvent.RESULT.FAILURE.name();
          event.exception = ExceptionFun.findUltimateCause(e)
                                        .toString();
          event.commit();
        }
        throw e;
      }
    } else {
      return op.call();
    }
  }

  static  IO decorateTx(IO tx,
                              String label,
                              boolean enableJFR) {
    if (enableJFR) {
      return IO.lazy(() -> {
                 var event = new TxExecutedEvent();
                 event.begin();
                 return event;
               })
               .then(event ->
                         tx.then(txResult -> {
                                   event.end();
                                   if (event.shouldCommit()) {
                                     event.label = label;
                                     event.result = RESULT.SUCCESS.name();
                                     event.commit();
                                   }
                                   return IO.succeed(txResult);
                                 },
                                 exc -> {
                                   event.end();
                                   if (event.shouldCommit()) {
                                     event.label = label;
                                     event.result = RESULT.FAILURE.name();
                                     event.exception = ExceptionFun.findUltimateCause(exc)
                                                                   .toString();
                                     event.commit();
                                   }
                                   return IO.fail(exc);
                                 }));
    } else {
      return tx;
    }
  }

  static IO decorateTxWithSavePoints(IO tx,
                                               String label,
                                               boolean enableJFR) {
    if (enableJFR) {
      return IO.lazy(() -> {
                 var event = new TxExecutedEvent();
                 event.begin();
                 return event;
               })
               .then(event ->
                         tx.then(txResult -> {
                                   event.end();
                                   if (event.shouldCommit()) {
                                     event.label = label;
                                     if (txResult instanceof TxPartialSuccess partialSuccess) {
                                       event.savePoint = partialSuccess.savePointName();
                                       event.exception = ExceptionFun.findUltimateCause(partialSuccess.cause())
                                                                     .toString();
                                       event.result = RESULT.PARTIAL_SUCCESS.name();

                                     } else {
                                       event.result = RESULT.SUCCESS.name();
                                     }

                                     event.commit();
                                   }
                                   return IO.succeed(txResult);
                                 },
                                 exc -> {
                                   event.end();
                                   if (event.shouldCommit()) {
                                     event.label = label;
                                     event.result = RESULT.SUCCESS.name();
                                     event.exception = ExceptionFun.findUltimateCause(exc)
                                                                   .toString();
                                     event.commit();
                                     ;
                                   }
                                   return IO.fail(exc);
                                 }));
    } else {
      return tx;
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy