/*
* 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.execution;
import com.facebook.presto.operator.BlockedReason;
import com.facebook.presto.operator.OperatorStats;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import io.airlift.units.DataSize;
import io.airlift.units.Duration;
import org.joda.time.DateTime;
import java.util.List;
import java.util.OptionalDouble;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
import static io.airlift.units.Duration.succinctNanos;
import static java.lang.Math.min;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
public class QueryStats
{
private final DateTime createTime;
private final DateTime executionStartTime;
private final DateTime lastHeartbeat;
private final DateTime endTime;
private final Duration elapsedTime;
private final Duration queuedTime;
private final Duration analysisTime;
private final Duration distributedPlanningTime;
private final Duration totalPlanningTime;
private final Duration finishingTime;
private final int totalTasks;
private final int runningTasks;
private final int completedTasks;
private final int totalDrivers;
private final int queuedDrivers;
private final int runningDrivers;
private final int completedDrivers;
private final double cumulativeMemory;
private final DataSize totalMemoryReservation;
private final DataSize peakMemoryReservation;
private final boolean scheduled;
private final Duration totalScheduledTime;
private final Duration totalCpuTime;
private final Duration totalUserTime;
private final Duration totalBlockedTime;
private final boolean fullyBlocked;
private final Set<BlockedReason> blockedReasons;
private final DataSize rawInputDataSize;
private final long rawInputPositions;
private final DataSize processedInputDataSize;
private final long processedInputPositions;
private final DataSize outputDataSize;
private final long outputPositions;
private final List<OperatorStats> operatorSummaries;
@VisibleForTesting
public QueryStats()
{
this.createTime = null;
this.executionStartTime = null;
this.lastHeartbeat = null;
this.endTime = null;
this.elapsedTime = null;
this.queuedTime = null;
this.analysisTime = null;
this.distributedPlanningTime = null;
this.totalPlanningTime = null;
this.finishingTime = null;
this.totalTasks = 0;
this.runningTasks = 0;
this.completedTasks = 0;
this.totalDrivers = 0;
this.queuedDrivers = 0;
this.runningDrivers = 0;
this.completedDrivers = 0;
this.cumulativeMemory = 0.0;
this.totalMemoryReservation = null;
this.peakMemoryReservation = null;
this.scheduled = false;
this.totalScheduledTime = null;
this.totalCpuTime = null;
this.totalUserTime = null;
this.totalBlockedTime = null;
this.fullyBlocked = false;
this.blockedReasons = ImmutableSet.of();
this.rawInputDataSize = null;
this.rawInputPositions = 0;
this.processedInputDataSize = null;
this.processedInputPositions = 0;
this.outputDataSize = null;
this.outputPositions = 0;
this.operatorSummaries = null;
}
@JsonCreator
public QueryStats(
@JsonProperty("createTime") DateTime createTime,
@JsonProperty("executionStartTime") DateTime executionStartTime,
@JsonProperty("lastHeartbeat") DateTime lastHeartbeat,
@JsonProperty("endTime") DateTime endTime,
@JsonProperty("elapsedTime") Duration elapsedTime,
@JsonProperty("queuedTime") Duration queuedTime,
@JsonProperty("analysisTime") Duration analysisTime,
@JsonProperty("distributedPlanningTime") Duration distributedPlanningTime,
@JsonProperty("totalPlanningTime") Duration totalPlanningTime,
@JsonProperty("finishingTime") Duration finishingTime,
@JsonProperty("totalTasks") int totalTasks,
@JsonProperty("runningTasks") int runningTasks,
@JsonProperty("completedTasks") int completedTasks,
@JsonProperty("totalDrivers") int totalDrivers,
@JsonProperty("queuedDrivers") int queuedDrivers,
@JsonProperty("runningDrivers") int runningDrivers,
@JsonProperty("completedDrivers") int completedDrivers,
@JsonProperty("cumulativeMemory") double cumulativeMemory,
@JsonProperty("totalMemoryReservation") DataSize totalMemoryReservation,
@JsonProperty("peakMemoryReservation") DataSize peakMemoryReservation,
@JsonProperty("scheduled") boolean scheduled,
@JsonProperty("totalScheduledTime") Duration totalScheduledTime,
@JsonProperty("totalCpuTime") Duration totalCpuTime,
@JsonProperty("totalUserTime") Duration totalUserTime,
@JsonProperty("totalBlockedTime") Duration totalBlockedTime,
@JsonProperty("fullyBlocked") boolean fullyBlocked,
@JsonProperty("blockedReasons") Set<BlockedReason> blockedReasons,
@JsonProperty("rawInputDataSize") DataSize rawInputDataSize,
@JsonProperty("rawInputPositions") long rawInputPositions,
@JsonProperty("processedInputDataSize") DataSize processedInputDataSize,
@JsonProperty("processedInputPositions") long processedInputPositions,
@JsonProperty("outputDataSize") DataSize outputDataSize,
@JsonProperty("outputPositions") long outputPositions,
@JsonProperty("operatorSummaries") List<OperatorStats> operatorSummaries)
{
this.createTime = requireNonNull(createTime, "createTime is null");
this.executionStartTime = executionStartTime;
this.lastHeartbeat = requireNonNull(lastHeartbeat, "lastHeartbeat is null");
this.endTime = endTime;
this.elapsedTime = elapsedTime;
this.queuedTime = queuedTime;
this.analysisTime = analysisTime;
this.distributedPlanningTime = distributedPlanningTime;
this.totalPlanningTime = totalPlanningTime;
this.finishingTime = finishingTime;
checkArgument(totalTasks >= 0, "totalTasks is negative");
this.totalTasks = totalTasks;
checkArgument(runningTasks >= 0, "runningTasks is negative");
this.runningTasks = runningTasks;
checkArgument(completedTasks >= 0, "completedTasks is negative");
this.completedTasks = completedTasks;
checkArgument(totalDrivers >= 0, "totalDrivers is negative");
this.totalDrivers = totalDrivers;
checkArgument(queuedDrivers >= 0, "queuedDrivers is negative");
this.queuedDrivers = queuedDrivers;
checkArgument(runningDrivers >= 0, "runningDrivers is negative");
this.runningDrivers = runningDrivers;
checkArgument(completedDrivers >= 0, "completedDrivers is negative");
this.completedDrivers = completedDrivers;
this.cumulativeMemory = requireNonNull(cumulativeMemory, "cumulativeMemory is null");
this.totalMemoryReservation = requireNonNull(totalMemoryReservation, "totalMemoryReservation is null");
this.peakMemoryReservation = requireNonNull(peakMemoryReservation, "peakMemoryReservation is null");
this.scheduled = scheduled;
this.totalScheduledTime = requireNonNull(totalScheduledTime, "totalScheduledTime is null");
this.totalCpuTime = requireNonNull(totalCpuTime, "totalCpuTime is null");
this.totalUserTime = requireNonNull(totalUserTime, "totalUserTime is null");
this.totalBlockedTime = requireNonNull(totalBlockedTime, "totalBlockedTime is null");
this.fullyBlocked = fullyBlocked;
this.blockedReasons = ImmutableSet.copyOf(requireNonNull(blockedReasons, "blockedReasons is null"));
this.rawInputDataSize = requireNonNull(rawInputDataSize, "rawInputDataSize is null");
checkArgument(rawInputPositions >= 0, "rawInputPositions is negative");
this.rawInputPositions = rawInputPositions;
this.processedInputDataSize = requireNonNull(processedInputDataSize, "processedInputDataSize is null");
checkArgument(processedInputPositions >= 0, "processedInputPositions is negative");
this.processedInputPositions = processedInputPositions;
this.outputDataSize = requireNonNull(outputDataSize, "outputDataSize is null");
checkArgument(outputPositions >= 0, "outputPositions is negative");
this.outputPositions = outputPositions;
this.operatorSummaries = ImmutableList.copyOf(requireNonNull(operatorSummaries, "operatorSummaries is null"));
}
@JsonProperty
public DateTime getCreateTime()
{
return createTime;
}
@JsonProperty
public DateTime getExecutionStartTime()
{
return executionStartTime;
}
@JsonProperty
public DateTime getLastHeartbeat()
{
return lastHeartbeat;
}
@JsonProperty
public DateTime getEndTime()
{
return endTime;
}
@JsonProperty
public Duration getElapsedTime()
{
return elapsedTime;
}
@JsonProperty
public Duration getQueuedTime()
{
return queuedTime;
}
@JsonProperty
public Duration getExecutionTime()
{
if (queuedTime == null) {
// counter-intuitively, this means that the query is still queued
return new Duration(0, NANOSECONDS);
}
return succinctNanos((long) elapsedTime.getValue(NANOSECONDS) - (long) queuedTime.getValue(NANOSECONDS));
}
@JsonProperty
public Duration getAnalysisTime()
{
return analysisTime;
}
@JsonProperty
public Duration getDistributedPlanningTime()
{
return distributedPlanningTime;
}
@JsonProperty
public Duration getTotalPlanningTime()
{
return totalPlanningTime;
}
@JsonProperty
public Duration getFinishingTime()
{
return finishingTime;
}
@JsonProperty
public int getTotalTasks()
{
return totalTasks;
}
@JsonProperty
public int getRunningTasks()
{
return runningTasks;
}
@JsonProperty
public int getCompletedTasks()
{
return completedTasks;
}
@JsonProperty
public int getTotalDrivers()
{
return totalDrivers;
}
@JsonProperty
public int getQueuedDrivers()
{
return queuedDrivers;
}
@JsonProperty
public int getRunningDrivers()
{
return runningDrivers;
}
@JsonProperty
public int getCompletedDrivers()
{
return completedDrivers;
}
@JsonProperty
public double getCumulativeMemory()
{
return cumulativeMemory;
}
@JsonProperty
public DataSize getTotalMemoryReservation()
{
return totalMemoryReservation;
}
@JsonProperty
public DataSize getPeakMemoryReservation()
{
return peakMemoryReservation;
}
@JsonProperty
public boolean isScheduled()
{
return scheduled;
}
@JsonProperty
public Duration getTotalScheduledTime()
{
return totalScheduledTime;
}
@JsonProperty
public Duration getTotalCpuTime()
{
return totalCpuTime;
}
@JsonProperty
public Duration getTotalUserTime()
{
return totalUserTime;
}
@JsonProperty
public Duration getTotalBlockedTime()
{
return totalBlockedTime;
}
@JsonProperty
public boolean isFullyBlocked()
{
return fullyBlocked;
}
@JsonProperty
public Set<BlockedReason> getBlockedReasons()
{
return blockedReasons;
}
@JsonProperty
public DataSize getRawInputDataSize()
{
return rawInputDataSize;
}
@JsonProperty
public long getRawInputPositions()
{
return rawInputPositions;
}
@JsonProperty
public DataSize getProcessedInputDataSize()
{
return processedInputDataSize;
}
@JsonProperty
public long getProcessedInputPositions()
{
return processedInputPositions;
}
@JsonProperty
public DataSize getOutputDataSize()
{
return outputDataSize;
}
@JsonProperty
public long getOutputPositions()
{
return outputPositions;
}
@JsonProperty
public List<OperatorStats> getOperatorSummaries()
{
return operatorSummaries;
}
@JsonProperty
public OptionalDouble getProgressPercentage()
{
if (!scheduled || totalDrivers == 0) {
return OptionalDouble.empty();
}
return OptionalDouble.of(min(100, (completedDrivers * 100.0) / totalDrivers));
}
}