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
This commit is contained in:
parent
bad7510a63
commit
50aef06db0
12 changed files with 103 additions and 78 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,11 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator {
|
|||
super.init(indicatorDefinition, connectionId, active, cachingEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<EventType> 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<EventType> observedEvents() {
|
||||
return this.EMPTY_SET;
|
||||
}
|
||||
|
||||
public abstract boolean missingPingUpdate(final long now);
|
||||
|
||||
}
|
||||
|
|
|
@ -48,4 +48,9 @@ public class BatteryStatusIndicator extends AbstractLogNumberIndicator {
|
|||
return IndicatorType.BATTERY_STATUS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasIncident() {
|
||||
return this.currentValue < this.incidentThreshold;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,4 +48,9 @@ public class WLANStatusIndicator extends AbstractLogNumberIndicator {
|
|||
return IndicatorType.WLAN_STATUS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasIncident() {
|
||||
return this.currentValue < this.incidentThreshold;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue