/*
* 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.presto.server;
import com.facebook.presto.execution.QueryInfo;
import com.facebook.presto.execution.QueryManager;
import com.facebook.presto.execution.QueryState;
import com.facebook.presto.execution.scheduler.NodeSchedulerConfig;
import com.facebook.presto.metadata.InternalNodeManager;
import com.facebook.presto.spi.NodeState;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.SECONDS;
@Path("/v1/cluster")
public class ClusterStatsResource
{
private final InternalNodeManager nodeManager;
private final QueryManager queryManager;
private final boolean isIncludeCoordinator;
@Inject
public ClusterStatsResource(NodeSchedulerConfig nodeSchedulerConfig, InternalNodeManager nodeManager, QueryManager queryManager)
{
this.isIncludeCoordinator = requireNonNull(nodeSchedulerConfig, "nodeSchedulerConfig is null").isIncludeCoordinator();
this.nodeManager = requireNonNull(nodeManager, "nodeManager is null");
this.queryManager = requireNonNull(queryManager, "queryManager is null");
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public ClusterStats getClusterStats()
{
long runningQueries = 0;
long blockedQueries = 0;
long queuedQueries = 0;
long activeNodes = nodeManager.getNodes(NodeState.ACTIVE).size();
if (!isIncludeCoordinator) {
activeNodes -= 1;
}
long runningDrivers = 0;
double memoryReservation = 0;
double rowInputRate = 0;
double byteInputRate = 0;
double cpuTimeRate = 0;
for (QueryInfo query : queryManager.getAllQueryInfo()) {
if (query.getState() == QueryState.QUEUED) {
queuedQueries++;
}
else if (query.getState() == QueryState.RUNNING) {
if (query.getQueryStats().isFullyBlocked()) {
blockedQueries++;
}
else {
runningQueries++;
}
}
if (!query.getState().isDone()) {
double totalExecutionTimeSeconds = query.getQueryStats().getElapsedTime().getValue(SECONDS);
if (totalExecutionTimeSeconds != 0) {
byteInputRate += query.getQueryStats().getProcessedInputDataSize().toBytes() / totalExecutionTimeSeconds;
rowInputRate += query.getQueryStats().getProcessedInputPositions() / totalExecutionTimeSeconds;
cpuTimeRate += (query.getQueryStats().getTotalCpuTime().getValue(SECONDS)) / totalExecutionTimeSeconds;
}
memoryReservation += query.getQueryStats().getTotalMemoryReservation().toBytes();
runningDrivers += query.getQueryStats().getRunningDrivers();
}
}
return new ClusterStats(runningQueries, blockedQueries, queuedQueries, activeNodes, runningDrivers, memoryReservation, rowInputRate, byteInputRate, cpuTimeRate);
}
public static class ClusterStats
{
private final long runningQueries;
private final long blockedQueries;
private final long queuedQueries;
private final long activeWorkers;
private final long runningDrivers;
private final double reservedMemory;
private final double rowInputRate;
private final double byteInputRate;
private final double cpuTimeRate;
@JsonCreator
public ClusterStats(
@JsonProperty("runningQueries") long runningQueries,
@JsonProperty("blockedQueries") long blockedQueries,
@JsonProperty("queuedQueries") long queuedQueries,
@JsonProperty("activeWorkers") long activeWorkers,
@JsonProperty("runningDrivers") long runningDrivers,
@JsonProperty("reservedMemory") double reservedMemory,
@JsonProperty("rowInputRate") double rowInputRate,
@JsonProperty("byteInputRate") double byteInputRate,
@JsonProperty("cpuTimeRate") double cpuTimeRate)
{
this.runningQueries = runningQueries;
this.blockedQueries = blockedQueries;
this.queuedQueries = queuedQueries;
this.activeWorkers = activeWorkers;
this.runningDrivers = runningDrivers;
this.reservedMemory = reservedMemory;
this.rowInputRate = rowInputRate;
this.byteInputRate = byteInputRate;
this.cpuTimeRate = cpuTimeRate;
}
@JsonProperty
public long getRunningQueries()
{
return runningQueries;
}
@JsonProperty
public long getBlockedQueries()
{
return blockedQueries;
}
@JsonProperty
public long getQueuedQueries()
{
return queuedQueries;
}
@JsonProperty
public long getActiveWorkers()
{
return activeWorkers;
}
@JsonProperty
public long getRunningDrivers()
{
return runningDrivers;
}
@JsonProperty
public double getReservedMemory()
{
return reservedMemory;
}
@JsonProperty
public double getRowInputRate()
{
return rowInputRate;
}
@JsonProperty
public double getByteInputRate()
{
return byteInputRate;
}
@JsonProperty
public double getCpuTimeRate()
{
return cpuTimeRate;
}
}
}