private SafeHtml buildPingBar(final Long ping,
                                  final String msg,
                                  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;

//        GWT.log("ping: " + ping + ", msg '" + msg + "', severityClass: "
//                + severityClass + ", barWidthPct: " + barWidthPct);

        final String text;
        final String title;
        final boolean isErrorMsg;
        if (msg == null) {
            final String pingStr = THOUSANDS_FORMATTER.format(ping);
            text = pingStr;
            title = "Ping: " + pingStr + " ms";
            isErrorMsg = false;
        } else {
            if (msg.startsWith("Unable to connect")
                || msg.startsWith("Error calling node")
                || msg.startsWith("Request failed")) {
                text = "Unable to connect";
            } else {
                text = "Error";
            }
            title = msg;
            isErrorMsg = true;
        }

        final Attribute barWidthAttr = Attribute.style("width:" + barWidthPct + "%");
        final Attribute textClass = Attribute.className(PING_TEXT_CLASS);
        final Attribute errorTextClass = Attribute.className(PING_ERROR_TEXT_CLASS);
        final Attribute barClass = Attribute.className(PING_BAR_CLASS + " " + severityClass);
        final Attribute barWrapperClass = Attribute.className(PING_BAR_CLASS + "-wrapper");
        final Attribute titleAttr = Attribute.title(title);
        final Attribute outerClass = Attribute.className("nodePingBar-outer");

        HtmlBuilder htmlBuilder = new HtmlBuilder();
        if (isErrorMsg) {
            // A text div covering the whole of the cell
            // e.g. ' Unable to connect           '
            htmlBuilder.div(outerBuilder -> outerBuilder
                            .div(text, errorTextClass),
                    outerClass, titleAttr);
        } else {
            // A text div for the ping number
            // A div for the ping bar
            // e.g. '   23 ===================      '
            htmlBuilder.div(outerBuilder -> outerBuilder
                            .div(text, textClass)
                            .div(barWrapperBuilder ->
                                            barWrapperBuilder.div(
                                                    (Consumer<HtmlBuilder>) null, barWidthAttr, barClass),
                                    barWrapperClass),
                    outerClass, titleAttr);
        }
        return htmlBuilder.toSafeHtml();
    }
Add the columns to the table.
stroom-core-client/src/main/java/stroom/node/client/presenter/NodeListPresenter.java