public String getDescription() { Long lastUpTime = connectionLastUp.get(); Long lastDownTime = connectionLastDown.get(); Duration serviceFailedStabilizationDelay = getConnectionFailedStabilizationDelay(); Duration serviceRecoveredStabilizationDelay = getConnectionRecoveredStabilizationDelay(); return String.format( "endpoint=%s; connected=%s; timeNow=%s; lastUp=%s; lastDown=%s; lastPublished=%s; " + "currentFailurePeriod=%s; currentRecoveryPeriod=%s", getConfig(ENDPOINT), connected, Time.makeDateString(System.currentTimeMillis()), (lastUpTime != null ? Time.makeDateString(lastUpTime) : "<never>"), (lastDownTime != null ? Time.makeDateString(lastDownTime) : "<never>"), lastPublished, (currentFailureStartTime != null ? getTimeStringSince(currentFailureStartTime) : "<none>") + " (stabilization " + makeTimeStringRounded(serviceFailedStabilizationDelay) + ")", (currentRecoveryStartTime != null ? getTimeStringSince(currentRecoveryStartTime) : "<none>") + " (stabilization " + makeTimeStringRounded(serviceRecoveredStabilizationDelay) + ")"); }
protected String getExplanation(Lifecycle state) { Duration serviceFailedStabilizationDelay = getConfig(ENTITY_FAILED_STABILIZATION_DELAY); Duration serviceRecoveredStabilizationDelay = getConfig(ENTITY_RECOVERED_STABILIZATION_DELAY); return String.format( "location=%s; status=%s; lastPublished=%s; timeNow=%s; " + "currentFailurePeriod=%s; currentRecoveryPeriod=%s", entity.getLocations(), (state != null ? state : "<unreported>"), lastPublished, Time.makeDateString(System.currentTimeMillis()), (currentFailureStartTime != null ? getTimeStringSince(currentFailureStartTime) : "<none>") + " (stabilization " + Time.makeTimeStringRounded(serviceFailedStabilizationDelay) + ")", (currentRecoveryStartTime != null ? getTimeStringSince(currentRecoveryStartTime) : "<none>") + " (stabilization " + Time.makeTimeStringRounded(serviceRecoveredStabilizationDelay) + ")"); }
@Override protected void setActualState(Lifecycle state) { long now = System.currentTimeMillis(); synchronized (mutex) { if (state == Lifecycle.ON_FIRE) { if (lastPublished == LastPublished.FAILED) { if (currentRecoveryStartTime != null) { if (LOG.isDebugEnabled()) LOG.debug( "{} health-check for {}, component was recovering, now failing: {}", new Object[] {this, entity, getExplanation(state)}); currentRecoveryStartTime = null; publishEntityRecoveredTime = null; } else { if (LOG.isTraceEnabled()) LOG.trace( "{} health-check for {}, component still failed: {}", new Object[] {this, entity, getExplanation(state)}); } } else { if (firstUpTime == null && getConfig(ENTITY_FAILED_ONLY_IF_PREVIOUSLY_UP)) { // suppress; won't publish } else if (currentFailureStartTime == null) { if (LOG.isDebugEnabled()) LOG.debug( "{} health-check for {}, component now failing: {}", new Object[] {this, entity, getExplanation(state)}); currentFailureStartTime = now; publishEntityFailedTime = currentFailureStartTime + getConfig(ENTITY_FAILED_STABILIZATION_DELAY).toMilliseconds(); } else { if (LOG.isTraceEnabled()) LOG.trace( "{} health-check for {}, component continuing failing: {}", new Object[] {this, entity, getExplanation(state)}); } } if (setEntityOnFireTime == null) { setEntityOnFireTime = now + getConfig(SERVICE_ON_FIRE_STABILIZATION_DELAY).toMilliseconds(); } currentRecoveryStartTime = null; publishEntityRecoveredTime = null; } else if (state == Lifecycle.RUNNING) { if (lastPublished == LastPublished.FAILED) { if (currentRecoveryStartTime == null) { if (LOG.isDebugEnabled()) LOG.debug( "{} health-check for {}, component now recovering: {}", new Object[] {this, entity, getExplanation(state)}); currentRecoveryStartTime = now; publishEntityRecoveredTime = currentRecoveryStartTime + getConfig(ENTITY_RECOVERED_STABILIZATION_DELAY).toMilliseconds(); } else { if (LOG.isTraceEnabled()) LOG.trace( "{} health-check for {}, component continuing recovering: {}", new Object[] {this, entity, getExplanation(state)}); } } else { if (currentFailureStartTime != null) { if (LOG.isDebugEnabled()) LOG.debug( "{} health-check for {}, component was failing, now healthy: {}", new Object[] {this, entity, getExplanation(state)}); } else { if (LOG.isTraceEnabled()) LOG.trace( "{} health-check for {}, component still healthy: {}", new Object[] {this, entity, getExplanation(state)}); } } currentFailureStartTime = null; publishEntityFailedTime = null; setEntityOnFireTime = null; } else { if (LOG.isTraceEnabled()) LOG.trace( "{} health-check for {}, in unconfirmed sate: {}", new Object[] {this, entity, getExplanation(state)}); } long recomputeIn = Long.MAX_VALUE; // For whether to call recomputeAfterDelay if (publishEntityFailedTime != null) { long delayBeforeCheck = publishEntityFailedTime - now; if (delayBeforeCheck <= 0) { if (LOG.isDebugEnabled()) LOG.debug( "{} publishing failed (state={}; currentFailureStartTime={}; now={}", new Object[] { this, state, Time.makeDateString(currentFailureStartTime), Time.makeDateString(now) }); publishEntityFailedTime = null; lastPublished = LastPublished.FAILED; entity.emit( HASensors.ENTITY_FAILED, new HASensors.FailureDescriptor(entity, getFailureDescription(now))); } else { recomputeIn = Math.min(recomputeIn, delayBeforeCheck); } } else if (publishEntityRecoveredTime != null) { long delayBeforeCheck = publishEntityRecoveredTime - now; if (delayBeforeCheck <= 0) { if (LOG.isDebugEnabled()) LOG.debug( "{} publishing recovered (state={}; currentRecoveryStartTime={}; now={}", new Object[] { this, state, Time.makeDateString(currentRecoveryStartTime), Time.makeDateString(now) }); publishEntityRecoveredTime = null; lastPublished = LastPublished.RECOVERED; entity.emit(HASensors.ENTITY_RECOVERED, new HASensors.FailureDescriptor(entity, null)); } else { recomputeIn = Math.min(recomputeIn, delayBeforeCheck); } } if (setEntityOnFireTime != null) { long delayBeforeCheck = setEntityOnFireTime - now; if (delayBeforeCheck <= 0) { if (LOG.isDebugEnabled()) LOG.debug( "{} setting on-fire, now that deferred period has passed (state={})", new Object[] {this, state}); setEntityOnFireTime = null; super.setActualState(state); } else { recomputeIn = Math.min(recomputeIn, delayBeforeCheck); } } else { super.setActualState(state); } if (recomputeIn < Long.MAX_VALUE) { recomputeAfterDelay(recomputeIn); } } }