private double calcAverageWithinPeriod(VirtualMachineStatisticsChangedEvent event) {

    if (event.getStatistics().isNA()) {
      return -1;
    }

    final String key = event.getVirtualMachine().getUid();
    movingAverageStatistics.addStatistics(key, event.getStatistics().getMemoryHeapUsedPerc());
    double average = movingAverageStatistics.getAverageAndReset(key);

    if (average != -1 && logger.isLoggable(Level.FINE)) {
      logger.fine(
          "vm pid=["
              + event.getVirtualMachine().getDetails().getPid()
              + "] memory used=["
              + event.getStatistics().getMemoryHeapUsedPerc()
              + "%]"
              + " average=["
              + average
              + "%] values: "
              + movingAverageStatistics.toString(key));
    }

    return average;
  }
  @Override
  public void virtualMachineStatisticsChanged(VirtualMachineStatisticsChangedEvent event) {

    int highThreshold = config.getHighThresholdPerc();
    int lowThreshold = config.getLowThresholdPerc();

    double memoryAvg = calcAverageWithinPeriod(event);
    if (memoryAvg < 0) return; // period hasn't passed

    if (memoryAvg > highThreshold) {
      final String groupUid = generateGroupUid(event.getVirtualMachine().getUid());
      AlertFactory factory = new AlertFactory();
      factory.name(ALERT_NAME);
      factory.groupUid(groupUid);
      factory.description(
          AlertBeanUtils.getGridComponentShortName(event.getVirtualMachine())
              + " Heap memory crossed above a "
              + highThreshold
              + "% threshold, for a period of "
              + TimeUtil.format(config.getMeasurementPeriod())
              + ", with an average memory of "
              + NUMBER_FORMAT.format(memoryAvg)
              + "%");
      factory.severity(AlertSeverity.WARNING);
      factory.status(AlertStatus.RAISED);
      factory.componentUid(event.getVirtualMachine().getUid());
      factory.componentDescription(
          AlertBeanUtils.getGridComponentDescription(event.getVirtualMachine()));
      factory.config(config.getProperties());

      factory.putProperty(
          HeapMemoryUtilizationAlert.HOST_ADDRESS,
          event.getVirtualMachine().getMachine().getHostAddress());
      factory.putProperty(
          HeapMemoryUtilizationAlert.HOST_NAME,
          event.getVirtualMachine().getMachine().getHostName());
      factory.putProperty(
          HeapMemoryUtilizationAlert.CPU_UTILIZATION,
          AlertBeanUtils.getCpuPercToString(event.getStatistics().getCpuPerc()));
      factory.putProperty(
          HeapMemoryUtilizationAlert.PROCESS_ID,
          String.valueOf(event.getVirtualMachine().getDetails().getPid()));
      factory.putProperty(
          HeapMemoryUtilizationAlert.COMPONENT_NAME,
          AlertBeanUtils.getGridComponentFullName(event.getVirtualMachine()));
      factory.putProperty(
          HeapMemoryUtilizationAlert.HEAP_UTILIZATION,
          String.valueOf(event.getStatistics().getMemoryHeapUsedPerc()));
      factory.putProperty(
          HeapMemoryUtilizationAlert.MAX_HEAP_IN_BYTES,
          String.valueOf(event.getVirtualMachine().getDetails().getMemoryHeapMaxInBytes()));

      Alert alert = factory.toAlert();
      admin.getAlertManager().triggerAlert(new HeapMemoryUtilizationAlert(alert));

    } else if (memoryAvg < lowThreshold) {
      final String groupUid = generateGroupUid(event.getVirtualMachine().getUid());
      Alert[] alertsByGroupUid =
          ((InternalAlertManager) admin.getAlertManager())
              .getAlertRepository()
              .getAlertsByGroupUid(groupUid);
      if (alertsByGroupUid.length != 0 && !alertsByGroupUid[0].getStatus().isResolved()) {
        AlertFactory factory = new AlertFactory();
        factory.name(ALERT_NAME);
        factory.groupUid(groupUid);
        factory.description(
            AlertBeanUtils.getGridComponentShortName(event.getVirtualMachine())
                + " Heap memory crossed below a "
                + lowThreshold
                + "% threshold, for a period of "
                + getPeriodOfTime(event)
                + ", with an average memory of "
                + NUMBER_FORMAT.format(memoryAvg)
                + "%");
        factory.severity(AlertSeverity.WARNING);
        factory.status(AlertStatus.RESOLVED);
        factory.componentUid(event.getVirtualMachine().getUid());
        factory.componentDescription(
            AlertBeanUtils.getGridComponentDescription(event.getVirtualMachine()));
        factory.config(config.getProperties());

        factory.putProperty(
            HeapMemoryUtilizationAlert.HOST_ADDRESS,
            event.getVirtualMachine().getMachine().getHostAddress());
        factory.putProperty(
            HeapMemoryUtilizationAlert.HOST_NAME,
            event.getVirtualMachine().getMachine().getHostName());
        factory.putProperty(
            HeapMemoryUtilizationAlert.CPU_UTILIZATION,
            AlertBeanUtils.getCpuPercToString(event.getStatistics().getCpuPerc()));
        factory.putProperty(
            HeapMemoryUtilizationAlert.PROCESS_ID,
            String.valueOf(event.getVirtualMachine().getDetails().getPid()));
        factory.putProperty(
            HeapMemoryUtilizationAlert.COMPONENT_NAME,
            AlertBeanUtils.getGridComponentFullName(event.getVirtualMachine()));
        factory.putProperty(
            HeapMemoryUtilizationAlert.HEAP_UTILIZATION,
            String.valueOf(event.getStatistics().getMemoryHeapUsedPerc()));
        factory.putProperty(
            HeapMemoryUtilizationAlert.MAX_HEAP_IN_BYTES,
            String.valueOf(event.getVirtualMachine().getDetails().getMemoryHeapMaxInBytes()));

        Alert alert = factory.toAlert();
        admin.getAlertManager().triggerAlert(new HeapMemoryUtilizationAlert(alert));
      }
    }
  }