/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.hive.ql.exec.tez.monitoring;
import org.apache.hadoop.hive.llap.counters.LlapIOCounters;
import org.apache.hadoop.hive.ql.exec.Utilities;
import org.apache.hadoop.hive.ql.session.SessionState;
import org.apache.tez.common.counters.TezCounters;
import org.apache.tez.dag.api.TezException;
import org.apache.tez.dag.api.client.DAGClient;
import org.apache.tez.dag.api.client.Progress;
import org.apache.tez.dag.api.client.StatusGetOpts;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;
import static org.apache.hadoop.hive.ql.exec.tez.monitoring.Constants.SEPARATOR;
import static org.apache.hadoop.hive.ql.exec.tez.monitoring.TezJobMonitor.getCounterValueByGroupName;
public class LLAPioSummary implements PrintSummary {
private static final String LLAP_SUMMARY_HEADER_FORMAT = "%10s %9s %9s %10s %9s %10s %11s %8s %9s";
private static final String LLAP_IO_SUMMARY_HEADER = "LLAP IO Summary";
private static final String LLAP_SUMMARY_HEADER = String.format(LLAP_SUMMARY_HEADER_FORMAT,
"VERTICES", "ROWGROUPS", "META_HIT", "META_MISS", "DATA_HIT", "DATA_MISS",
"ALLOCATION", "USED", "TOTAL_IO");
private final DecimalFormat secondsFormatter = new DecimalFormat("#0.00");
private Map<String, Progress> progressMap;
private DAGClient dagClient;
private boolean first = false;
LLAPioSummary(Map<String, Progress> progressMap, DAGClient dagClient) {
this.progressMap = progressMap;
this.dagClient = dagClient;
}
@Override
public void print(SessionState.LogHelper console) {
console.printInfo("");
console.printInfo(LLAP_IO_SUMMARY_HEADER);
SortedSet<String> keys = new TreeSet<>(progressMap.keySet());
Set<StatusGetOpts> statusOptions = new HashSet<>(1);
statusOptions.add(StatusGetOpts.GET_COUNTERS);
String counterGroup = LlapIOCounters.class.getName();
for (String vertexName : keys) {
// Reducers do not benefit from LLAP IO so no point in printing
if (vertexName.startsWith("Reducer")) {
continue;
}
TezCounters vertexCounters = vertexCounter(statusOptions, vertexName);
if (vertexCounters != null) {
if (!first) {
console.printInfo(SEPARATOR);
console.printInfo(LLAP_SUMMARY_HEADER);
console.printInfo(SEPARATOR);
first = true;
}
console.printInfo(vertexSummary(vertexName, counterGroup, vertexCounters));
}
}
console.printInfo(SEPARATOR);
console.printInfo("");
}
private String vertexSummary(String vertexName, String counterGroup, TezCounters vertexCounters) {
final long selectedRowgroups = getCounterValueByGroupName(vertexCounters,
counterGroup, LlapIOCounters.SELECTED_ROWGROUPS.name());
final long metadataCacheHit = getCounterValueByGroupName(vertexCounters,
counterGroup, LlapIOCounters.METADATA_CACHE_HIT.name());
final long metadataCacheMiss = getCounterValueByGroupName(vertexCounters,
counterGroup, LlapIOCounters.METADATA_CACHE_MISS.name());
final long cacheHitBytes = getCounterValueByGroupName(vertexCounters,
counterGroup, LlapIOCounters.CACHE_HIT_BYTES.name());
final long cacheMissBytes = getCounterValueByGroupName(vertexCounters,
counterGroup, LlapIOCounters.CACHE_MISS_BYTES.name());
final long allocatedBytes = getCounterValueByGroupName(vertexCounters,
counterGroup, LlapIOCounters.ALLOCATED_BYTES.name());
final long allocatedUsedBytes = getCounterValueByGroupName(vertexCounters,
counterGroup, LlapIOCounters.ALLOCATED_USED_BYTES.name());
final long totalIoTime = getCounterValueByGroupName(vertexCounters,
counterGroup, LlapIOCounters.TOTAL_IO_TIME_NS.name());
return String.format(LLAP_SUMMARY_HEADER_FORMAT,
vertexName,
selectedRowgroups,
metadataCacheHit,
metadataCacheMiss,
Utilities.humanReadableByteCount(cacheHitBytes),
Utilities.humanReadableByteCount(cacheMissBytes),
Utilities.humanReadableByteCount(allocatedBytes),
Utilities.humanReadableByteCount(allocatedUsedBytes),
secondsFormatter.format(totalIoTime / 1000_000_000.0) + "s");
}
private TezCounters vertexCounter(Set<StatusGetOpts> statusOptions, String vertexName) {
try {
return dagClient.getVertexStatus(vertexName, statusOptions).getVertexCounters();
} catch (IOException | TezException e) {
// best attempt, shouldn't really kill DAG for this
}
return null;
}
}