From 50aef06db0cbf0b148a4f4b2dfd9740d86927a64 Mon Sep 17 00:00:00 2001 From: anhefti Date: Thu, 13 Jan 2022 13:07:02 +0100 Subject: [PATCH] SEBSERV-250,SEBSERV-188 - implemented overall generic incident marker for client connection handler and removed specific missingPing incident. - adapted missing ping handling to new overall generic incident marker --- .../model/session/ClientConnectionData.java | 5 ++ .../servicelayer/session/ClientIndicator.java | 10 +++ .../impl/ClientConnectionDataInternal.java | 22 ++++++- .../impl/SEBClientConnectionServiceImpl.java | 2 +- .../indicator/AbstractClientIndicator.java | 28 +++++--- .../AbstractLogLevelCountIndicator.java | 19 ++++-- .../impl/indicator/AbstractPingIndicator.java | 12 ++-- .../indicator/BatteryStatusIndicator.java | 5 ++ .../PingIntervalClientIndicator.java | 66 +++++-------------- .../impl/indicator/WLANStatusIndicator.java | 5 ++ .../indicator/IndicatorValueJSONTest.java | 3 +- .../PingIntervalClientIndicatorTest.java | 4 +- 12 files changed, 103 insertions(+), 78 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnectionData.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnectionData.java index d1c1c5f7..3092f078 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnectionData.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientConnectionData.java @@ -73,6 +73,11 @@ public class ClientConnectionData { return this.clientConnection.id; } + @JsonIgnore + public boolean hasAnyIncident() { + return this.missingPing || this.pendingNotification; + } + public ClientConnection getClientConnection() { return this.clientConnection; } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ClientIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ClientIndicator.java index b5a80ee9..5fac4a91 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ClientIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ClientIndicator.java @@ -67,6 +67,16 @@ public interface ClientIndicator extends IndicatorValue { * @param event The ClientEvent instance */ void notifyValueChange(ClientEvent event); + /** This gets called on a value change e.g.: when a ClientEvent was received. + * NOTE: that this is called only on the same machine (server-instance) on that the ClientEvent was received. + * + * @param clientEventRecord The ClientEventRecord instance */ void notifyValueChange(ClientEventRecord clientEventRecord); + /** This indicates if the indicator indicates an incident. This is the case if the actual indicator value + * is above or below the max or min value defined by the indicator threshold settings. + * + * @return true if this indicator indicates an incident */ + boolean hasIncident(); + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ClientConnectionDataInternal.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ClientConnectionDataInternal.java index 894e99cd..ab1b42d2 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ClientConnectionDataInternal.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ClientConnectionDataInternal.java @@ -17,6 +17,7 @@ import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; @@ -74,14 +75,29 @@ public class ClientConnectionDataInternal extends ClientConnectionData { @Override @JsonProperty(ATTR_MISSING_PING) - public Boolean getMissingPing() { - return this.pingIndicator != null && this.pingIndicator.isMissingPing(); + public final Boolean getMissingPing() { + return this.pingIndicator != null && this.pingIndicator.hasIncident(); } @Override @JsonProperty(ATTR_PENDING_NOTIFICATION) - public Boolean pendingNotification() { + public final Boolean pendingNotification() { return this.pendingNotificationIndication.notifictionPending(); } + @Override + @JsonIgnore + public final boolean hasAnyIncident() { + return pendingNotification() || hasIncident(); + } + + private boolean hasIncident() { + return this.indicatorMapping.values() + .stream() + .flatMap(Collection::stream) + .filter(ClientIndicator::hasIncident) + .findFirst() + .isPresent(); + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java index 0b504bd9..97b96f79 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java @@ -847,7 +847,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic return connection -> { if (connection.pingIndicator.missingPingUpdate(now)) { - final boolean missingPing = connection.pingIndicator.isMissingPing(); + final boolean missingPing = connection.getMissingPing(); final ClientEventRecord clientEventRecord = new ClientEventRecord( null, connection.getConnectionId(), diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java index 714540d1..7aff1d9f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java @@ -8,6 +8,8 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator; +import java.util.Comparator; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,8 +23,8 @@ public abstract class AbstractClientIndicator implements ClientIndicator { protected final DistributedIndicatorValueService distributedPingCache; - protected Long indicatorId; - protected Long examId; + protected Long indicatorId = -1L; + protected Long examId = -1L; protected Long connectionId; protected boolean cachingEnabled; protected boolean active = true; @@ -32,6 +34,8 @@ public abstract class AbstractClientIndicator implements ClientIndicator { protected boolean initialized = false; protected double currentValue = Double.NaN; + protected double incidentThreshold = 0.0; + public AbstractClientIndicator(final DistributedIndicatorValueService distributedPingCache) { super(); this.distributedPingCache = distributedPingCache; @@ -44,12 +48,20 @@ public abstract class AbstractClientIndicator implements ClientIndicator { final boolean active, final boolean cachingEnabled) { - this.indicatorId = (indicatorDefinition != null && indicatorDefinition.id != null) - ? indicatorDefinition.id - : -1; - this.examId = (indicatorDefinition != null && indicatorDefinition.examId != null) - ? indicatorDefinition.examId - : -1; + if (indicatorDefinition != null) { + this.incidentThreshold = (!indicatorDefinition.type.inverse) + ? indicatorDefinition.thresholds.stream() + .map(t -> t.value) + .max(Comparator.naturalOrder()) + .orElse(0.0) + : indicatorDefinition.thresholds.stream() + .map(t -> t.value) + .min(Comparator.naturalOrder()) + .orElse(0.0); + this.indicatorId = indicatorDefinition.id; + this.examId = indicatorDefinition.examId; + } + this.connectionId = connectionId; this.active = active; this.cachingEnabled = cachingEnabled; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogLevelCountIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogLevelCountIndicator.java index 25bee3c9..2fcd2eb2 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogLevelCountIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractLogLevelCountIndicator.java @@ -47,13 +47,9 @@ public abstract class AbstractLogLevelCountIndicator extends AbstractLogIndicato valueChanged(clientEventRecord.getText()); } - private void valueChanged(final String eventText) { - if (this.tags == null || this.tags.length == 0 || hasTag(eventText)) { - if (super.ditributedIndicatorValueRecordId != null) { - this.distributedPingCache.incrementIndicatorValue(super.ditributedIndicatorValueRecordId); - } - this.currentValue = getValue() + 1d; - } + @Override + public final boolean hasIncident() { + return this.currentValue > this.incidentThreshold; } @Override @@ -114,4 +110,13 @@ public abstract class AbstractLogLevelCountIndicator extends AbstractLogIndicato return result; } + private void valueChanged(final String eventText) { + if (this.tags == null || this.tags.length == 0 || hasTag(eventText)) { + if (super.ditributedIndicatorValueRecordId != null) { + this.distributedPingCache.incrementIndicatorValue(super.ditributedIndicatorValueRecordId); + } + this.currentValue = getValue() + 1d; + } + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java index f19b2eb5..4987c509 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java @@ -33,6 +33,11 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator { super.init(indicatorDefinition, connectionId, active, cachingEnabled); } + @Override + public Set observedEvents() { + return this.EMPTY_SET; + } + public final void notifyPing(final long timestamp, final int pingNumber) { super.currentValue = timestamp; @@ -49,11 +54,4 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator { } } - @Override - public Set observedEvents() { - return this.EMPTY_SET; - } - - public abstract boolean missingPingUpdate(final long now); - } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/BatteryStatusIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/BatteryStatusIndicator.java index 387efbb8..2187b585 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/BatteryStatusIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/BatteryStatusIndicator.java @@ -48,4 +48,9 @@ public class BatteryStatusIndicator extends AbstractLogNumberIndicator { return IndicatorType.BATTERY_STATUS; } + @Override + public final boolean hasIncident() { + return this.currentValue < this.incidentThreshold; + } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicator.java index 5257ec70..b5cad8ca 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicator.java @@ -8,11 +8,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator; -import java.util.Comparator; - import org.joda.time.DateTimeUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; @@ -32,15 +28,11 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord; @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public final class PingIntervalClientIndicator extends AbstractPingIndicator { - private static final Logger log = LoggerFactory.getLogger(PingIntervalClientIndicator.class); - // This is the default ping error threshold that is set if the threshold cannot be get // from the ping threshold settings. If the last ping is older then this interval back in time // then the ping is considered and marked as missing private static final long DEFAULT_PING_ERROR_THRESHOLD = Constants.SECOND_IN_MILLIS * 5; - private long pingErrorThreshold; - private boolean missingPing = false; private boolean hidden = false; public PingIntervalClientIndicator(final DistributedIndicatorValueService distributedPingCache) { @@ -62,35 +54,11 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator { super.init(indicatorDefinition, connectionId, active, cachingEnabled); - // init ping error threshold - try { + this.lastCheckVal = getValue(); - indicatorDefinition - .getThresholds() - .stream() - .max(Comparator.naturalOrder()) - .ifPresent(t -> this.pingErrorThreshold = t.value.longValue()); - - } catch (final Exception e) { - log.error("Failed to initialize pingErrorThreshold: {}", e.getMessage()); - this.pingErrorThreshold = DEFAULT_PING_ERROR_THRESHOLD; + if (this.incidentThreshold <= 0.0) { + this.incidentThreshold = DEFAULT_PING_ERROR_THRESHOLD; } - - // init missing ping indicator - if (!cachingEnabled) { - try { - this.missingPing = this.pingErrorThreshold < getValue(); - } catch (final Exception e) { - log.error("Failed to initialize missingPing: {}", e.getMessage()); - this.missingPing = true; - } - } - - } - - @JsonIgnore - public final boolean isMissingPing() { - return this.missingPing; } @JsonIgnore @@ -146,25 +114,23 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator { } @Override - public boolean missingPingUpdate(final long now) { + public final boolean hasIncident() { + return getValue() > super.incidentThreshold; + } + + private double lastCheckVal = 0; + + public final boolean missingPingUpdate(final long now) { if (this.currentValue <= 0) { return false; } - final long value = now - (long) super.currentValue; - if (this.missingPing) { - if (this.pingErrorThreshold > value) { - this.missingPing = false; - return true; - } - } else { - if (this.pingErrorThreshold < value) { - this.missingPing = true; - return true; - } - } - - return false; + final double val = now - this.currentValue; + // check if incidentThreshold was passed (up or down) since last update + final boolean result = (this.lastCheckVal < this.incidentThreshold && val >= this.incidentThreshold) || + (this.lastCheckVal >= this.incidentThreshold && val < this.incidentThreshold); + this.lastCheckVal = val; + return result; } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/WLANStatusIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/WLANStatusIndicator.java index 87905dfa..21ba28f0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/WLANStatusIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/WLANStatusIndicator.java @@ -48,4 +48,9 @@ public class WLANStatusIndicator extends AbstractLogNumberIndicator { return IndicatorType.WLAN_STATUS; } + @Override + public final boolean hasIncident() { + return this.currentValue < this.incidentThreshold; + } + } diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/IndicatorValueJSONTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/IndicatorValueJSONTest.java index 0bb13638..f0c0291d 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/IndicatorValueJSONTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/IndicatorValueJSONTest.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import ch.ethz.seb.sebserver.gbl.api.JSONMapper; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; public class IndicatorValueJSONTest { @@ -25,7 +26,7 @@ public class IndicatorValueJSONTest { final JSONMapper jsonMapper = new JSONMapper(); final DistributedIndicatorValueService mock = Mockito.mock(DistributedIndicatorValueService.class); final ErrorLogCountClientIndicator indicator = new ErrorLogCountClientIndicator(mock, null); - indicator.init(new Indicator(1L, null, null, null, null, null, null, null), 2L, true, true); + indicator.init(new Indicator(1L, 2L, "test", IndicatorType.NONE, null, null, null, null), 2L, true, true); final String json = jsonMapper.writeValueAsString(indicator); assertEquals("{\"id\":1,\"val\":\"NaN\"}", json); } diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicatorTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicatorTest.java index 5b66af36..5c0c9542 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicatorTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/PingIntervalClientIndicatorTest.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import ch.ethz.seb.sebserver.gbl.api.JSONMapper; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; +import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; public class PingIntervalClientIndicatorTest { @@ -68,7 +69,8 @@ public class PingIntervalClientIndicatorTest { final PingIntervalClientIndicator pingIntervalClientIndicator = new PingIntervalClientIndicator(distributedPingCache); - pingIntervalClientIndicator.init(new Indicator(2L, null, null, null, null, null, null, null), 1L, true, true); + pingIntervalClientIndicator.init(new Indicator(2L, 3L, "test", IndicatorType.NONE, null, null, null, null), 1L, + true, true); final JSONMapper jsonMapper = new JSONMapper(); final String json = jsonMapper.writeValueAsString(pingIntervalClientIndicator); assertEquals("{\"id\":2,\"val\":0.0}", json);