blob: 3b9a8463ac46b227813367a8432a85a32265486b [file] [log] [blame]
/*
* 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.nifi.toolkit.flowanalyzer;
import java.io.FileInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.zip.GZIPInputStream;
import javax.xml.parsers.DocumentBuilder;
import org.apache.nifi.security.xml.XmlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class FlowAnalyzerDriver {
final static String CONST_BYTES_GB_CONV = "1000000000";
final static String CONST_BYTES_MB_CONV = "1000000";
final static String CONST_BYTES_KB_CONV = "1000";
final static int DIVIDE_SCALE = 9;
final static String CONST_XMLNODE_CONNECTION = "connection";
private static void printUsage() {
System.out.println("This application seeks to produce a report to analyze the flow.xml.gz file");
System.out.println(
"Currently the reports supported by this application are Total Storage for all queues " +
"backpressure, average storage of all queues backpressure, and min and max of all queues " +
"backpressure over the entire flow.");
System.out.println("\n\n\n");
System.out.println("Usage: flow-analyzer.sh <path to flow.xml.gz>");
}
public static void main(String[] args) throws Exception {
BigDecimal totalDataSize = new BigDecimal("0.0");
BigDecimal max = new BigDecimal("0.0");
BigDecimal min = new BigDecimal("0.0");
BigDecimal avg = new BigDecimal("0.0");
long maxQueueSize = 0L;
long minQueueSize = 0L;
long totalQueueSize = 0L;
int numberOfConnections = 0;
if (helpRequested(args)) {
printUsage();
return;
}
String input = args[0];
if (!input.contains("xml.gz"))
input = input + "/flow.xml.gz";
InputStream fileStream = new FileInputStream(input);
InputStream gzipStream = new GZIPInputStream(fileStream);
System.out.println("Using flow=" + input);
try {
DocumentBuilder documentBuilder = XmlUtils.createSafeDocumentBuilder(false);
Document document = documentBuilder.parse(gzipStream);
NodeList connectionNode = document.getElementsByTagName(CONST_XMLNODE_CONNECTION);
for (int x = 0; x < connectionNode.getLength(); x++) {
Node nNode = connectionNode.item(x);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element maxWorkQueueSize = (Element) nNode;
String maxDataSize = maxWorkQueueSize.getElementsByTagName("maxWorkQueueDataSize").item(0)
.getTextContent();
BigDecimal byteValue = (convertSizeToByteValue(maxDataSize)) != null
? convertSizeToByteValue(maxDataSize) : new BigDecimal("0.0");
numberOfConnections++;
avg = avg.add(byteValue);
String dataQueueSize = maxWorkQueueSize.getElementsByTagName("maxWorkQueueSize").item(0)
.getTextContent();
Long dataQueueSizeL = Long.valueOf(dataQueueSize);
totalQueueSize = dataQueueSizeL + totalQueueSize;
if(dataQueueSizeL > maxQueueSize)
maxQueueSize = dataQueueSizeL;
if(dataQueueSizeL < minQueueSize || minQueueSize == 0)
minQueueSize = dataQueueSizeL;
if (max.compareTo(byteValue) < 0)
max = byteValue;
if (byteValue.compareTo(min) < 0 || min.compareTo(new BigDecimal("0.0")) == 0)
min = byteValue;
totalDataSize = totalDataSize.add(byteValue);
}
}
System.out.println("Total Bytes Utilized by System=" + convertBytesToGB(totalDataSize).toPlainString()
+ " GB\nMax Back Pressure Size=" + convertBytesToGB(max).toPlainString()
+ " GB\nMin Back Pressure Size=" + convertBytesToGB(min).toPlainString()
+ " GB\nAverage Back Pressure Size="
+ convertBytesToGB(avg.divide(new BigDecimal(numberOfConnections), DIVIDE_SCALE, RoundingMode.HALF_UP)) + " GB");
System.out.println("Max Flowfile Queue Size=" + maxQueueSize + "\nMin Flowfile Queue Size=" + minQueueSize
+ "\nAvg Flowfile Queue Size=" + new BigDecimal(totalQueueSize).divide(new BigDecimal(numberOfConnections), DIVIDE_SCALE, RoundingMode.HALF_UP));
gzipStream.close();
fileStream.close();
} catch (Exception e) {
e.printStackTrace();
System.out.println("Exception occurred while attempting to parse flow.xml.gz. Cause: " + e.getCause());
}
}
private static boolean helpRequested(String[] args) {
return args.length == 0 || args[0].equalsIgnoreCase("-h") || args[0].equalsIgnoreCase("--help");
}
/**
*
* @param value to convert to bytes
* @return BigDecimal Byte size
*/
public static BigDecimal convertSizeToByteValue(String value) {
BigDecimal size = null;
if (value.contains("GB")) {
String numericValue = value.substring(0, value.indexOf("G") - 1);
size = new BigDecimal(numericValue).multiply(new BigDecimal(CONST_BYTES_GB_CONV));
}
if (value.contains("MB")) {
String numericValue = value.substring(0, value.indexOf("M") - 1);
size = new BigDecimal(numericValue).multiply(new BigDecimal(CONST_BYTES_MB_CONV));
}
if (value.contains("KB")) {
String numericValue = value.substring(0, value.indexOf("K") - 1);
size = new BigDecimal(numericValue).multiply(new BigDecimal(CONST_BYTES_KB_CONV));
}
return size;
}
/**
* @param bytes to convert to GB
* @return BigDecimal bytes to GB
*/
public static BigDecimal convertBytesToGB(BigDecimal bytes) {
return bytes.divide(new BigDecimal(CONST_BYTES_GB_CONV), DIVIDE_SCALE, RoundingMode.HALF_UP).stripTrailingZeros();
}
}