/*
* Copyright 2017-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.facebook.buck.event.listener;
import com.facebook.buck.distributed.thrift.BuildSlaveStatus;
import com.facebook.buck.util.Ansi;
import com.facebook.buck.util.MoreCollectors;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.stream.LongStream;
public class DistBuildSlaveStateRenderer implements MultiStateRenderer {
private final Ansi ansi;
private final long currentTimeMs;
private final ImmutableList<BuildSlaveStatus> slaveStatuses;
public DistBuildSlaveStateRenderer(
Ansi ansi, long currentTimeMs, ImmutableList<BuildSlaveStatus> slaveStatuses) {
this.ansi = ansi;
this.currentTimeMs = currentTimeMs;
this.slaveStatuses = slaveStatuses;
}
@Override
public String getExecutorCollectionLabel() {
return "SERVERS";
}
@Override
public int getExecutorCount() {
return slaveStatuses.size();
}
@Override
public ImmutableList<Long> getSortedExecutorIds(boolean sortByTime) {
// TODO(shivanker): Implement 'sort by busyness' for Stampede BuildSlaves.
return LongStream.range(0, slaveStatuses.size())
.boxed()
.collect(MoreCollectors.toImmutableList());
}
@Override
public String renderStatusLine(long slaveID, StringBuilder lineBuilder) {
Preconditions.checkArgument(slaveID >= 0 && slaveID < slaveStatuses.size());
BuildSlaveStatus status = slaveStatuses.get((int) slaveID);
lineBuilder.append(String.format(" SERVER %d)=> ", slaveID));
if (status.getTotalRulesCount() == 0) {
lineBuilder.append("PROCESSING BUILD GRAPH...");
} else {
String prefix = "IDLE";
if (status.getRulesStartedCount() != 0) {
prefix = String.format("WORKING ON %d JOBS", status.getRulesStartedCount());
}
ImmutableList.Builder<String> columns = new ImmutableList.Builder<>();
columns.add(
String.format(
"BUILT %d/%d JOBS", status.getRulesFinishedCount(), status.getTotalRulesCount()));
if (status.getRulesFailureCount() != 0) {
columns.add(String.format("%d JOBS FAILED", status.getRulesFailureCount()));
}
if (status.isSetCacheRateStats()) {
CacheRateStatsKeeper.CacheRateStatsUpdateEvent cacheStats =
CacheRateStatsKeeper.getCacheRateStatsUpdateEventFromSerializedStats(
status.getCacheRateStats());
columns.add(
String.format(
"%d [%.1f%%] CACHE MISS",
cacheStats.getCacheMissCount(), cacheStats.getCacheMissRate()));
if (cacheStats.getCacheErrorCount() != 0) {
columns.add(
String.format(
"%d [%.1f%%] CACHE ERRORS",
cacheStats.getCacheErrorCount(), cacheStats.getCacheErrorRate()));
}
}
if (status.getHttpArtifactUploadScheduledCount() > 0) {
columns.add(
String.format(
"%d/%d UPLOADED",
status.getHttpArtifactUploadSuccessCount(),
status.getHttpArtifactUploadScheduledCount()));
if (status.getHttpArtifactUploadFailureCount() > 0) {
columns.add(
String.format("%d UPLOAD ERRORS", status.getHttpArtifactUploadFailureCount()));
}
}
lineBuilder.append(
String.format("%s... (%s)", prefix, Joiner.on(", ").join(columns.build())));
}
if (status.getRulesFailureCount() != 0) {
return ansi.asErrorText(lineBuilder.toString());
} else if (status.getTotalRulesCount() != 0
&& status.getRulesSuccessCount() == status.getTotalRulesCount()) {
return ansi.asSuccessText(lineBuilder.toString());
} else {
return lineBuilder.toString();
}
}
@Override
public String renderShortStatus(long slaveID) {
Preconditions.checkArgument(slaveID >= 0 && slaveID < slaveStatuses.size());
BuildSlaveStatus status = slaveStatuses.get((int) slaveID);
String animationFrames = ":':.";
int offset = (int) ((currentTimeMs / 400) % animationFrames.length());
String glyph = "[" + animationFrames.charAt(offset) + "]";
if (status.getRulesStartedCount() == 0) {
if (status.getRulesFailureCount() != 0) {
glyph = "[X]";
} else {
glyph = "[ ]";
}
}
if (status.getRulesFailureCount() != 0) {
return ansi.asErrorText(glyph);
} else if (status.getTotalRulesCount() != 0
&& status.getRulesSuccessCount() == status.getTotalRulesCount()) {
return ansi.asSuccessText(glyph);
} else {
return glyph;
}
}
}