// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.clustercontroller.core.status; import com.yahoo.vdslib.distribution.ConfiguredNode; import com.yahoo.vdslib.distribution.Group; import com.yahoo.vdslib.state.Node; import com.yahoo.vdslib.state.NodeType; import com.yahoo.vespa.clustercontroller.core.ClusterStateBundle; import com.yahoo.vespa.clustercontroller.core.ClusterStateHistoryEntry; import com.yahoo.vespa.clustercontroller.core.ContentCluster; import com.yahoo.vespa.clustercontroller.core.EventLog; import com.yahoo.vespa.clustercontroller.core.FleetControllerOptions; import com.yahoo.vespa.clustercontroller.core.LeafGroups; import com.yahoo.vespa.clustercontroller.core.MasterElectionHandler; import com.yahoo.vespa.clustercontroller.core.NodeInfo; import com.yahoo.vespa.clustercontroller.core.RealTimer; import com.yahoo.vespa.clustercontroller.core.StateVersionTracker; import com.yahoo.vespa.clustercontroller.core.Timer; import com.yahoo.vespa.clustercontroller.core.status.statuspage.HtmlTable; import com.yahoo.vespa.clustercontroller.core.status.statuspage.StatusPageResponse; import com.yahoo.vespa.clustercontroller.core.status.statuspage.StatusPageServer; import com.yahoo.vespa.clustercontroller.core.status.statuspage.VdsClusterHtmlRenderer; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.TreeMap; import java.util.stream.Collectors; /** * @author Haakon Humberset */ public class LegacyIndexPageRequestHandler implements StatusPageServer.RequestHandler { private static final DecimalFormat DecimalDot2 = new DecimalFormat("0.00", new DecimalFormatSymbols(Locale.ENGLISH)); private final Timer timer; private final ContentCluster cluster; private final MasterElectionHandler masterElectionHandler; private final StateVersionTracker stateVersionTracker; private final EventLog eventLog; private final long startedTime; private FleetControllerOptions options; public LegacyIndexPageRequestHandler(Timer timer, ContentCluster cluster, MasterElectionHandler masterElectionHandler, StateVersionTracker stateVersionTracker, EventLog eventLog, FleetControllerOptions options) { this.timer = timer; this.cluster = cluster; this.masterElectionHandler = masterElectionHandler; this.stateVersionTracker = stateVersionTracker; this.eventLog = eventLog; this.startedTime = timer.getCurrentTimeInMillis(); this.options = options; } public void propagateOptions(FleetControllerOptions options) { this.options = options; } @Override public StatusPageResponse handle(StatusPageServer.HttpRequest request) { TimeZone tz = TimeZone.getTimeZone("UTC"); long currentTime = timer.getCurrentTimeInMillis(); StatusPageResponse response = new StatusPageResponse(); response.setContentType("text/html"); StringBuilder content = new StringBuilder(); content.append("\n"); response.writeHtmlHeader(content, cluster.getName() + " Cluster Controller " + options.fleetControllerIndex() + " Status Page"); content.append("
") .append(" [ Current config") .append(" | Cluster states") .append(" | Event log") .append(" ]
\n"); content.append("UTC time when creating this page: | ").append(RealTimer.printDateNoMilliSeconds(currentTime, tz)).append(" |
Cluster controller uptime: | " + RealTimer.printDuration(currentTime - startedTime) + " |
Creation date (").append(tz.getDisplayName(false, TimeZone.SHORT)).append(") | \n") .append("Bucket space | \n") .append("Cluster state | \n") .append("
---|
Baseline cluster state:").append(clusterStates.getBaselineClusterState().toString()).append("
" + bucketSpace + " cluster state:").append(state.getClusterState().toString()).append("
Summary: %s
\n", HtmlTable.escape(state.getFeedBlockOrNull().getDescription()))); } ListProperty | Value |
---|---|
").append(options.clusterName()).append(" | |
").append(options.fleetControllerIndex()).append("/").append(options.fleetControllerCount()).append(" | |
").append(slobrokspecs).append(" | |
").append(options.rpcPort() == 0 ? "Pick random available" : options.rpcPort()).append(" | |
").append(options.httpPort() == 0 ? "Pick random available" : options.httpPort()).append(" | |
").append(RealTimer.printDuration(options.masterZooKeeperCooldownPeriod())).append(" | |
").append(zooKeeperAddress).append(" | |
").append(RealTimer.printDuration(options.zooKeeperSessionTimeout())).append(" | |
").append(options.cycleWaitTime()).append(" ms | |
").append(RealTimer.printDuration(options.minTimeBeforeFirstSystemStateBroadcast())).append(" | |
").append(RealTimer.printDuration(options.minTimeBetweenNewSystemStates())).append(" | |
").append(RealTimer.printDuration(options.nodeStateRequestTimeoutMS())).append(" | |
").append(RealTimer.printDuration(options.maxTransitionTime().get(NodeType.DISTRIBUTOR))).append(" | |
").append(RealTimer.printDuration(options.maxTransitionTime().get(NodeType.STORAGE))).append(" | |
").append(RealTimer.printDuration(options.maxInitProgressTime())).append(" | |
").append(options.maxPrematureCrashes()).append(" | |
").append(RealTimer.printDuration(options.stableStateTimePeriod())).append(" | |
").append(RealTimer.printDuration(options.maxSlobrokDisconnectGracePeriod())).append(" | |
").append(options.nodes() == null ? "Autodetect" : options.nodes().size()).append(" | |
").append(options.nodes() == null ? "Autodetect" : options.nodes().size()).append(" | |
").append(options.minDistributorNodesUp()).append(" | |
").append(options.minStorageNodesUp()).append(" | |
").append(DecimalDot2.format(100 * options.minRatioOfDistributorNodesUp())).append(" % | |
").append(DecimalDot2.format(100 * options.minRatioOfStorageNodesUp())).append(" % | |
").append(options.showLocalSystemStatesInEventLog()).append(" | |
").append(options.eventLogMaxSize()).append(" | |
").append(options.eventNodeLogMaxSize()).append(" | |
").append(options.distributionBits()).append(" | |
").append(options.maxDeferredTaskVersionWaitTime().toMillis()).append("ms | |
").append(options.clusterHasGlobalDocumentTypes()).append(" | |
").append(options.enableTwoPhaseClusterStateActivation()).append(" | |
") .append(options.clusterFeedBlockEnabled()).append(" | |
")
.append(options.clusterFeedBlockLimit().entrySet().stream()
.map(kv -> String.format("%s: %.2f%%", kv.getKey(), kv.getValue() * 100.0))
.sorted()
.collect(Collectors.joining(" "))).append(" |