![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.avro.ipc.stats.StatsServlet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of avro-ipc Show documentation
Show all versions of avro-ipc Show documentation
Avro inter-process communication components
The newest version!
/*
* 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
*
* https://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.avro.ipc.stats;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.avro.Protocol.Message;
import org.apache.avro.ipc.RPCContext;
/**
* Exposes information provided by a StatsPlugin as a web page.
*
* This class follows the same synchronization conventions as StatsPlugin, to
* avoid requiring StatsPlugin to serve a copy of the data.
*/
public class StatsServlet extends HttpServlet {
private final StatsPlugin statsPlugin;
private VelocityEngine velocityEngine;
private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
public StatsServlet(StatsPlugin statsPlugin) throws UnavailableException {
this.statsPlugin = statsPlugin;
this.velocityEngine = new VelocityEngine();
// These two properties tell Velocity to use its own classpath-based loader
velocityEngine.addProperty("resource.loaders", "class");
velocityEngine.addProperty("resource.loader.class.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
velocityEngine.setProperty("runtime.strict_mode.enable", true);
String logChuteName = "org.apache.velocity.runtime.log.NullLogChute";
velocityEngine.setProperty("runtime.log.logsystem.class", logChuteName);
}
/*
* Helper class to store per-message data which is passed to templates.
*
* The template expects a list of charts, each of which is parameterized by map
* key-value string attributes.
*/
public class RenderableMessage { // Velocity brakes if not public
public String name;
public int numCalls;
public ArrayList> charts;
public RenderableMessage(String name) {
this.name = name;
this.charts = new ArrayList<>();
}
public ArrayList> getCharts() {
return this.charts;
}
public String getname() {
return this.name;
}
public int getNumCalls() {
return this.numCalls;
}
}
/*
* Surround each string in an array with quotation marks and escape existing
* quotes.
*
* This is useful when we have an array of strings that we want to turn into a
* javascript array declaration.
*/
protected static List escapeStringArray(List input) {
for (int i = 0; i < input.size(); i++) {
input.set(i, "\"" + input.get(i).replace("\"", "\\\"") + "\"");
}
return input;
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
try {
writeStats(resp.getWriter());
} catch (Exception e) {
e.printStackTrace();
}
}
public void writeStats(Writer w) throws IOException {
VelocityContext context = new VelocityContext();
context.put("title", "Avro RPC Stats");
ArrayList rpcs = new ArrayList<>(); // in flight rpcs
ArrayList messages = new ArrayList<>();
for (Entry rpc : this.statsPlugin.activeRpcs.entrySet()) {
rpcs.add(renderActiveRpc(rpc.getKey(), rpc.getValue()));
}
// Get set of all seen messages
Set keys = null;
synchronized (this.statsPlugin.methodTimings) {
keys = this.statsPlugin.methodTimings.keySet();
for (Message m : keys) {
messages.add(renderMethod(m));
}
}
context.put("inFlightRpcs", rpcs);
context.put("messages", messages);
context.put("currTime", FORMATTER.format(new Date()));
context.put("startupTime", FORMATTER.format(statsPlugin.startupTime));
Template t;
try {
t = velocityEngine.getTemplate("org/apache/avro/ipc/stats/templates/statsview.vm");
} catch (Exception e) {
throw new IOException();
}
t.merge(context, w);
}
private String renderActiveRpc(RPCContext rpc, Stopwatch stopwatch) throws IOException {
String out = new String();
out += rpc.getMessage().getName() + ": " + formatMillis(StatsPlugin.nanosToMillis(stopwatch.elapsedNanos()));
return out;
}
private RenderableMessage renderMethod(Message message) {
RenderableMessage out = new RenderableMessage(message.getName());
synchronized (this.statsPlugin.methodTimings) {
FloatHistogram> hist = this.statsPlugin.methodTimings.get(message);
out.numCalls = hist.getCount();
HashMap latencyBar = new HashMap<>();
// Fill in chart attributes for velocity
latencyBar.put("type", "bar");
latencyBar.put("title", "All-Time Latency");
latencyBar.put("units", "ms");
latencyBar.put("numCalls", Integer.toString(hist.getCount()));
latencyBar.put("avg", Float.toString(hist.getMean()));
latencyBar.put("stdDev", Float.toString(hist.getUnbiasedStdDev()));
latencyBar.put("labelStr", Arrays.toString(hist.getSegmenter().getBoundaryLabels().toArray()));
latencyBar.put("boundaryStr",
Arrays.toString(escapeStringArray(hist.getSegmenter().getBucketLabels()).toArray()));
latencyBar.put("dataStr", Arrays.toString(hist.getHistogram()));
out.charts.add(latencyBar);
HashMap latencyDot = new HashMap<>();
latencyDot.put("title", "Latency");
latencyDot.put("type", "dot");
latencyDot.put("dataStr", Arrays.toString(hist.getRecentAdditions().toArray()));
out.charts.add(latencyDot);
}
synchronized (this.statsPlugin.sendPayloads) {
IntegerHistogram> hist = this.statsPlugin.sendPayloads.get(message);
HashMap latencyBar = new HashMap<>();
// Fill in chart attributes for velocity
latencyBar.put("type", "bar");
latencyBar.put("title", "All-Time Send Payload");
latencyBar.put("units", "ms");
latencyBar.put("numCalls", Integer.toString(hist.getCount()));
latencyBar.put("avg", Float.toString(hist.getMean()));
latencyBar.put("stdDev", Float.toString(hist.getUnbiasedStdDev()));
latencyBar.put("labelStr", Arrays.toString(hist.getSegmenter().getBoundaryLabels().toArray()));
latencyBar.put("boundaryStr",
Arrays.toString(escapeStringArray(hist.getSegmenter().getBucketLabels()).toArray()));
latencyBar.put("dataStr", Arrays.toString(hist.getHistogram()));
out.charts.add(latencyBar);
HashMap latencyDot = new HashMap<>();
latencyDot.put("title", "Send Payload");
latencyDot.put("type", "dot");
latencyDot.put("dataStr", Arrays.toString(hist.getRecentAdditions().toArray()));
out.charts.add(latencyDot);
}
synchronized (this.statsPlugin.receivePayloads) {
IntegerHistogram> hist = this.statsPlugin.receivePayloads.get(message);
HashMap latencyBar = new HashMap<>();
// Fill in chart attributes for velocity
latencyBar.put("type", "bar");
latencyBar.put("title", "All-Time Receive Payload");
latencyBar.put("units", "ms");
latencyBar.put("numCalls", Integer.toString(hist.getCount()));
latencyBar.put("avg", Float.toString(hist.getMean()));
latencyBar.put("stdDev", Float.toString(hist.getUnbiasedStdDev()));
latencyBar.put("labelStr", Arrays.toString(hist.getSegmenter().getBoundaryLabels().toArray()));
latencyBar.put("boundaryStr",
Arrays.toString(escapeStringArray(hist.getSegmenter().getBucketLabels()).toArray()));
latencyBar.put("dataStr", Arrays.toString(hist.getHistogram()));
out.charts.add(latencyBar);
HashMap latencyDot = new HashMap<>();
latencyDot.put("title", "Recv Payload");
latencyDot.put("type", "dot");
latencyDot.put("dataStr", Arrays.toString(hist.getRecentAdditions().toArray()));
out.charts.add(latencyDot);
}
return out;
}
private CharSequence formatMillis(float millis) {
return String.format("%.0fms", millis);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy