/** * 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.hadoop.hdfs.storageservice.server; import org.apache.hadoop.hdfs.protocol.ClientProxyRequests.Request; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStreamWriter; public class ClientProxyMetrics { private EventDurationCalculator requestProcessing = new EventDurationCalculator(); private EventDurationCalculator namenodeRPC = new EventDurationCalculator(); private EventDurationCalculator executorWaiting = new EventDurationCalculator(); private File outFile; public ClientProxyMetrics() throws IOException { outFile = File.createTempFile("ClientProxyMetrics-", ".txt", new File("/tmp/")); } public void startProcessing(@SuppressWarnings("unused") Request request) { requestProcessing.eventStarted(); } public void executorSubmit(@SuppressWarnings("unused") Request request) { executorWaiting.eventStarted(); } public void executorCall(@SuppressWarnings("unused") Request request) { executorWaiting.eventEnded(); } public void namenodeCalled(@SuppressWarnings("unused") Request request) { namenodeRPC.eventStarted(); } public void namenodeReturned(@SuppressWarnings("unused") Request request) { namenodeRPC.eventEnded(); } public void endProcessing(@SuppressWarnings("unused") Request request) { requestProcessing.eventEnded(); } public void dump(OutputStreamWriter output) throws IOException { output.write("requestProcessing : " + requestProcessing.getMean() + "\n"); output.write("namenodeRPC : " + namenodeRPC.getMean() + "\n"); output.write("executorWaiting : " + executorWaiting.getMean() + "\n"); } // TODO: this is temporary, all metrics should get into Hadoop Metrics-like thing public void dump() throws IOException { FileWriter out = new FileWriter(outFile, true); try { dump(out); } finally { out.close(); } } public static class EventDurationCalculator { private long lastEventTime = 0; private double cumulativeTimeMillis = 0; private int eventsCountTotal = 0; private int eventsCountCurrent = 0; private void update() { System.nanoTime(); // Discarding first result, empirically improves stability long now = System.nanoTime(); cumulativeTimeMillis += ((double) eventsCountCurrent * (now - lastEventTime)) / 1e6; lastEventTime = now; } public synchronized void eventStarted() { update(); eventsCountCurrent++; eventsCountTotal++; } public synchronized void eventEnded() { if (eventsCountCurrent < 0) { throw new IllegalStateException("No matching eventStarted()"); } update(); eventsCountCurrent--; } public synchronized double getMean() { update(); return ((double) cumulativeTimeMillis / eventsCountTotal); } } }