Skip to content

Commit

Permalink
gh-3649 Change ping bars to consistent scale + now 3 colours
Browse files Browse the repository at this point in the history
  • Loading branch information
at055612 committed Aug 1, 2023
1 parent 48c8982 commit b812de6
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 68 deletions.
21 changes: 17 additions & 4 deletions stroom-app/src/main/resources/ui/css/components.css
Original file line number Diff line number Diff line change
Expand Up @@ -1734,12 +1734,25 @@ button.main-menu svg {
height: 100%;
}

.nodePingBar-bar__healthy {
background-color: rgba(33, 150, 243, 0.6);
.nodePingBar-bar.nodePingBar-severity__healthy {
background-color: var(--primary);
}

.nodePingBar-bar__unhealthy {
background-color: rgba(255, 111, 0, 0.6);
.nodePingBar-bar.nodePingBar-severity__warn {
background-color: var(--warning);
}

.nodePingBar-bar.nodePingBar-severity__max {
background-color: var(--danger);
}

.nodePingBar-severity__healthy .nodePingBar-text {
color: var(--white);
}

.nodePingBar-severity__warn .nodePingBar-text,
.nodePingBar-severity__max .nodePingBar-text {
color: var(--black);
}

.nodePingBar-text {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,9 @@ appConfig:
helpUrl: "https://gchq.github.io/stroom-docs/7.2/docs"
htmlTitle: "Stroom"
namePattern: "^[a-zA-Z0-9_\\- \\.\\(\\)]{1,}$"
nodeMonitoring:
pingMaxThreshold: 500
pingWarnThreshold: 100
oncontextmenu: "return false;"
process:
defaultRecordLimit: 1000000
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package stroom.node.client.presenter;

import stroom.alert.client.event.AlertEvent;
import stroom.cell.info.client.InfoColumn;
import stroom.cell.tickbox.client.TickBoxCell;
import stroom.cell.tickbox.shared.TickBoxState;
Expand All @@ -38,8 +39,11 @@
import stroom.preferences.client.DateTimeFormatter;
import stroom.svg.client.IconColour;
import stroom.svg.shared.SvgImage;
import stroom.ui.config.client.UiConfigCache;
import stroom.ui.config.shared.NodeMonitoringConfig;
import stroom.util.client.DataGridUtil;
import stroom.util.shared.BuildInfo;
import stroom.util.shared.GwtNullSafe;
import stroom.util.shared.ModelStringUtil;
import stroom.widget.popup.client.presenter.PopupPosition;
import stroom.widget.tooltip.client.presenter.TooltipPresenter;
Expand Down Expand Up @@ -67,11 +71,19 @@ public class NodeMonitoringPresenter extends ContentTabPresenter<PagerView>
implements Refreshable {

private static final NumberFormat THOUSANDS_FORMATTER = NumberFormat.getFormat("#,###");
private static final String CLASS_BASE = "nodePingBar";
private static final String PING_BAR_CLASS = CLASS_BASE + "-bar";
private static final String PING_TEXT_CLASS = CLASS_BASE + "-text";
private static final String PING_SEVERITY_CLASS_BASE = CLASS_BASE + "-severity";
private static final String PING_SEVERITY_CLASS_SUFFIX_HEALTHY = "__healthy";
private static final String PING_SEVERITY_CLASS_SUFFIX_WARN = "__warn";
private static final String PING_SEVERITY_CLASS_SUFFIX_MAX = "__max";

private final MyDataGrid<NodeStatusResult> dataGrid;
private final NodeManager nodeManager;
private final TooltipPresenter tooltipPresenter;
private final DateTimeFormatter dateTimeFormatter;
private final UiConfigCache uiConfigCache;
private final RestDataProvider<NodeStatusResult, FetchNodeStatusResponse> dataProvider;

private final Map<String, PingResult> latestPing = new HashMap<>();
Expand All @@ -82,7 +94,8 @@ public NodeMonitoringPresenter(final EventBus eventBus,
final PagerView view,
final NodeManager nodeManager,
final TooltipPresenter tooltipPresenter,
final DateTimeFormatter dateTimeFormatter) {
final DateTimeFormatter dateTimeFormatter,
final UiConfigCache uiConfigCache) {
super(eventBus, view);

dataGrid = new MyDataGrid<>();
Expand All @@ -91,6 +104,8 @@ public NodeMonitoringPresenter(final EventBus eventBus,
this.nodeManager = nodeManager;
this.tooltipPresenter = tooltipPresenter;
this.dateTimeFormatter = dateTimeFormatter;
this.uiConfigCache = uiConfigCache;

initTableColumns();
dataProvider = new RestDataProvider<NodeStatusResult, FetchNodeStatusResponse>(eventBus) {
@Override
Expand All @@ -102,19 +117,31 @@ protected void exec(final Range range,

@Override
protected void changeData(final FetchNodeStatusResponse data) {
// Ping each node.
data.getValues().forEach(row -> {
final String nodeName = row.getNode().getName();
nodeManager.ping(nodeName,
ping -> {
latestPing.put(nodeName, new PingResult(ping, null));
super.changeData(data);
},
throwable -> {
latestPing.put(nodeName, new PingResult(null, throwable.getMessage()));
super.changeData(data);
uiConfigCache.get()
.onSuccess(uiConfig -> {
final NodeMonitoringConfig nodeMonitoringConfig = uiConfig.getNodeMonitoring();

// Ping each node.
data.getValues().forEach(row -> {
final String nodeName = row.getNode().getName();
nodeManager.ping(nodeName,
pingMs -> {
latestPing.put(nodeName, PingResult.success(pingMs, nodeMonitoringConfig));
super.changeData(data);
},
throwable -> {
latestPing.put(nodeName, PingResult.error(
throwable.getMessage(), nodeMonitoringConfig));
super.changeData(data);
});
});
});
})
.onFailure(caught ->
AlertEvent.fireError(
NodeMonitoringPresenter.this,
caught.getMessage(),
null));

super.changeData(data);
}
};
Expand Down Expand Up @@ -169,52 +196,7 @@ public String getValue(final NodeStatusResult row) {
dataGrid.addResizableColumn(hostNameColumn, "Cluster Base Endpoint URL", 400);

// Ping (ms)
final Column<NodeStatusResult, SafeHtml> safeHtmlColumn = DataGridUtil.safeHtmlColumn(row -> {
if (row == null) {
return null;
}

final PingResult pingResult = latestPing.get(row.getNode().getName());
if (pingResult != null) {
if ("No response".equals(pingResult.getError())) {
return SafeHtmlUtil.getSafeHtml(pingResult.getError());
}
if (pingResult.getError() != null) {
return SafeHtmlUtil.getSafeHtml("Error");
}

// Bar widths are all relative to the longest ping.
final long unHealthyThresholdPing = 250;
final long highestPing = latestPing.values().stream()
.filter(result -> result.getPing() != null)
.mapToLong(PingResult::getPing)
.max()
.orElse(unHealthyThresholdPing);
final int maxBarWidthPct = 100;
final double barWidthPct = pingResult.getPing() > highestPing
? maxBarWidthPct
: ((double) pingResult.getPing() / highestPing * maxBarWidthPct);

final String barColourClass = pingResult.getPing() < unHealthyThresholdPing
? "nodePingBar-bar__healthy"
: "nodePingBar-bar__unhealthy";

HtmlBuilder htmlBuilder = new HtmlBuilder();
htmlBuilder.div(hb1 ->
hb1.div(hb2 ->
hb2.span(hb3 ->
hb3.append(THOUSANDS_FORMATTER
.format(pingResult.getPing())),
Attribute.className("nodePingBar-text")),
Attribute.className("nodePingBar-bar " +
barColourClass),
Attribute.style("width:" +
barWidthPct +
"%")), Attribute.className("nodePingBar-outer"));
return htmlBuilder.toSafeHtml();
}
return SafeHtmlUtil.getSafeHtml("-");
});
final Column<NodeStatusResult, SafeHtml> safeHtmlColumn = DataGridUtil.safeHtmlColumn(this::getPingBarSafeHtml);
dataGrid.addResizableColumn(safeHtmlColumn, "Ping (ms)", 300);

// Master.
Expand Down Expand Up @@ -276,6 +258,64 @@ public TickBoxState getValue(final NodeStatusResult row) {
dataGrid.addEndColumn(new EndColumn<>());
}

private SafeHtml getPingBarSafeHtml(final NodeStatusResult row) {
if (row == null) {
return SafeHtmlUtils.EMPTY_SAFE_HTML;
}

final PingResult pingResult = latestPing.get(row.getNode().getName());

if (pingResult != null) {
if ("No response".equals(pingResult.getError())) {
return SafeHtmlUtil.getSafeHtml(pingResult.getError());
}
if (pingResult.getError() != null) {
return SafeHtmlUtil.getSafeHtml("Error");
}
final Long ping = pingResult.getPing();
if (ping == null || ping < 0) {
return SafeHtmlUtil.getSafeHtml("Invalid ping value: "
+ GwtNullSafe.requireNonNullElse(ping, "null"));
}

return buildPingBar(ping, pingResult.getNodeMonitoringConfig());
}
return SafeHtmlUtil.getSafeHtml("-");
}

private SafeHtml buildPingBar(final long ping, final NodeMonitoringConfig nodeMonitoringConfig) {
final int warnThresholdMs = nodeMonitoringConfig.getPingWarnThreshold();
final int maxThresholdMs = nodeMonitoringConfig.getPingMaxThreshold();
final int maxBarWidthPct = 100;

final double barWidthPct = ping >= maxThresholdMs
? maxBarWidthPct
: ((double) ping / maxThresholdMs * maxBarWidthPct);

final String severityClassSuffix;
if (ping >= maxThresholdMs) {
severityClassSuffix = PING_SEVERITY_CLASS_SUFFIX_MAX;
} else if (ping >= warnThresholdMs) {
severityClassSuffix = PING_SEVERITY_CLASS_SUFFIX_WARN;
} else {
severityClassSuffix = PING_SEVERITY_CLASS_SUFFIX_HEALTHY;
}
final String severityClass = PING_SEVERITY_CLASS_BASE + severityClassSuffix;

HtmlBuilder htmlBuilder = new HtmlBuilder();
htmlBuilder.div(hb1 ->
hb1.div(hb2 ->
hb2.span(hb3 ->
hb3.append(THOUSANDS_FORMATTER
.format(ping)),
Attribute.className(PING_TEXT_CLASS)),
Attribute.className(PING_BAR_CLASS + " " + severityClass),
Attribute.style("width:" +
barWidthPct +
"%")), Attribute.className("nodePingBar-outer"));
return htmlBuilder.toSafeHtml();
}

private void showNodeInfoResult(final Node node, final ClusterNodeInfo result, final PopupPosition popupPosition) {
final TableBuilder tb1 = new TableBuilder();
final TableBuilder tb2 = new TableBuilder();
Expand Down Expand Up @@ -349,14 +389,30 @@ public String getLabel() {
return "Nodes";
}


// --------------------------------------------------------------------------------


private static final class PingResult {

private final Long ping;
private final String error;
private final NodeMonitoringConfig nodeMonitoringConfig;

PingResult(final Long ping, final String error) {
PingResult(final Long ping,
final String error,
final NodeMonitoringConfig nodeMonitoringConfig) {
this.ping = ping;
this.error = error;
this.nodeMonitoringConfig = nodeMonitoringConfig;
}

static PingResult success(final Long ping, final NodeMonitoringConfig nodeMonitoringConfig) {
return new PingResult(ping, null, nodeMonitoringConfig);
}

static PingResult error(final String error, final NodeMonitoringConfig nodeMonitoringConfig) {
return new PingResult(null, error, nodeMonitoringConfig);
}

Long getPing() {
Expand All @@ -366,5 +422,9 @@ Long getPing() {
String getError() {
return error;
}

public NodeMonitoringConfig getNodeMonitoringConfig() {
return nodeMonitoringConfig;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package stroom.ui.config.shared;

import stroom.util.shared.AbstractConfig;
import stroom.util.shared.IsStroomConfig;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

import java.util.Objects;
import javax.validation.constraints.Min;

@JsonPropertyOrder(alphabetic = true)
@JsonInclude(Include.NON_NULL)
public class NodeMonitoringConfig extends AbstractConfig implements IsStroomConfig {

@Min(1)
@JsonProperty
@JsonPropertyDescription("The threshold in milliseconds, above which a node ping response time is " +
"considered to have a severity of warning and the ping bar will be coloured accordingly. " +
"Must be lest then or equal to pingMaxThreshold.")
private final int pingWarnThreshold;

@Min(1)
@JsonProperty
@JsonPropertyDescription("The maximum number of milliseconds that the node monitoring ping bar " +
"can display. Above this value the ping bar will be displayed in a different colour to " +
"indicate it has exceeded the maximum threshold. This value should be greater than or equal " +
"to pingWarnThreshold")
private final int pingMaxThreshold;

public NodeMonitoringConfig() {
pingWarnThreshold = 100;
pingMaxThreshold = 500;
}

@JsonCreator
public NodeMonitoringConfig(@JsonProperty("pingWarnThreshold") final int pingWarnThreshold,
@JsonProperty("pingMaxThreshold") final int pingMaxThreshold) {
this.pingWarnThreshold = pingWarnThreshold;
this.pingMaxThreshold = pingMaxThreshold;
}

public int getPingWarnThreshold() {
return pingWarnThreshold;
}

public int getPingMaxThreshold() {
return pingMaxThreshold;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final NodeMonitoringConfig that = (NodeMonitoringConfig) o;
return pingWarnThreshold == that.pingWarnThreshold && pingMaxThreshold == that.pingMaxThreshold;
}

@Override
public int hashCode() {
return Objects.hash(pingWarnThreshold, pingMaxThreshold);
}

@Override
public String toString() {
return "NodeMonitoringConfig{" +
"pingWarnThreshold=" + pingWarnThreshold +
", pingMaxThreshold=" + pingMaxThreshold +
'}';
}
}
Loading

0 comments on commit b812de6

Please sign in to comment.