/* * 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.flink.runtime.webmonitor.utils; import com.fasterxml.jackson.core.JsonGenerator; import org.apache.flink.runtime.executiongraph.AccessExecution; import org.apache.flink.runtime.executiongraph.ExecutionGraph; import org.apache.flink.runtime.executiongraph.IOMetrics; import org.apache.flink.runtime.metrics.MetricNames; import org.apache.flink.runtime.webmonitor.handlers.JobVertexDetailsHandler; import org.apache.flink.runtime.webmonitor.metrics.MetricFetcher; import org.apache.flink.runtime.webmonitor.metrics.MetricStore; import javax.annotation.Nullable; import java.io.IOException; /** * This class is a mutable version of the {@link IOMetrics} class that allows adding up IO-related metrics. * * For finished jobs these metrics are stored in the {@link ExecutionGraph} as another {@link IOMetrics}. * For running jobs these metrics are retrieved using the {@link MetricFetcher}. * * This class provides a common interface to handle both cases, reducing complexity in various handlers (like * the {@link JobVertexDetailsHandler}). */ public class MutableIOMetrics extends IOMetrics { private static final long serialVersionUID = -5460777634971381737L; public MutableIOMetrics() { super(0, 0, 0, 0, 0, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D); } /** * Adds the IO metrics for the given attempt to this object. If the {@link AccessExecution} is in * a terminal state the contained {@link IOMetrics} object is added. Otherwise the given {@link MetricFetcher} is * used to retrieve the required metrics. * * @param attempt Attempt whose IO metrics should be added * @param fetcher MetricFetcher to retrieve metrics for running jobs * @param jobID JobID to which the attempt belongs * @param taskID TaskID to which the attempt belongs */ public void addIOMetrics(AccessExecution attempt, @Nullable MetricFetcher fetcher, String jobID, String taskID) { if (attempt.getState().isTerminal()) { IOMetrics ioMetrics = attempt.getIOMetrics(); if (ioMetrics != null) { // execAttempt is already finished, use final metrics stored in ExecutionGraph this.numBytesInLocal += ioMetrics.getNumBytesInLocal(); this.numBytesInRemote += ioMetrics.getNumBytesInRemote(); this.numBytesOut += ioMetrics.getNumBytesOut(); this.numRecordsIn += ioMetrics.getNumRecordsIn(); this.numRecordsOut += ioMetrics.getNumRecordsOut(); } } else { // execAttempt is still running, use MetricQueryService instead if (fetcher != null) { fetcher.update(); MetricStore.SubtaskMetricStore metrics = fetcher.getMetricStore().getSubtaskMetricStore(jobID, taskID, attempt.getParallelSubtaskIndex()); if (metrics != null) { this.numBytesInLocal += Long.valueOf(metrics.getMetric(MetricNames.IO_NUM_BYTES_IN_LOCAL, "0")); this.numBytesInRemote += Long.valueOf(metrics.getMetric(MetricNames.IO_NUM_BYTES_IN_REMOTE, "0")); this.numBytesOut += Long.valueOf(metrics.getMetric(MetricNames.IO_NUM_BYTES_OUT, "0")); this.numRecordsIn += Long.valueOf(metrics.getMetric(MetricNames.IO_NUM_RECORDS_IN, "0")); this.numRecordsOut += Long.valueOf(metrics.getMetric(MetricNames.IO_NUM_RECORDS_OUT, "0")); } } } } /** * Writes the IO metrics contained in this object to the given {@link JsonGenerator}. * * The JSON structure written is as follows: * "metrics": { * "read-bytes": 1, * "write-bytes": 2, * "read-records": 3, * "write-records": 4 * } * * @param gen JsonGenerator to which the metrics should be written * @throws IOException */ public void writeIOMetricsAsJson(JsonGenerator gen) throws IOException { gen.writeObjectFieldStart("metrics"); gen.writeNumberField("read-bytes",this.numBytesInLocal + this.numBytesInRemote); gen.writeNumberField("write-bytes", this.numBytesOut); gen.writeNumberField("read-records", this.numRecordsIn); gen.writeNumberField("write-records", this.numRecordsOut); gen.writeEndObject(); } }