blob: 4d79fb0c1ba31a779bc4ac2e5a069f6ac98c17b8 [file] [log] [blame]
/*
* Copyright 2018, OpenCensus Authors
*
* 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 io.opencensus.contrib.zpages;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_ERROR_COUNT_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_ERROR_COUNT_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_ERROR_COUNT_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_FINISHED_COUNT_CUMULATIVE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_FINISHED_COUNT_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_FINISHED_COUNT_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_REQUEST_BYTES_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_REQUEST_BYTES_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_REQUEST_BYTES_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_REQUEST_COUNT_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_REQUEST_COUNT_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_REQUEST_COUNT_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_RESPONSE_BYTES_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_RESPONSE_BYTES_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_RESPONSE_BYTES_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_RESPONSE_COUNT_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_RESPONSE_COUNT_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_RESPONSE_COUNT_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_ROUNDTRIP_LATENCY_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_ROUNDTRIP_LATENCY_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_ROUNDTRIP_LATENCY_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_STARTED_COUNT_CUMULATIVE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_STARTED_COUNT_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_STARTED_COUNT_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_UNCOMPRESSED_REQUEST_BYTES_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_UNCOMPRESSED_REQUEST_BYTES_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_UNCOMPRESSED_REQUEST_BYTES_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_UNCOMPRESSED_RESPONSE_BYTES_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_UNCOMPRESSED_RESPONSE_BYTES_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_CLIENT_UNCOMPRESSED_RESPONSE_BYTES_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_ERROR_COUNT_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_ERROR_COUNT_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_ERROR_COUNT_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_FINISHED_COUNT_CUMULATIVE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_FINISHED_COUNT_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_FINISHED_COUNT_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_REQUEST_BYTES_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_REQUEST_BYTES_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_REQUEST_BYTES_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_REQUEST_COUNT_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_REQUEST_COUNT_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_REQUEST_COUNT_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_RESPONSE_BYTES_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_RESPONSE_BYTES_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_RESPONSE_BYTES_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_RESPONSE_COUNT_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_RESPONSE_COUNT_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_RESPONSE_COUNT_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_SERVER_ELAPSED_TIME_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_SERVER_LATENCY_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_SERVER_LATENCY_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_SERVER_LATENCY_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_STARTED_COUNT_CUMULATIVE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_STARTED_COUNT_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_STARTED_COUNT_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_UNCOMPRESSED_REQUEST_BYTES_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_UNCOMPRESSED_REQUEST_BYTES_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_UNCOMPRESSED_REQUEST_BYTES_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_UNCOMPRESSED_RESPONSE_BYTES_HOUR_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_UNCOMPRESSED_RESPONSE_BYTES_MINUTE_VIEW;
import static io.opencensus.contrib.grpc.metrics.RpcViewConstants.RPC_SERVER_UNCOMPRESSED_RESPONSE_BYTES_VIEW;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import io.opencensus.common.Duration;
import io.opencensus.stats.AggregationData;
import io.opencensus.stats.AggregationData.CountData;
import io.opencensus.stats.AggregationData.DistributionData;
import io.opencensus.stats.View;
import io.opencensus.stats.ViewData;
import io.opencensus.stats.ViewManager;
import io.opencensus.tags.TagValue;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Formatter;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
/*>>>
import org.checkerframework.checker.nullness.qual.Nullable;
*/
/** HTML page formatter for gRPC cumulative and interval stats. */
@SuppressWarnings("deprecation")
final class RpczZPageHandler extends ZPageHandler {
private final ViewManager viewManager;
private static final String RPCZ_URL = "/rpcz";
private static final String SENT = "Sent";
private static final String RECEIVED = "Received";
private static final double SECONDS_PER_MINUTE = 60.0;
private static final double SECONDS_PER_HOUR = 3600.0;
private static final double NANOS_PER_SECOND = 1e9;
private static final double BYTES_PER_KB = 1024;
private static final ImmutableList<String> RPC_STATS_TYPES =
ImmutableList.of(
"Count",
"Avg latency (ms)",
// TODO(songya): add a column for latency percentiles.
"Rate (rpc/s)",
"Input (kb/s)",
"Output (kb/s)",
"Errors");
private static final ImmutableList<View> CLIENT_RPC_CUMULATIVE_VIEWS =
ImmutableList.of(
RPC_CLIENT_ERROR_COUNT_VIEW,
RPC_CLIENT_ROUNDTRIP_LATENCY_VIEW,
RPC_CLIENT_REQUEST_BYTES_VIEW,
RPC_CLIENT_RESPONSE_BYTES_VIEW,
RPC_CLIENT_STARTED_COUNT_CUMULATIVE_VIEW,
// The last 5 views are not used yet.
RPC_CLIENT_REQUEST_COUNT_VIEW,
RPC_CLIENT_RESPONSE_COUNT_VIEW,
RPC_CLIENT_UNCOMPRESSED_REQUEST_BYTES_VIEW,
RPC_CLIENT_UNCOMPRESSED_RESPONSE_BYTES_VIEW,
RPC_CLIENT_FINISHED_COUNT_CUMULATIVE_VIEW);
private static final ImmutableList<View> SERVER_RPC_CUMULATIVE_VIEWS =
ImmutableList.of(
RPC_SERVER_ERROR_COUNT_VIEW,
RPC_SERVER_SERVER_LATENCY_VIEW,
RPC_SERVER_REQUEST_BYTES_VIEW,
RPC_SERVER_RESPONSE_BYTES_VIEW,
RPC_SERVER_STARTED_COUNT_CUMULATIVE_VIEW,
// The last 5 views are not used yet.
RPC_SERVER_REQUEST_COUNT_VIEW,
RPC_SERVER_RESPONSE_COUNT_VIEW,
RPC_SERVER_UNCOMPRESSED_REQUEST_BYTES_VIEW,
RPC_SERVER_UNCOMPRESSED_RESPONSE_BYTES_VIEW,
RPC_SERVER_FINISHED_COUNT_CUMULATIVE_VIEW);
// Interval views may be removed in the future.
private static final ImmutableList<View> CLIENT_RPC_MINUTE_VIEWS =
ImmutableList.of(
RPC_CLIENT_ERROR_COUNT_MINUTE_VIEW,
RPC_CLIENT_ROUNDTRIP_LATENCY_MINUTE_VIEW,
RPC_CLIENT_REQUEST_BYTES_MINUTE_VIEW,
RPC_CLIENT_RESPONSE_BYTES_MINUTE_VIEW,
RPC_CLIENT_STARTED_COUNT_MINUTE_VIEW,
// The last 5 views are not used yet.
RPC_CLIENT_REQUEST_COUNT_MINUTE_VIEW,
RPC_CLIENT_RESPONSE_COUNT_MINUTE_VIEW,
RPC_CLIENT_UNCOMPRESSED_REQUEST_BYTES_MINUTE_VIEW,
RPC_CLIENT_UNCOMPRESSED_RESPONSE_BYTES_MINUTE_VIEW,
RPC_CLIENT_FINISHED_COUNT_MINUTE_VIEW);
// Interval views may be removed in the future.
private static final ImmutableList<View> SERVER_RPC_MINUTE_VIEWS =
ImmutableList.of(
RPC_SERVER_ERROR_COUNT_MINUTE_VIEW,
RPC_SERVER_SERVER_LATENCY_MINUTE_VIEW,
RPC_SERVER_REQUEST_BYTES_MINUTE_VIEW,
RPC_SERVER_RESPONSE_BYTES_MINUTE_VIEW,
RPC_SERVER_STARTED_COUNT_MINUTE_VIEW,
// The last 5 views are not used yet.
RPC_SERVER_REQUEST_COUNT_MINUTE_VIEW,
RPC_SERVER_RESPONSE_COUNT_MINUTE_VIEW,
RPC_SERVER_UNCOMPRESSED_REQUEST_BYTES_MINUTE_VIEW,
RPC_SERVER_UNCOMPRESSED_RESPONSE_BYTES_MINUTE_VIEW,
RPC_SERVER_FINISHED_COUNT_MINUTE_VIEW);
// Interval views may be removed in the future.
private static final ImmutableList<View> CLIENT_RPC_HOUR_VIEWS =
ImmutableList.of(
RPC_CLIENT_ERROR_COUNT_HOUR_VIEW,
RPC_CLIENT_ROUNDTRIP_LATENCY_HOUR_VIEW,
RPC_CLIENT_REQUEST_BYTES_HOUR_VIEW,
RPC_CLIENT_RESPONSE_BYTES_HOUR_VIEW,
RPC_CLIENT_STARTED_COUNT_HOUR_VIEW,
// The last 5 views are not used yet.
RPC_CLIENT_REQUEST_COUNT_HOUR_VIEW,
RPC_CLIENT_RESPONSE_COUNT_HOUR_VIEW,
RPC_CLIENT_UNCOMPRESSED_REQUEST_BYTES_HOUR_VIEW,
RPC_CLIENT_UNCOMPRESSED_RESPONSE_BYTES_HOUR_VIEW,
RPC_CLIENT_FINISHED_COUNT_HOUR_VIEW);
// Interval views may be removed in the future.
private static final ImmutableList<View> SERVER_RPC_HOUR_VIEWS =
ImmutableList.of(
RPC_SERVER_ERROR_COUNT_HOUR_VIEW,
RPC_SERVER_SERVER_LATENCY_HOUR_VIEW,
RPC_SERVER_SERVER_ELAPSED_TIME_HOUR_VIEW,
RPC_SERVER_REQUEST_BYTES_HOUR_VIEW,
RPC_SERVER_RESPONSE_BYTES_HOUR_VIEW,
RPC_SERVER_STARTED_COUNT_HOUR_VIEW,
// The last 5 views are not used yet.
RPC_SERVER_REQUEST_COUNT_HOUR_VIEW,
RPC_SERVER_RESPONSE_COUNT_HOUR_VIEW,
RPC_SERVER_UNCOMPRESSED_REQUEST_BYTES_HOUR_VIEW,
RPC_SERVER_UNCOMPRESSED_RESPONSE_BYTES_HOUR_VIEW,
RPC_SERVER_FINISHED_COUNT_HOUR_VIEW);
@Override
public String getUrlPath() {
return RPCZ_URL;
}
private static void emitStyle(PrintWriter out) {
out.write("<style>\n");
out.write(Style.style);
out.write("</style>\n");
}
@Override
public void emitHtml(Map<String, String> queryMap, OutputStream outputStream) {
PrintWriter out =
new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream, Charsets.UTF_8)));
out.write("<!DOCTYPE html>\n");
out.write("<html lang=\"en\"><head>\n");
out.write("<meta charset=\"utf-8\">\n");
out.write("<title>RpcZ</title>\n");
out.write("<link rel=\"shortcut icon\" href=\"https://opencensus.io/images/favicon.ico\"/>\n");
out.write(
"<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300\""
+ "rel=\"stylesheet\">\n");
out.write(
"<link href=\"https://fonts.googleapis.com/css?family=Roboto\"" + "rel=\"stylesheet\">\n");
emitStyle(out);
out.write("</head>\n");
out.write("<body>\n");
try {
emitHtmlBody(out);
} catch (Throwable t) {
out.write("Errors while generate the HTML page " + t);
}
out.write("</body>\n");
out.write("</html>\n");
out.close();
}
private void emitHtmlBody(PrintWriter out) {
Formatter formatter = new Formatter(out, Locale.US);
out.write(
"<p class=\"header\">"
+ "<img class=\"oc\" src=\"https://opencensus.io/img/logo-sm.svg\" />"
+ "Open<span>Census</span></p>");
out.write("<h1>RPC Stats</h1>");
out.write("<p></p>");
emitSummaryTable(out, formatter, /* isReceived= */ false);
emitSummaryTable(out, formatter, /* isReceived= */ true);
}
private void emitSummaryTable(PrintWriter out, Formatter formatter, boolean isReceived) {
formatter.format(
"<h2><table class=\"title\"><tr align=left><td><font size=+2>"
+ "%s</font></td></tr></table></h2>",
(isReceived ? RECEIVED : SENT));
formatter.format("<table frame=box cellspacing=0 cellpadding=2>");
emitSummaryTableHeader(out, formatter);
Map<String, StatsSnapshot> snapshots = getStatsSnapshots(isReceived);
for (Entry<String, StatsSnapshot> entry : snapshots.entrySet()) {
emitSummaryTableRows(out, formatter, entry.getValue(), entry.getKey());
}
out.write("</table>");
out.write("<br />");
}
private static void emitSummaryTableHeader(PrintWriter out, Formatter formatter) {
// First line.
formatter.format("<tr bgcolor=#A94442>");
out.write("<th></th><td></td>");
for (String rpcStatsType : RPC_STATS_TYPES) {
formatter.format("<th class=\"borderLB\" colspan=3>%s</th>", rpcStatsType);
}
out.write("</tr>");
// Second line.
formatter.format("<tr bgcolor=#A94442>");
out.write("<th align=left>Method</th>\n");
out.write("<td bgcolor=#A94442>&nbsp;&nbsp;&nbsp;&nbsp;</td>");
for (int i = 0; i < RPC_STATS_TYPES.size(); i++) {
out.write("<th class=\"borderLB\" align=center>Min.</th>\n");
out.write("<th class=\"borderLB\" align=center>Hr.</th>\n");
out.write("<th class=\"borderLB\" align=center>Tot.</th>");
}
}
private static void emitSummaryTableRows(
PrintWriter out, Formatter formatter, StatsSnapshot snapshot, String method) {
out.write("<tr>");
formatter.format("<td><b>%s</b></td>", method);
out.write("<td></td>");
formatter.format("<td class=\"borderLC\">%d</td>", snapshot.countLastMinute);
formatter.format("<td class=\"borderLC\">%d</td>", snapshot.countLastHour);
formatter.format("<td class=\"borderLC\">%d</td>", snapshot.countTotal);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.avgLatencyLastMinute);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.avgLatencyLastHour);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.avgLatencyTotal);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.rpcRateLastMinute);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.rpcRateLastHour);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.rpcRateTotal);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.inputRateLastMinute);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.inputRateLastHour);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.inputRateTotal);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.outputRateLastMinute);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.outputRateLastHour);
formatter.format("<td class=\"borderLC\">%.3f</td>", snapshot.outputRateTotal);
formatter.format("<td class=\"borderLC\">%d</td>", snapshot.errorsLastMinute);
formatter.format("<td class=\"borderLC\">%d</td>", snapshot.errorsLastHour);
formatter.format("<td class=\"borderLC\">%d</td>", snapshot.errorsTotal);
out.write("</tr>");
}
// Gets stats snapshot for each method.
private Map<String, StatsSnapshot> getStatsSnapshots(boolean isReceived) {
SortedMap<String, StatsSnapshot> map = Maps.newTreeMap(); // Sorted by method name.
if (isReceived) {
getStatsSnapshots(map, SERVER_RPC_CUMULATIVE_VIEWS);
getStatsSnapshots(map, SERVER_RPC_MINUTE_VIEWS);
getStatsSnapshots(map, SERVER_RPC_HOUR_VIEWS);
} else {
getStatsSnapshots(map, CLIENT_RPC_CUMULATIVE_VIEWS);
getStatsSnapshots(map, CLIENT_RPC_MINUTE_VIEWS);
getStatsSnapshots(map, CLIENT_RPC_HOUR_VIEWS);
}
return map;
}
private void getStatsSnapshots(Map<String, StatsSnapshot> map, List<View> views) {
for (View view : views) {
ViewData viewData = viewManager.getView(view.getName());
if (viewData == null) {
continue;
}
for (Entry<List</*@Nullable*/ TagValue>, AggregationData> entry :
viewData.getAggregationMap().entrySet()) {
TagValue tagValue;
List</*@Nullable*/ TagValue> tagValues = entry.getKey();
if (tagValues.size() == 1) {
tagValue = tagValues.get(0);
} else { // Error count views have two tag key: status and method.
tagValue = tagValues.get(1);
}
String method = tagValue == null ? "" : tagValue.asString();
StatsSnapshot snapshot = map.get(method);
if (snapshot == null) {
snapshot = new StatsSnapshot();
map.put(method, snapshot);
}
getStats(snapshot, entry.getValue(), view, viewData.getWindowData());
}
}
}
// Gets RPC stats by its view definition, and set it to stats snapshot.
private static void getStats(
StatsSnapshot snapshot,
AggregationData data,
View view,
ViewData.AggregationWindowData windowData) {
if (view == RPC_CLIENT_ROUNDTRIP_LATENCY_VIEW || view == RPC_SERVER_SERVER_LATENCY_VIEW) {
snapshot.avgLatencyTotal = ((DistributionData) data).getMean();
} else if (view == RPC_CLIENT_ROUNDTRIP_LATENCY_MINUTE_VIEW
|| view == RPC_SERVER_SERVER_LATENCY_MINUTE_VIEW) {
snapshot.avgLatencyLastMinute = ((AggregationData.MeanData) data).getMean();
} else if (view == RPC_CLIENT_ROUNDTRIP_LATENCY_HOUR_VIEW
|| view == RPC_SERVER_SERVER_LATENCY_HOUR_VIEW) {
snapshot.avgLatencyLastHour = ((AggregationData.MeanData) data).getMean();
} else if (view == RPC_CLIENT_ERROR_COUNT_VIEW || view == RPC_SERVER_ERROR_COUNT_VIEW) {
snapshot.errorsTotal = ((AggregationData.MeanData) data).getCount();
} else if (view == RPC_CLIENT_ERROR_COUNT_MINUTE_VIEW
|| view == RPC_SERVER_ERROR_COUNT_MINUTE_VIEW) {
snapshot.errorsLastMinute = ((AggregationData.MeanData) data).getCount();
} else if (view == RPC_CLIENT_ERROR_COUNT_HOUR_VIEW
|| view == RPC_SERVER_ERROR_COUNT_HOUR_VIEW) {
snapshot.errorsLastHour = ((AggregationData.MeanData) data).getCount();
} else if (view == RPC_CLIENT_REQUEST_BYTES_VIEW || view == RPC_SERVER_REQUEST_BYTES_VIEW) {
DistributionData distributionData = (DistributionData) data;
snapshot.inputRateTotal =
distributionData.getCount()
* distributionData.getMean()
/ BYTES_PER_KB
/ getDurationInSecs((ViewData.AggregationWindowData.CumulativeData) windowData);
} else if (view == RPC_CLIENT_REQUEST_BYTES_MINUTE_VIEW
|| view == RPC_SERVER_REQUEST_BYTES_MINUTE_VIEW) {
AggregationData.MeanData meanData = (AggregationData.MeanData) data;
snapshot.inputRateLastMinute =
meanData.getMean() * meanData.getCount() / BYTES_PER_KB / SECONDS_PER_MINUTE;
} else if (view == RPC_CLIENT_REQUEST_BYTES_HOUR_VIEW
|| view == RPC_SERVER_REQUEST_BYTES_HOUR_VIEW) {
AggregationData.MeanData meanData = (AggregationData.MeanData) data;
snapshot.inputRateLastHour =
meanData.getMean() * meanData.getCount() / BYTES_PER_KB / SECONDS_PER_HOUR;
} else if (view == RPC_CLIENT_RESPONSE_BYTES_VIEW || view == RPC_SERVER_RESPONSE_BYTES_VIEW) {
DistributionData distributionData = (DistributionData) data;
snapshot.outputRateTotal =
distributionData.getCount()
* distributionData.getMean()
/ BYTES_PER_KB
/ getDurationInSecs((ViewData.AggregationWindowData.CumulativeData) windowData);
} else if (view == RPC_CLIENT_RESPONSE_BYTES_MINUTE_VIEW
|| view == RPC_SERVER_RESPONSE_BYTES_MINUTE_VIEW) {
AggregationData.MeanData meanData = (AggregationData.MeanData) data;
snapshot.outputRateLastMinute =
meanData.getMean() * meanData.getCount() / BYTES_PER_KB / SECONDS_PER_MINUTE;
} else if (view == RPC_CLIENT_RESPONSE_BYTES_HOUR_VIEW
|| view == RPC_SERVER_RESPONSE_BYTES_HOUR_VIEW) {
AggregationData.MeanData meanData = (AggregationData.MeanData) data;
snapshot.outputRateLastHour =
meanData.getMean() * meanData.getCount() / BYTES_PER_KB / SECONDS_PER_HOUR;
} else if (view == RPC_CLIENT_STARTED_COUNT_MINUTE_VIEW
|| view == RPC_SERVER_STARTED_COUNT_MINUTE_VIEW) {
snapshot.countLastMinute = ((CountData) data).getCount();
snapshot.rpcRateLastMinute = snapshot.countLastMinute / SECONDS_PER_MINUTE;
} else if (view == RPC_CLIENT_STARTED_COUNT_HOUR_VIEW
|| view == RPC_SERVER_STARTED_COUNT_HOUR_VIEW) {
snapshot.countLastHour = ((CountData) data).getCount();
snapshot.rpcRateLastHour = snapshot.countLastHour / SECONDS_PER_HOUR;
} else if (view == RPC_CLIENT_STARTED_COUNT_CUMULATIVE_VIEW
|| view == RPC_SERVER_STARTED_COUNT_CUMULATIVE_VIEW) {
snapshot.countTotal = ((CountData) data).getCount();
snapshot.rpcRateTotal =
snapshot.countTotal
/ getDurationInSecs((ViewData.AggregationWindowData.CumulativeData) windowData);
} // TODO(songya): compute and store latency percentiles.
}
// Calculates the duration of the given CumulativeData in seconds.
private static double getDurationInSecs(
ViewData.AggregationWindowData.CumulativeData cumulativeData) {
return toDoubleSeconds(cumulativeData.getEnd().subtractTimestamp(cumulativeData.getStart()));
}
// Converts a Duration to seconds. Converts the nanoseconds of the given duration to decimals of
// second, and adds it to the second of duration.
// For example, Duration.create(/* seconds */ 5, /* nanos */ 5 * 1e8) will be converted to 5.5
// seconds.
private static double toDoubleSeconds(Duration duration) {
return duration.getNanos() / NANOS_PER_SECOND + duration.getSeconds();
}
static RpczZPageHandler create(ViewManager viewManager) {
return new RpczZPageHandler(viewManager);
}
private RpczZPageHandler(ViewManager viewManager) {
this.viewManager = viewManager;
}
private static class StatsSnapshot {
long countLastMinute;
long countLastHour;
long countTotal;
double rpcRateLastMinute;
double rpcRateLastHour;
double rpcRateTotal;
double avgLatencyLastMinute;
double avgLatencyLastHour;
double avgLatencyTotal;
double inputRateLastMinute;
double inputRateLastHour;
double inputRateTotal;
double outputRateLastMinute;
double outputRateLastHour;
double outputRateTotal;
long errorsLastMinute;
long errorsLastHour;
long errorsTotal;
}
}