/*
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* 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 scouter.client.stack.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.StringTokenizer;
import scouter.client.stack.base.MainProcessor;
import scouter.client.stack.base.PreferenceManager;
import scouter.client.stack.data.StackFileInfo;
public class HtmlUtils {
static public final int HTML_MAX_LINES = 20000;
public static String getAsTable( String prefix, String[] elements ) {
StringBuffer result = new StringBuffer();
// int from = elements.length > 4 ? elements.length - 4 : 0;
int from = 0;
for ( int i = from; i < elements.length; i++ ) {
if ( elements[i].trim().length() > 0 ) {
// remove backslashes as they confuse the html display.
String elem = elements[i].replaceAll("\\\\", "/");
result.append("<tr><td width=\"20px\"></td><td><a href=\"");
result.append(prefix);
result.append(elem);
result.append("\">");
result.append(cutLink(elem, 80));
result.append("</a></td></tr>\n");
}
}
return (result.toString());
}
public static String cutLink( String link, int len ) {
if ( link.length() > len ) {
String cut = link.substring(0, len / 2) +
"..." + link.substring(link.length() - (len / 2));
return (cut);
}
return (link);
}
public static String getMainBodyStart() {
return "<TABLE width='1500'><TR><TD width='50'></TD><TD>";
}
public static String getMainBodyEnd() {
return "</TD></TR></TABLE>";
}
public static String getStackFileInfo( StackFileInfo stackFileInfo ) {
StringBuffer buffer = new StringBuffer(1024000);
buffer.append(getMainBodyStart());
buffer.append(getCurrentConfigurationBody()).append("<br><br>");
buffer.append("<b>[ ").append(stackFileInfo.getFilename()).append(" ]</b><BR>");
buffer.append("Parser configuration filename : ").append(stackFileInfo.getParserConfig().getConfigFilename()).append("<br>");
buffer.append("Dump count : ").append(NumberUtils.intToString(stackFileInfo.getDumpCount())).append("<BR>");
buffer.append("Worker count : ").append(NumberUtils.intToString(stackFileInfo.getTotalWorkerCount())).append("<BR>");
buffer.append("Working count : ").append(NumberUtils.intToString(stackFileInfo.getTotalWorkingCount())).append("<BR>");
ArrayList<String> list = stackFileInfo.getTimeList();
if ( list == null || list.size() == 0 ) {
return buffer.toString();
}
int size = list.size();
if ( stackFileInfo.getTotalSecond() > 0 ) {
buffer.append("Monitoring seconds : ").append(NumberUtils.secsToTime(stackFileInfo.getTotalSecond())).append(" -> ");
buffer.append(NumberUtils.intToString(stackFileInfo.getTotalSecond())).append(" secs ");
}
if ( list != null && size > 1 ) {
buffer.append('(').append(list.get(0).substring(0, stackFileInfo.getParserConfig().getTimeSize())).append(" - ")
.append(list.get(size - 1).substring(0, stackFileInfo.getParserConfig().getTimeSize())).append(')');
}
boolean isSimpleDumpList = MainProcessor.instance().isSimpleDumpTimeList();
buffer.append("<BR><BR>");
if ( isSimpleDumpList ) {
buffer.append("<b>[ Simple dump time list ]</b><BR>");
} else {
buffer.append("<b>[ Dump time list ]</b><BR>");
}
buffer.append("<TABLE border='1'>");
buffer.append("<TR><TH align='center'>Time</TH><TH align='center'>Worker</TH><TH align='center'>Working</TH>");
ArrayList<String> statusList = stackFileInfo.getThreadStatusList();
int statusCnt = 0;
if(statusList != null){
statusCnt = statusList.size();
for(int i = 0; i < statusCnt ; i++){
buffer.append("<TH align='center'>").append(statusList.get(i)).append("</TH>");
}
}
buffer.append("</TR>");
if ( isSimpleDumpList ) {
int workerCnt = 0;
int workingCnt = 0;
int [] threadStatusList = null;
if(statusCnt > 0){
threadStatusList = new int[statusCnt];
for(int i= 0; i < statusCnt; i++){
threadStatusList[i] = 0;
}
}
StringTokenizer token = null;
int index, value;
for ( int i = 0; i < size; i++ ) {
token = new StringTokenizer(list.get(i), "\t");
index = 0;
while ( token.hasMoreElements() ) {
if ( index > 0 ) {
try {
value = Integer.parseInt((String)token.nextElement());
} catch ( Exception ex ) {
ex.printStackTrace();
value = 0;
}
switch ( index ) {
case 1:
workerCnt += value;
break;
case 2:
workingCnt += value;
break;
default:
if(index > 2){
threadStatusList[index - 3] += value;
}
break;
}
} else {
token.nextElement();
}
index++;
}
}
buffer.append("<TR>");
buffer.append("<TD align='center'>").append(size).append(" Average (Sum)</TD>");
buffer.append("<TD align='right'>").append((workerCnt / size)).append(" (").append(NumberUtils.intToString(workerCnt)).append(")</TD>");
buffer.append("<TD align='right'>").append((workingCnt / size)).append(" (").append(NumberUtils.intToString(workingCnt)).append(")</TD>");
for(int i= 0; i < statusCnt; i++){
buffer.append("<TD align='right'>").append((threadStatusList[i] / size)).append(" (").append(NumberUtils.intToString(threadStatusList[i])).append(")</TD>");
}
buffer.append("</TR>");
} else {
StringTokenizer token = null;
int index;
for ( int i = 0; i < size; i++ ) {
token = new StringTokenizer(list.get(i), "\t");
buffer.append("<TR>");
index = 0;
while ( token.hasMoreElements() ) {
if ( index == 0 ) {
buffer.append("<TD align='center'>");
} else {
buffer.append("<TD align='right'>");
}
buffer.append(token.nextElement());
buffer.append("</TD>");
index++;
}
buffer.append("</TR>");
}
}
buffer.append("</TABLE>");
buffer.append(getMainBodyEnd());
return buffer.toString();
}
static public String getDefaultBody() {
StringBuilder buffer = new StringBuilder(102400);
buffer.append(getMainBodyStart());
buffer.append(getCurrentConfigurationBody());
buffer.append(getMainBodyEnd());
return buffer.toString();
}
static public String getCurrentConfigurationBody(){
String fileName = PreferenceManager.get().getCurrentParserConfig();
StringBuilder buffer = new StringBuilder(100);
buffer.append("Current parser configuration filename : ");
if(fileName != null){
buffer.append(fileName);
}
return buffer.toString();
}
static public String filterThreadStack( String filename, String filter, ArrayList<String> excludeStackList, int stackStartLine ) {
if ( filename == null )
return "";
StringBuilder buffer = new StringBuilder(1024000);
buffer.append(getMainBodyStart());
buffer.append("<b>[ View thread stack ]</b><BR>");
buffer.append("Filter : ").append(filter).append("<BR>");
buffer.append("<pre><font size=3>");
BufferedReader reader = null;
int totalLineCount = 0;
try {
File file = new File(filename);
reader = new BufferedReader(new FileReader(file));
String line = null;
boolean isFiltered = false;
ArrayList<String> list = new ArrayList<String>(300);
while ( (line = reader.readLine()) != null ) {
if ( line.length() == 0 ) {
if ( isFiltered && list.size() > stackStartLine ) {
totalLineCount += printStack(list, buffer, excludeStackList);
}
list = new ArrayList<String>(300);
isFiltered = false;
if ( totalLineCount >= HTML_MAX_LINES )
break;
} else {
if ( !isFiltered ) {
if ( filter == null ) {
isFiltered = true;
} else if ( line.indexOf(filter) >= 0 ) {
isFiltered = true;
}
}
list.add(line);
}
}
if ( isFiltered && list.size() > stackStartLine ) {
totalLineCount += printStack(list, buffer, excludeStackList);
}
} catch ( Exception ex ) {
throw new RuntimeException(ex);
} finally {
if ( reader != null ) {
try {
reader.close();
} catch ( Exception e ) {
}
}
}
buffer.append("</font></pre>");
buffer.append("Total : ").append(NumberUtils.intToString(totalLineCount)).append(" lines <BR>");
buffer.append(getMainBodyEnd());
return buffer.toString();
}
static private int printStack( ArrayList<String> list, StringBuilder buffer, ArrayList<String> excludeStackList ) {
int i;
int size = list.size();
if ( excludeStackList == null ) {
for ( i = 0; i < size; i++ ) {
buffer.append(list.get(i)).append('\n');
}
buffer.append('\n');
return size + 1;
} else {
int lines = 0;
String line;
for ( i = 0; i < size; i++ ) {
line = list.get(i);
if ( !StringUtils.checkExist(line, excludeStackList) ) {
buffer.append(line).append('\n');
lines++;
}
}
buffer.append('\n');
return lines + 1;
}
}
static public String filterServiceCall( String filename, String filter, ArrayList<String> serviceList, int stackStartLine ) {
if ( filename == null )
return "";
BufferedReader reader = null;
String serviceCall = null;
int totalServiceCount = 0;
HashMap<String, Integer> map = new HashMap<String, Integer>();
try {
File file = new File(filename);
reader = new BufferedReader(new FileReader(file));
String line = null;
boolean isFiltered = false;
int lineCount = 0;
while ( (line = reader.readLine()) != null ) {
if ( line.length() == 0 ) {
if ( isFiltered && lineCount > stackStartLine ) {
totalServiceCount++;
caculCounter(serviceCall, map);
}
isFiltered = false;
serviceCall = null;
lineCount = 0;
} else {
if ( !isFiltered ) {
if ( filter == null ) {
isFiltered = true;
} else if ( line.indexOf(filter) >= 0 ) {
isFiltered = true;
}
}
if ( lineCount == stackStartLine || StringUtils.checkExist(line, serviceList) ) {
serviceCall = line;
}
lineCount++;
}
}
if ( isFiltered && lineCount > stackStartLine ) {
totalServiceCount++;
caculCounter(serviceCall, map);
}
} catch ( Exception ex ) {
throw new RuntimeException(ex);
} finally {
if ( reader != null ) {
try {
reader.close();
} catch ( Exception e ) {
}
}
}
StringBuilder buffer = new StringBuilder(10240);
buffer.append(getMainBodyStart());
buffer.append("<b>[ View service call ]</b><BR>");
buffer.append("Filter : ").append(filter).append("<BR>");
buffer.append("Total count : ").append(NumberUtils.intToString(totalServiceCount)).append("<BR><BR>");
if ( totalServiceCount == 0 ) {
buffer.append(getMainBodyEnd());
return buffer.toString();
}
buffer.append("<TABLE border='1'>");
buffer.append("<TR><TH align='center'>Count</TH><TH align='center'>Percent</TH><TH align='center'>Service name</TH></TR>");
ArrayList<ValueObject> list = sortCounter(map);
ValueObject object = null;
int value = 0;
for ( int i = 0; i < list.size(); i++ ) {
object = list.get(i);
value = object.getValue();
buffer.append("<TR>");
buffer.append("<TD align='right'>").append(NumberUtils.intToString(value)).append("</TD>");
buffer.append("<TD align='right'>").append(NumberUtils.intToPercent((10000 * value) / totalServiceCount)).append("%</TD>");
buffer.append("<TD align='left'>").append(object.getKey()).append("</TD>");
buffer.append("</TR>");
}
buffer.append("</TABLE>");
buffer.append(getMainBodyEnd());
return buffer.toString();
}
static public void caculCounter( String name, HashMap<String, Integer> map ) {
String key = StringUtils.makeSimpleLine(name, false);
Integer value = map.get(key);
if ( value == null ) {
value = new Integer(1);
} else {
value = new Integer(value.intValue() + 1);
}
map.put(key, value);
}
static public ArrayList<ValueObject> sortCounter(HashMap<String, Integer> map){
String key = null;
Integer value = null;
Iterator<String> itor = map.keySet().iterator();
ArrayList<ValueObject> list = new ArrayList<ValueObject>();
ValueObject object = null;
while ( itor.hasNext() ) {
key = itor.next();
value = map.get(key);
object = new ValueObject(key, value.intValue());
list.add(object);
}
Collections.sort(list, new ValueObjectComp());
return list;
}
static public String getUniqueStack(ArrayList<String> list){
if ( list == null )
return "";
StringBuilder buffer = new StringBuilder(1024000);
buffer.append(getMainBodyStart());
buffer.append("<b>[ Unique Stack ]</b><BR>");
buffer.append("<pre><font size=3>");
for(String stack : list){
buffer.append(stack).append("\n");
}
buffer.append("</font></pre>");
buffer.append(getMainBodyEnd());
return buffer.toString();
}
}