@Override
  public void virtualMachineRemoved(VirtualMachine virtualMachine) {

    movingAverageStatistics.clear(virtualMachine.getUid());

    final String groupUid = generateGroupUid(virtualMachine.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(virtualMachine)
              + " Heap memory is unavailable; JVM has been removed");
      factory.severity(AlertSeverity.WARNING);
      factory.status(AlertStatus.NA);
      factory.componentUid(virtualMachine.getUid());
      factory.componentDescription(AlertBeanUtils.getGridComponentDescription(virtualMachine));
      factory.config(config.getProperties());

      Alert alert = factory.toAlert();
      admin.getAlertManager().triggerAlert(new HeapMemoryUtilizationAlert(alert));
    }
  }
  @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));
      }
    }
  }