Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
/**
* Created by doki on 22.10.16.
*/
public class ActionDoneParser
{
public class ActionDoneParser implements IDataParser{
private static Set<String> EXCLUDED_ACTIONS = new HashSet<>();

static
Expand Down
95 changes: 36 additions & 59 deletions src/main/java/ru/naumen/sd40/log/parser/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

import org.springframework.web.multipart.MultipartFile;
import ru.naumen.perfhouse.influx.InfluxDAO;
import ru.naumen.sd40.log.parser.GCParser.GCTimeParser;

/**
* Created by doki on 22.10.16.
Expand All @@ -36,97 +35,75 @@ public static void parse(MultipartFile logs, String nameInfluxDB, String timeZon
BatchPoints points = influxDAO.startBatchPoints(influxDb);
HashMap<Long, DataSet> data = new HashMap<>();

TimeParser timeParser = new TimeParser(timeZone);
GCTimeParser gcTime = new GCTimeParser(timeZone);

switch (parseMode)
{
IDataParser parser;
ITimeParser timeParser;
switch (parseMode){
case "sdng":
//Parse sdng
try (BufferedReader br = new BufferedReader(new InputStreamReader(logs.getInputStream())))
{
String line;
while ((line = br.readLine()) != null)
{
long time = timeParser.parseLine(line);

if (time == 0)
{
continue;
}

int min5 = 5 * 60 * 1000;
long count = time / min5;
long key = count * min5;

data.computeIfAbsent(key, k -> new DataSet()).parseLine(line);
}
}
parser = new SDNGParser();
timeParser = new SDNGTimeParser();
break;
case "gc":
//Parse gc log
try (BufferedReader br = new BufferedReader(new InputStreamReader(logs.getInputStream())))
{
String line;
while ((line = br.readLine()) != null)
{
long time = gcTime.parseTime(line);

if (time == 0)
{
continue;
}

int min5 = 5 * 60 * 1000;
long count = time / min5;
long key = count * min5;
data.computeIfAbsent(key, k -> new DataSet()).parseGcLine(line);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

раньше в каждом режиме (внутри каждого блока case) был вызов соответствующего данному режиму метода
parseGcLine для GC
parseLine для sdng

TopParser содержал этот цикл внутри себя.

Нужно убрать эти методы из DataSet (они всего лишь переадресуют вызов в соответствующий парсер) и прямо здесь вызывать конкретный парсер. Как вы его получите - это уже зависит от вашего решения.

Также задача была "убрать дублирование". Имелся в виду в основном цикл while, который обходит все строки файла. Он есть здесь два раза, он есть в TopParser. В конце должен остаться только один.

}
}
parser = new GCParser();
timeParser = new GCTimeParser();
break;
case "top":
TopParser topParser = new TopParser(logs, data);
topParser.configureTimeZone(timeZone);
//Parse top
topParser.parse();
//Parse top
parser = new TopParser();
timeParser = new TopTimeParser(logs, data, timeZone);

break;
default:
throw new IllegalArgumentException(
"Unknown parse mode! Availiable modes: sdng, gc, top. Requested mode: " + parseMode);
}
parse(data, timeZone, logs, parser, timeParser);

if (traceCheck)
{
if (traceCheck){
System.out.print("Timestamp;Actions;Min;Mean;Stddev;50%%;95%%;99%%;99.9%%;Max;Errors\n");
}
data.forEach((k, set) ->
{
data.forEach((k, set) ->{
ActionDoneParser dones = set.getActionsDone();
dones.calculate();
ErrorParser erros = set.getErrors();
if (traceCheck)
{
if (traceCheck){
System.out.print(String.format("%d;%d;%f;%f;%f;%f;%f;%f;%f;%f;%d\n", k, dones.getCount(),
dones.getMin(), dones.getMean(), dones.getStddev(), dones.getPercent50(), dones.getPercent95(),
dones.getPercent99(), dones.getPercent999(), dones.getMax(), erros.getErrorCount()));
}
if (!dones.isNan())
{
if (!dones.isNan()){
influxDAO.storeActionsFromLog(points, influxDb, k, dones, erros);
}

GCParser gc = set.getGc();
if (!gc.isNan())
{
if (!gc.isNan()){
influxDAO.storeGc(points, influxDb, k, gc);
}

TopData cpuData = set.cpuData();
if (!cpuData.isNan())
{
if (!cpuData.isNan()){
influxDAO.storeTop(points, influxDb, k, cpuData);
}
});
influxDAO.writeBatch(points);
}

private static void parse(HashMap<Long, DataSet> data, String timeZone,
MultipartFile logs, IDataParser dataParser, ITimeParser timeParser)
throws ParseException, IOException {
try (BufferedReader br = new BufferedReader(new InputStreamReader(logs.getInputStream()))){
String line;
while ((line = br.readLine()) != null){
long time = timeParser.parseTime(line);

if (time == 0){
continue;
}

data.computeIfAbsent(time, k -> new DataSet());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тут создается новый dataset, но никак не используется. Надо присвоить это значение в переменную, а переменную передать в метод следующей строки - parseLine. Измените сигнатуру у parseLine в DataParser, чтобы он принимал строку и текущий dataset. Тогда не будет проблем с пустым currentSet во всех парсерах

dataParser.parseLine(line);
}
}
}
}
26 changes: 5 additions & 21 deletions src/main/java/ru/naumen/sd40/log/parser/DataSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,25 @@ public class DataSet
private GCParser gc;
private TopData cpuData = new TopData();

public DataSet()
{
public DataSet(){
actionsDone = new ActionDoneParser();
errors = new ErrorParser();
gc = new GCParser();
}

public void parseLine(String line)
{
errors.parseLine(line);
actionsDone.parseLine(line);
}

public void parseGcLine(String line)
{
gc.parseLine(line);
}

public ActionDoneParser getActionsDone()
{
public ActionDoneParser getActionsDone(){
return actionsDone;
}

public ErrorParser getErrors()
{
public ErrorParser getErrors(){
return errors;
}

public GCParser getGc()
{
public GCParser getGc(){
return gc;
}

public TopData cpuData()
{
public TopData cpuData(){
return cpuData;
}
}
5 changes: 2 additions & 3 deletions src/main/java/ru/naumen/sd40/log/parser/ErrorParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
/**
* Created by doki on 22.10.16.
*/
public class ErrorParser
{
public class ErrorParser implements IDataParser{
long warnCount;
long errorCount;
long fatalCount;
Expand All @@ -15,7 +14,7 @@ public class ErrorParser
Pattern errorRegEx = Pattern.compile("^\\d+ \\[.+?\\] \\(.+?\\) ERROR");
Pattern fatalRegEx = Pattern.compile("^\\d+ \\[.+?\\] \\(.+?\\) FATAL");

void parseLine(String line)
public void parseLine(String line)
{
if (warnRegEx.matcher(line).find())
{
Expand Down
55 changes: 7 additions & 48 deletions src/main/java/ru/naumen/sd40/log/parser/GCParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,77 +3,36 @@
import static ru.naumen.sd40.log.parser.NumberUtils.getSafeDouble;
import static ru.naumen.sd40.log.parser.NumberUtils.roundToTwoPlaces;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;

public class GCParser
{
public final static class GCTimeParser
{
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ",
new Locale("ru", "RU"));

private static final Pattern PATTERN = Pattern
.compile("^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{3}\\+\\d{4}).*");

public GCTimeParser()
{
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
}

public GCTimeParser(String timeZone)
{
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone(timeZone));
}

public long parseTime(String line) throws ParseException
{
Matcher matcher = PATTERN.matcher(line);
if (matcher.find())
{
Date parse = DATE_FORMAT.parse(matcher.group(1));
return parse.getTime();
}
return 0L;
}
}
public class GCParser implements IDataParser{

private DescriptiveStatistics ds = new DescriptiveStatistics();

private Pattern gcExecutionTime = Pattern.compile(".*real=(.*)secs.*");

public double getCalculatedAvg()
{
public double getCalculatedAvg(){
return roundToTwoPlaces(getSafeDouble(ds.getMean()));
}

public long getGcTimes()
{
public long getGcTimes() {
return ds.getN();
}

public double getMaxGcTime()
{
public double getMaxGcTime(){
return roundToTwoPlaces(getSafeDouble(ds.getMax()));
}

public boolean isNan()
{
public boolean isNan(){
return getGcTimes() == 0;
}

public void parseLine(String line)
{
public void parseLine(String line){
Matcher matcher = gcExecutionTime.matcher(line);
if (matcher.find())
{
if (matcher.find()){
ds.addValue(Double.parseDouble(matcher.group(1).trim().replace(',', '.')));
}
}
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/ru/naumen/sd40/log/parser/GCTimeParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package ru.naumen.sd40.log.parser;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class GCTimeParser implements ITimeParser{
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ",
new Locale("ru", "RU"));

private static final Pattern PATTERN = Pattern
.compile("^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{3}\\+\\d{4}).*");

public GCTimeParser(){
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
}

public GCTimeParser(String timeZone){
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone(timeZone));
}

public long parseTime(String line) throws ParseException{
Matcher matcher = PATTERN.matcher(line);
if (matcher.find()){
Date parse = DATE_FORMAT.parse(matcher.group(1));
return parse.getTime();
}
return 0L;
}
}
7 changes: 7 additions & 0 deletions src/main/java/ru/naumen/sd40/log/parser/IDataParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.naumen.sd40.log.parser;

import java.text.ParseException;

public interface IDataParser {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ActionDoneParser, ErrorParser, GCParser, TopParser - все они должны реализовывать этот интерфейс

public void parseLine(String line) throws ParseException;
}
7 changes: 7 additions & 0 deletions src/main/java/ru/naumen/sd40/log/parser/ITimeParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.naumen.sd40.log.parser;

import java.text.ParseException;

public interface ITimeParser {
public long parseTime(String line) throws ParseException;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCTimeParser, TimeParser, а также у TopParser должен появиться свой парсер для времени - они должны реализовывать этот интерфейс

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Имеется в виду, что каждый из них(GCTimeParser, TimeParser, TopParser) будет должен реализовать интерфейс ITimeParser, или что будут существовать другие классы-парсеры?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Есть еще мысль сделать по аналогии с GCParser (где существует подкласс GCTimeParser) или наоборот, избавиться от этого подкласса...

}
17 changes: 17 additions & 0 deletions src/main/java/ru/naumen/sd40/log/parser/SDNGParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ru.naumen.sd40.log.parser;


/**
* Created by doki on 22.10.16.
*/
public class SDNGParser implements IDataParser{

private DataSet currentSet;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currentSet всегда null?


public void parseLine(String line){
ErrorParser errors = currentSet.getErrors();
ActionDoneParser actionsDone = currentSet.getActionsDone();
errors.parseLine(line);
actionsDone.parseLine(line);
}
}
Loading