class FunctionStatsImpl implements FunctionStats {

  @Override
  public void endFunctionExecution(long startTime, boolean haveResult) {
    long elapsedNanos = clock.getAsLong() - startTime;

    successTimer.record(elapsedNanos, NANOSECONDS);

    statistics.incInt(functionExecutionsCompletedId, 1);
    statistics.incInt(functionExecutionsRunningId, -1);

    if (timeStatisticsEnabled.getAsBoolean()) {
      statistics.incLong(functionExecutionsCompletedProcessingTimeId, elapsedNanos);
    }

    if (haveResult) {
      statistics.incInt(functionExecutionsHasResultRunningId, -1);

      if (timeStatisticsEnabled.getAsBoolean()) {
        statistics.incLong(functionExecutionsHasResultCompletedProcessingTimeId, elapsedNanos);
      }
    }

    aggregateStatistics.endFunctionExecutionWithElapsedTime(elapsedNanos, haveResult);
  }

    FunctionStatsImpl(String functionId, MeterRegistry meterRegistry, Statistics statistics,
      FunctionServiceStats functionServiceStats);
  @VisibleForTesting  FunctionStatsImpl(String functionId, MeterRegistry meterRegistry, Statistics statistics,
      FunctionServiceStats aggregateStatistics, long clockResult,
      boolean timeStatisticsEnabledResult);
  @VisibleForTesting  FunctionStatsImpl(String functionId, MeterRegistry meterRegistry, Statistics statistics,
      FunctionServiceStats aggregateStatistics, long clockResult,
      boolean timeStatisticsEnabledResult, Timer successTimerResult, Timer registerFailureResult);
  private  FunctionStatsImpl(String functionId, MeterRegistry meterRegistry, Statistics statistics,
      FunctionServiceStats aggregateStatistics, LongSupplier clock,
      BooleanSupplier timeStatisticsEnabled,
      BiFunction<String, MeterRegistry, Timer> registerSuccessTimerFunction,
      BiFunction<String, MeterRegistry, Timer> registerFailureTimerFunction);

}