Added code for http log analyze.
This commit is contained in:
parent
a1f9dbabf9
commit
029a9f563d
16 changed files with 1736 additions and 276 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
|
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
*
|
*
|
||||||
* This file is part of StatoolInfos, simple service statistics tool.
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
*
|
*
|
||||||
|
@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import fr.devinsy.statoolinfos.crawl.CrawlCache;
|
import fr.devinsy.statoolinfos.crawl.CrawlCache;
|
||||||
import fr.devinsy.statoolinfos.properties.PathProperties;
|
import fr.devinsy.statoolinfos.properties.PathProperties;
|
||||||
import fr.devinsy.statoolinfos.properties.PathPropertyList;
|
import fr.devinsy.statoolinfos.properties.PathPropertyList;
|
||||||
|
import fr.devinsy.strings.StringList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Class PathProperty.
|
* The Class PathProperty.
|
||||||
|
@ -346,6 +347,80 @@ public class Configuration extends PathPropertyList
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the probe http access log file.
|
||||||
|
*
|
||||||
|
* @return the probe http access log file
|
||||||
|
*/
|
||||||
|
public String getProbeHttpAccessLogSource()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = get("conf.probe.httpaccesslog.file");
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the probe http error log source.
|
||||||
|
*
|
||||||
|
* @return the probe http error log source
|
||||||
|
*/
|
||||||
|
public String getProbeHttpErrorLogSource()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = get("conf.probe.httperrorlog.file");
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the probe target.
|
||||||
|
*
|
||||||
|
* @return the probe target
|
||||||
|
*/
|
||||||
|
public File getProbeTarget()
|
||||||
|
{
|
||||||
|
File result;
|
||||||
|
|
||||||
|
String filename = get("conf.probe.target");
|
||||||
|
if (StringUtils.isBlank(filename))
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = new File(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the probe types.
|
||||||
|
*
|
||||||
|
* @return the probe types
|
||||||
|
*/
|
||||||
|
public StringList getProbeTypes()
|
||||||
|
{
|
||||||
|
StringList result;
|
||||||
|
|
||||||
|
result = new StringList();
|
||||||
|
|
||||||
|
String types = get("conf.probe.types");
|
||||||
|
if (!StringUtils.isBlank(types))
|
||||||
|
{
|
||||||
|
result.append(types.split("[, ;]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for valid cache.
|
* Checks for valid cache.
|
||||||
*
|
*
|
||||||
|
|
|
@ -18,18 +18,14 @@
|
||||||
*/
|
*/
|
||||||
package fr.devinsy.statoolinfos.htmlize.probes;
|
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -45,62 +41,42 @@ public class HttpAccessLogAnalyzer
|
||||||
|
|
||||||
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
|
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
|
||||||
|
|
||||||
|
private int errorCount;
|
||||||
|
private PathCounters counters;
|
||||||
|
private VisitCounters visits;
|
||||||
|
private IpCounters ips;
|
||||||
|
private IpCounters ipv4;
|
||||||
|
private IpCounters ipv6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new http access log prober.
|
* Instantiates a new http access log prober.
|
||||||
*/
|
*/
|
||||||
private HttpAccessLogAnalyzer()
|
public HttpAccessLogAnalyzer()
|
||||||
{
|
{
|
||||||
|
this.counters = new PathCounters();
|
||||||
|
this.visits = new VisitCounters();
|
||||||
|
this.ips = new IpCounters();
|
||||||
|
this.ipv4 = new IpCounters();
|
||||||
|
this.ipv6 = new IpCounters();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the log.
|
* Gets the counters.
|
||||||
*
|
*
|
||||||
* @param line
|
* @return the counters
|
||||||
* the line
|
|
||||||
* @return the http log
|
|
||||||
*/
|
*/
|
||||||
public static HttpLog parseLog(final String line)
|
public PathCounters getCounters()
|
||||||
{
|
{
|
||||||
HttpLog result;
|
PathCounters result;
|
||||||
|
|
||||||
//
|
result = new PathCounters();
|
||||||
// log_format combined '$remote_addr - $remote_user [$time_local] '
|
result.putAll(this.counters);
|
||||||
// '"$request" $status $body_bytes_sent '
|
|
||||||
// '"$http_referer" "$http_user_agent"';
|
|
||||||
String remoteAddressPattern = "(?<remoteAddress>[a-zA-F0-9\\\\:\\\\.]+)";
|
|
||||||
String remoteUserPattern = "(?<remoteUser>\\S+)";
|
|
||||||
String timePattern = "(?<time>[^\\]]+)";
|
|
||||||
String requestPattern = "(?<request>[^\"]*)";
|
|
||||||
String statusPattern = "(?<status>\\d+)";
|
|
||||||
String bodyBytesSentPattern = "(?<bodyBytesSent>\\d+)";
|
|
||||||
String refererPattern = "(?<referer>[^\"]*)";
|
|
||||||
String httpUserAgentPattern = "(?<httpUserAgent>[^\"]*)";
|
|
||||||
|
|
||||||
String combinedPattern = String.format("^%s - %s \\[%s\\] \"%s\" %s %s \"%s\" \"%s\".*$",
|
result.putAll(this.ips.getCounters("metrics.http.ip"));
|
||||||
remoteAddressPattern, remoteUserPattern, timePattern, requestPattern, statusPattern, bodyBytesSentPattern,
|
result.putAll(this.ipv4.getCounters("metrics.http.ip.ipv4"));
|
||||||
refererPattern, httpUserAgentPattern);
|
result.putAll(this.ipv6.getCounters("metrics.http.ip.ipv6"));
|
||||||
|
|
||||||
// logger.info("pattern=[{}]", combinedPattern);
|
result.putAll(this.visits.getCounters("metrics.http.visits"));
|
||||||
|
|
||||||
Pattern combined = Pattern.compile(combinedPattern);
|
|
||||||
|
|
||||||
Matcher matcher = combined.matcher(line);
|
|
||||||
if (matcher.matches())
|
|
||||||
{
|
|
||||||
result = new HttpLog();
|
|
||||||
result.setRemoteAddress(matcher.group("remoteAddress"));
|
|
||||||
result.setRemoteUser(matcher.group("remoteUser"));
|
|
||||||
result.setTime(LocalDateTime.parse(matcher.group("time"), DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss Z").withLocale(Locale.ENGLISH)));
|
|
||||||
result.setRequest(matcher.group("request"));
|
|
||||||
result.setStatus(HttpStatusTable.instance().get(matcher.group("status")));
|
|
||||||
result.setBodyBytesSent(Long.valueOf(matcher.group("bodyBytesSent")));
|
|
||||||
result.setReferer(matcher.group("referer"));
|
|
||||||
result.setHttpUserAgent(new UserAgent(matcher.group("httpUserAgent")));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
|
@ -109,87 +85,32 @@ public class HttpAccessLogAnalyzer
|
||||||
/**
|
/**
|
||||||
* Probe.
|
* Probe.
|
||||||
*
|
*
|
||||||
* @param source
|
* @param file
|
||||||
* the source
|
* the file
|
||||||
* @param target
|
|
||||||
* the target
|
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* Signals that an I/O exception has occurred.
|
* Signals that an I/O exception has occurred.
|
||||||
* @throws StatoolInfosException
|
* @throws StatoolInfosException
|
||||||
* the statool infos exception
|
* the statool infos exception
|
||||||
*/
|
*/
|
||||||
public static PathCounters probe(final File source, final File target) throws IOException, StatoolInfosException
|
public void probe(final File file) throws IOException
|
||||||
{
|
{
|
||||||
PathCounters result = new PathCounters();
|
LineIterator iterator = new LineIterator(file);
|
||||||
|
while (iterator.hasNext())
|
||||||
int errorCount = 0;
|
|
||||||
for (File file : source.getParentFile().listFiles())
|
|
||||||
{
|
{
|
||||||
// if (file.getName().startsWith(source.getName()))
|
String line = iterator.next();
|
||||||
if (file.getName().equals(source.getName()))
|
|
||||||
{
|
|
||||||
errorCount += probe(result, source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Probe.
|
|
||||||
*
|
|
||||||
* @param source
|
|
||||||
* the source
|
|
||||||
* @param counters
|
|
||||||
* the counters
|
|
||||||
* @throws IOException
|
|
||||||
* Signals that an I/O exception has occurred.
|
|
||||||
* @throws StatoolInfosException
|
|
||||||
* the statool infos exception
|
|
||||||
*/
|
|
||||||
public static int probe(final PathCounters counters, final File source) throws IOException, StatoolInfosException
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
BufferedReader in = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = 0;
|
probeLine(line);
|
||||||
in = new BufferedReader(new InputStreamReader(new FileInputStream(source), DEFAULT_CHARSET_NAME));
|
|
||||||
|
|
||||||
boolean ended = false;
|
|
||||||
while (!ended)
|
|
||||||
{
|
|
||||||
String line = in.readLine();
|
|
||||||
|
|
||||||
if (line == null)
|
|
||||||
{
|
|
||||||
ended = true;
|
|
||||||
}
|
|
||||||
else if (StringUtils.isNotEmpty(line))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
probe(counters, line);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
logger.warn("Error parsing line [{}][{}]", line, exception.getMessage());
|
||||||
exception.printStackTrace();
|
exception.printStackTrace();
|
||||||
result += 1;
|
this.errorCount += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IOUtils.closeQuietly(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Probe.
|
* Probe.
|
||||||
|
@ -199,9 +120,10 @@ public class HttpAccessLogAnalyzer
|
||||||
* @param line
|
* @param line
|
||||||
* the line
|
* the line
|
||||||
*/
|
*/
|
||||||
public static void probe(final PathCounters counters, final String line)
|
public void probeLine(final String line)
|
||||||
{
|
{
|
||||||
HttpLog log = parseLog(line);
|
|
||||||
|
HttpLog log = parseNginxCombinedLog(line);
|
||||||
|
|
||||||
// logger.info("==================");
|
// logger.info("==================");
|
||||||
if (log == null)
|
if (log == null)
|
||||||
|
@ -220,64 +142,174 @@ public class HttpAccessLogAnalyzer
|
||||||
String date = log.getDate();
|
String date = log.getDate();
|
||||||
|
|
||||||
// metrics.http.hits
|
// metrics.http.hits
|
||||||
counters.inc("metrics.http.hits", year, yearMonth, yearWeek, date);
|
this.counters.inc("metrics.http.hits", year, yearMonth, yearWeek, date);
|
||||||
|
|
||||||
if (log.isIPv4())
|
if (log.isIPv4())
|
||||||
{
|
{
|
||||||
counters.inc("metrics.http.hits.ipv4", year, yearMonth, yearWeek, date);
|
this.counters.inc("metrics.http.hits.ipv4", year, yearMonth, yearWeek, date);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
counters.inc("metrics.http.hits.ipv6", year, yearMonth, yearWeek, date);
|
this.counters.inc("metrics.http.hits.ipv6", year, yearMonth, yearWeek, date);
|
||||||
}
|
}
|
||||||
|
|
||||||
// metrics.http.files
|
// metrics.http.files
|
||||||
if (log.getBodyBytesSent() != 0)
|
if (log.getBodyBytesSent() != 0)
|
||||||
{
|
{
|
||||||
counters.inc("metrics.http.file", year, yearMonth, yearWeek, date);
|
this.counters.inc("metrics.http.file", year, yearMonth, yearWeek, date);
|
||||||
}
|
}
|
||||||
|
|
||||||
// metrics.http.bytes
|
// metrics.http.bytes
|
||||||
counters.inc(log.getBodyBytesSent(), "metrics.http.bytes", year, yearMonth, yearWeek, date);
|
this.counters.inc(log.getBodyBytesSent(), "metrics.http.bytes", year, yearMonth, yearWeek, date);
|
||||||
|
|
||||||
// metrics.http.hits.bots.* =
|
// metrics.http.hits.bots.* =
|
||||||
if (log.isBot())
|
if (log.isBot())
|
||||||
{
|
{
|
||||||
counters.inc("metrics.http.hits.bots", year, yearMonth, yearWeek, date);
|
this.counters.inc("metrics.http.hits.bots", year, yearMonth, yearWeek, date);
|
||||||
}
|
}
|
||||||
|
|
||||||
// metrics.http.pages.* =
|
// metrics.http.pages.* =
|
||||||
if (StringUtils.endsWithAny(log.getRequest(), ".html", ".htm", ".xhtml", ".cgi"))
|
if (StringUtils.endsWithAny(log.getRequest(), ".html", ".htm", ".xhtml", ".cgi"))
|
||||||
{
|
{
|
||||||
counters.inc("metrics.http.pages", year, yearMonth, yearWeek, date);
|
this.counters.inc("metrics.http.pages", year, yearMonth, yearWeek, date);
|
||||||
}
|
}
|
||||||
|
|
||||||
// metrics.http.status.XXX
|
// metrics.http.status.XXX
|
||||||
String status = String.valueOf(log.getStatus().getCode());
|
String status = String.valueOf(log.getStatus().getCode());
|
||||||
counters.inc("metrics.http.status." + status, year, yearMonth, yearWeek, date);
|
this.counters.inc("metrics.http.status." + status, year, yearMonth, yearWeek, date);
|
||||||
|
|
||||||
// metrics.http.os.XXXXX
|
// metrics.http.os.XXXXX
|
||||||
UserAgentOS os = log.getHttpUserAgent().getOS();
|
UserAgentOS os = log.getUserAgent().getOS();
|
||||||
counters.inc("metrics.http.browsers." + os.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
this.counters.inc("metrics.http.browsers." + os.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
||||||
|
|
||||||
// metrics.http.browsers.XXXXX
|
// metrics.http.browsers.XXXXX
|
||||||
UserAgentBrowser browser = log.getHttpUserAgent().getBrowser();
|
UserAgentBrowser browser = log.getUserAgent().getBrowser();
|
||||||
counters.inc("metrics.http.browsers." + browser.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
this.counters.inc("metrics.http.browsers." + browser.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
||||||
|
|
||||||
// metrics.http.devices.XXXXX =
|
// metrics.http.devices.XXXXX =
|
||||||
UserAgentDevice device = log.getHttpUserAgent().getDevice();
|
UserAgentDevice device = log.getUserAgent().getDevice();
|
||||||
counters.inc("metrics.http.devices." + device.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
this.counters.inc("metrics.http.devices." + device.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
||||||
|
|
||||||
// metrics.http.countries.XX =
|
|
||||||
|
|
||||||
// metrics.http.ip.* =
|
// metrics.http.ip.* =
|
||||||
// metrics.http.ip.ipv4.* =
|
// metrics.http.ip.ipv4.* =
|
||||||
// metrics.http.ip.ipv6.* =
|
// metrics.http.ip.ipv6.* =
|
||||||
|
this.ips.put(log.getRemoteAddress(), year, yearMonth, yearWeek, date);
|
||||||
|
if (log.isIPv4())
|
||||||
|
{
|
||||||
|
this.ipv4.put(log.getRemoteAddress(), year, yearMonth, yearWeek, date);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.ipv6.put(log.getRemoteAddress(), year, yearMonth, yearWeek, date);
|
||||||
|
}
|
||||||
|
|
||||||
// metrics.http.visits.* =
|
// metrics.http.visits.* =
|
||||||
|
this.visits.putVisit(log);
|
||||||
|
this.visits.storeTimeMarks(year, yearMonth, yearWeek, date);
|
||||||
|
|
||||||
|
// metrics.http.countries.XX =
|
||||||
|
|
||||||
// metrics.http.errors.* =
|
// metrics.http.errors.* =
|
||||||
// metrics.http.errors.php.* =
|
// metrics.http.errors.php.* =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the log.
|
||||||
|
*
|
||||||
|
* @param line
|
||||||
|
* the line
|
||||||
|
* @return the http log
|
||||||
|
*/
|
||||||
|
public static HttpLog parseNginxCombinedLog(final String line)
|
||||||
|
{
|
||||||
|
HttpLog result;
|
||||||
|
|
||||||
|
// log_format combined '$remote_addr - $remote_user [$time_local] '
|
||||||
|
// '"$request" $status $body_bytes_sent '
|
||||||
|
// '"$http_referer" "$http_user_agent"';
|
||||||
|
String combinedPattern = "^(?<remoteAddress>[a-zA-F0-9\\\\:\\\\.]+) - (?<remoteUser>\\S+) \\[(?<time>[^\\]]+)\\] \"(?<request>[^\"]*)\" (?<status>\\d+) (?<bodyBytesSent>\\d+) \"(?<referer>[^\"]*)\" \"(?<userAgent>[^\"]*)\".*$";
|
||||||
|
|
||||||
|
result = parseLog(line, combinedPattern);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the log.
|
||||||
|
*
|
||||||
|
* @param line
|
||||||
|
* the line
|
||||||
|
* @return the http log
|
||||||
|
*/
|
||||||
|
public static HttpLog parseLog(final String line, final String pattern)
|
||||||
|
{
|
||||||
|
HttpLog result;
|
||||||
|
|
||||||
|
Pattern combined = Pattern.compile(pattern);
|
||||||
|
|
||||||
|
Matcher matcher = combined.matcher(line);
|
||||||
|
if (matcher.matches())
|
||||||
|
{
|
||||||
|
result = new HttpLog();
|
||||||
|
result.setRemoteAddress(matcher.group("remoteAddress"));
|
||||||
|
result.setRemoteUser(matcher.group("remoteUser"));
|
||||||
|
result.setTime(LocalDateTime.parse(matcher.group("time"), DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss Z").withLocale(Locale.ENGLISH)));
|
||||||
|
result.setRequest(matcher.group("request"));
|
||||||
|
result.setStatus(HttpStatusTable.instance().get(matcher.group("status")));
|
||||||
|
result.setBodyBytesSent(Long.valueOf(matcher.group("bodyBytesSent")));
|
||||||
|
result.setReferer(matcher.group("referer"));
|
||||||
|
result.setUserAgent(new UserAgent(matcher.group("userAgent")));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probe.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @throws IOException
|
||||||
|
* Signals that an I/O exception has occurred.
|
||||||
|
* @throws StatoolInfosException
|
||||||
|
* the statool infos exception
|
||||||
|
*/
|
||||||
|
public static PathCounters probe(final String source) throws IOException, StatoolInfosException
|
||||||
|
{
|
||||||
|
PathCounters result;
|
||||||
|
|
||||||
|
HttpAccessLogAnalyzer analyzer = new HttpAccessLogAnalyzer();
|
||||||
|
|
||||||
|
if (!StringUtils.isBlank(source))
|
||||||
|
{
|
||||||
|
if (source.endsWith("*"))
|
||||||
|
{
|
||||||
|
for (File file : new File(source).getParentFile().listFiles())
|
||||||
|
{
|
||||||
|
// if (file.getName().startsWith(source.getName()))
|
||||||
|
if (file.getName().equals(source))
|
||||||
|
{
|
||||||
|
analyzer.probe(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File file = new File(source);
|
||||||
|
analyzer.probe(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = analyzer.getCounters();
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org>
|
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
*
|
*
|
||||||
* This file is part of StatoolInfos, simple service statistics tool.
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
*
|
*
|
||||||
|
@ -18,16 +18,12 @@
|
||||||
*/
|
*/
|
||||||
package fr.devinsy.statoolinfos.htmlize.probes;
|
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -35,87 +31,69 @@ import org.slf4j.LoggerFactory;
|
||||||
import fr.devinsy.statoolinfos.core.StatoolInfosException;
|
import fr.devinsy.statoolinfos.core.StatoolInfosException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Class HttpErrorLogProber.
|
* The Class HttpErrorLogAnalyzer.
|
||||||
*/
|
*/
|
||||||
public class HttpErrorLogProber
|
public class HttpErrorLogAnalyzer
|
||||||
{
|
{
|
||||||
private static Logger logger = LoggerFactory.getLogger(HttpErrorLogProber.class);
|
private static Logger logger = LoggerFactory.getLogger(HttpErrorLogAnalyzer.class);
|
||||||
|
|
||||||
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
|
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
|
||||||
|
|
||||||
|
private PathCounters counters;
|
||||||
|
private int errorCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new http error log prober.
|
* Instantiates a new http error log analyzer.
|
||||||
*/
|
*/
|
||||||
private HttpErrorLogProber()
|
public HttpErrorLogAnalyzer()
|
||||||
{
|
{
|
||||||
|
this.counters = new PathCounters();
|
||||||
|
this.errorCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the counters.
|
||||||
|
*
|
||||||
|
* @return the counters
|
||||||
|
*/
|
||||||
|
public PathCounters getCounters()
|
||||||
|
{
|
||||||
|
PathCounters result;
|
||||||
|
|
||||||
|
result = new PathCounters();
|
||||||
|
result.putAll(this.counters);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Probe.
|
* Probe.
|
||||||
*
|
*
|
||||||
* @param source
|
* @param file
|
||||||
* the source
|
* the file
|
||||||
* @param target
|
|
||||||
* the target
|
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* Signals that an I/O exception has occurred.
|
* Signals that an I/O exception has occurred.
|
||||||
* @throws StatoolInfosException
|
|
||||||
* the statool infos exception
|
|
||||||
*/
|
*/
|
||||||
public static void probe(final File source, final File target) throws IOException, StatoolInfosException
|
public void probe(final File file) throws IOException
|
||||||
{
|
{
|
||||||
PathCounters counters;
|
LineIterator iterator = new LineIterator(file);
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
String line = iterator.next();
|
||||||
|
|
||||||
counters = new PathCounters();
|
|
||||||
|
|
||||||
for (File file : source.getParentFile().listFiles())
|
|
||||||
{
|
|
||||||
if (file.getName().startsWith(source.getName()))
|
|
||||||
{
|
|
||||||
probe(counters, source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Probe.
|
|
||||||
*
|
|
||||||
* @param source
|
|
||||||
* the source
|
|
||||||
* @param counters
|
|
||||||
* the counters
|
|
||||||
* @throws IOException
|
|
||||||
* Signals that an I/O exception has occurred.
|
|
||||||
* @throws StatoolInfosException
|
|
||||||
* the statool infos exception
|
|
||||||
*/
|
|
||||||
public static void probe(final PathCounters counters, final File source) throws IOException, StatoolInfosException
|
|
||||||
{
|
|
||||||
BufferedReader in = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
in = new BufferedReader(new InputStreamReader(new FileInputStream(source), DEFAULT_CHARSET_NAME));
|
probeLine(line);
|
||||||
|
|
||||||
boolean ended = false;
|
|
||||||
while (!ended)
|
|
||||||
{
|
|
||||||
String line = in.readLine();
|
|
||||||
|
|
||||||
if (line == null)
|
|
||||||
{
|
|
||||||
ended = true;
|
|
||||||
}
|
}
|
||||||
else if (StringUtils.isNotEmpty(line))
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
probe(counters, line);
|
logger.warn("Error parsing line [{}][{}]", line, exception.getMessage());
|
||||||
|
exception.printStackTrace();
|
||||||
|
this.errorCount += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
IOUtils.closeQuietly(in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Probe.
|
* Probe.
|
||||||
|
@ -125,7 +103,7 @@ public class HttpErrorLogProber
|
||||||
* @param line
|
* @param line
|
||||||
* the line
|
* the line
|
||||||
*/
|
*/
|
||||||
public static void probe(final PathCounters counters, final String line)
|
public void probeLine(final String line)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
LocalDateTime date;
|
LocalDateTime date;
|
||||||
|
@ -137,18 +115,52 @@ public class HttpErrorLogProber
|
||||||
String week = date.format(DateTimeFormatter.ofPattern("yyyyWW", Locale.FRANCE));
|
String week = date.format(DateTimeFormatter.ofPattern("yyyyWW", Locale.FRANCE));
|
||||||
String day = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.FRANCE));
|
String day = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.FRANCE));
|
||||||
|
|
||||||
// General HTTP access logs.
|
|
||||||
|
|
||||||
// metrics.http.errors
|
// metrics.http.errors
|
||||||
counters.inc("metrics.http.errors", year);
|
this.counters.inc("metrics.http.errors", year, month, week, day);
|
||||||
counters.inc("metrics.http.errors", month);
|
|
||||||
counters.inc("metrics.http.errors", week);
|
|
||||||
counters.inc("metrics.http.errors", day);
|
|
||||||
|
|
||||||
// metrics.http.hits.ipv4
|
// metrics.http.errors.php
|
||||||
counters.inc("metrics.http.errors.php", year);
|
}
|
||||||
counters.inc("metrics.http.errors.php", month);
|
|
||||||
counters.inc("metrics.http.errors.php", week);
|
/**
|
||||||
counters.inc("metrics.http.errors.php", day);
|
* Probe.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @return the path counters
|
||||||
|
* @throws IOException
|
||||||
|
* Signals that an I/O exception has occurred.
|
||||||
|
* @throws StatoolInfosException
|
||||||
|
* the statool infos exception
|
||||||
|
*/
|
||||||
|
public static PathCounters probe(final String source) throws IOException, StatoolInfosException
|
||||||
|
{
|
||||||
|
PathCounters result;
|
||||||
|
|
||||||
|
HttpErrorLogAnalyzer analyzer = new HttpErrorLogAnalyzer();
|
||||||
|
|
||||||
|
if (!StringUtils.isBlank(source))
|
||||||
|
{
|
||||||
|
if (source.endsWith("*"))
|
||||||
|
{
|
||||||
|
for (File file : new File(source).getParentFile().listFiles())
|
||||||
|
{
|
||||||
|
// if (file.getName().startsWith(source.getName()))
|
||||||
|
if (file.getName().equals(source))
|
||||||
|
{
|
||||||
|
analyzer.probe(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File file = new File(source);
|
||||||
|
analyzer.probe(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = analyzer.getCounters();
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -46,7 +46,7 @@ public class HttpLog
|
||||||
private HttpStatus status;
|
private HttpStatus status;
|
||||||
private long bodyBytesSent;
|
private long bodyBytesSent;
|
||||||
private String referer;
|
private String referer;
|
||||||
private UserAgent httpUserAgent;
|
private UserAgent userAgent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new http log.
|
* Instantiates a new http log.
|
||||||
|
@ -60,7 +60,7 @@ public class HttpLog
|
||||||
this.status = null;
|
this.status = null;
|
||||||
this.bodyBytesSent = 0;
|
this.bodyBytesSent = 0;
|
||||||
this.referer = null;
|
this.referer = null;
|
||||||
this.httpUserAgent = null;
|
this.userAgent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getBodyBytesSent()
|
public long getBodyBytesSent()
|
||||||
|
@ -78,11 +78,6 @@ public class HttpLog
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserAgent getHttpUserAgent()
|
|
||||||
{
|
|
||||||
return this.httpUserAgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getReferer()
|
public String getReferer()
|
||||||
{
|
{
|
||||||
return this.referer;
|
return this.referer;
|
||||||
|
@ -113,6 +108,11 @@ public class HttpLog
|
||||||
return this.time;
|
return this.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserAgent getUserAgent()
|
||||||
|
{
|
||||||
|
return this.userAgent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the year.
|
* Gets the year.
|
||||||
*
|
*
|
||||||
|
@ -128,7 +128,7 @@ public class HttpLog
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = this.time.format(DateTimeFormatter.ofPattern("yyyy", Locale.FRANCE));
|
result = TimeMarkUtils.yearOf(this.time);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -150,7 +150,7 @@ public class HttpLog
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = this.time.format(DateTimeFormatter.ofPattern("yyyy-MM", Locale.FRANCE));
|
result = TimeMarkUtils.yearMonthOf(this.time);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
|
@ -170,8 +170,7 @@ public class HttpLog
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
result = TimeMarkUtils.yearWeekOf(this.time);
|
||||||
result = this.time.format(DateTimeFormatter.ofPattern("yyyy'W'ww", Locale.FRANCE));
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
|
@ -184,7 +183,7 @@ public class HttpLog
|
||||||
{
|
{
|
||||||
boolean result;
|
boolean result;
|
||||||
|
|
||||||
result = StringsUtils.containsAnyIgnoreCase(this.httpUserAgent.toString(), "bot", "monitoring");
|
result = StringsUtils.containsAnyIgnoreCase(this.userAgent.toString(), "bot", "monitoring");
|
||||||
|
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
|
@ -237,11 +236,6 @@ public class HttpLog
|
||||||
this.bodyBytesSent = bodyBytesSent;
|
this.bodyBytesSent = bodyBytesSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHttpUserAgent(final UserAgent httpUserAgent)
|
|
||||||
{
|
|
||||||
this.httpUserAgent = httpUserAgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReferer(final String referer)
|
public void setReferer(final String referer)
|
||||||
{
|
{
|
||||||
this.referer = referer;
|
this.referer = referer;
|
||||||
|
@ -272,6 +266,11 @@ public class HttpLog
|
||||||
this.time = time;
|
this.time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setUserAgent(final UserAgent userAgent)
|
||||||
|
{
|
||||||
|
this.userAgent = userAgent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To string.
|
* To string.
|
||||||
*
|
*
|
||||||
|
@ -291,7 +290,7 @@ public class HttpLog
|
||||||
buffer.append("[status=").append(this.status.getCode()).append("]");
|
buffer.append("[status=").append(this.status.getCode()).append("]");
|
||||||
buffer.append("[bodyBytesSent=").append(this.bodyBytesSent).append("]");
|
buffer.append("[bodyBytesSent=").append(this.bodyBytesSent).append("]");
|
||||||
buffer.append("[referer=").append(this.referer).append("]");
|
buffer.append("[referer=").append(this.referer).append("]");
|
||||||
buffer.append("[httpUserAgent=").append(this.httpUserAgent).append("]");
|
buffer.append("[userAgent=").append(this.userAgent).append("]");
|
||||||
|
|
||||||
result = buffer.toString();
|
result = buffer.toString();
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class HttpLogIterator
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String line = this.iterator.next();
|
String line = this.iterator.next();
|
||||||
result = HttpAccessLogAnalyzer.parseLog(line);
|
result = HttpAccessLogAnalyzer.parseNginxCombinedLog(line);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
|
116
src/fr/devinsy/statoolinfos/htmlize/probes/IpCounters.java
Normal file
116
src/fr/devinsy/statoolinfos/htmlize/probes/IpCounters.java
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import fr.devinsy.strings.StringSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class IpCounters.
|
||||||
|
*/
|
||||||
|
public class IpCounters extends HashMap<String, StringSet>
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -1597516678500117985L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new path counters.
|
||||||
|
*/
|
||||||
|
public IpCounters()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* the path
|
||||||
|
* @param timeMark
|
||||||
|
* the time mark
|
||||||
|
* @return the path counter
|
||||||
|
*/
|
||||||
|
public StringSet get(final String timeMark)
|
||||||
|
{
|
||||||
|
StringSet result;
|
||||||
|
|
||||||
|
result = super.get(timeMark);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the counters.
|
||||||
|
*
|
||||||
|
* @return the counters
|
||||||
|
*/
|
||||||
|
public PathCounters getCounters(final String prefix)
|
||||||
|
{
|
||||||
|
PathCounters result;
|
||||||
|
|
||||||
|
result = new PathCounters();
|
||||||
|
|
||||||
|
for (String timeMark : keySet())
|
||||||
|
{
|
||||||
|
StringSet set = get(timeMark);
|
||||||
|
|
||||||
|
result.inc(set.size(), prefix, timeMark);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put.
|
||||||
|
*
|
||||||
|
* @param timemark
|
||||||
|
* the timemark
|
||||||
|
* @param ip
|
||||||
|
* the ip
|
||||||
|
*/
|
||||||
|
public void put(final String ip, final String timemark)
|
||||||
|
{
|
||||||
|
StringSet set = super.get(ip);
|
||||||
|
if (set == null)
|
||||||
|
{
|
||||||
|
set = new StringSet();
|
||||||
|
put(timemark, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
set.put(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put.
|
||||||
|
*
|
||||||
|
* @param ip
|
||||||
|
* the ip
|
||||||
|
* @param timeMarks
|
||||||
|
* the time marks
|
||||||
|
*/
|
||||||
|
public void put(final String ip, final String... timeMarks)
|
||||||
|
{
|
||||||
|
for (String timeMark : timeMarks)
|
||||||
|
{
|
||||||
|
put(ip, timeMark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -50,8 +51,16 @@ public class LineIterator
|
||||||
* Signals that an I/O exception has occurred.
|
* Signals that an I/O exception has occurred.
|
||||||
*/
|
*/
|
||||||
public LineIterator(final File source) throws IOException
|
public LineIterator(final File source) throws IOException
|
||||||
|
{
|
||||||
|
if (source.getName().endsWith(".gz"))
|
||||||
|
{
|
||||||
|
this.in = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(source))));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
this.in = new BufferedReader(new InputStreamReader(new FileInputStream(source), DEFAULT_CHARSET_NAME));
|
this.in = new BufferedReader(new InputStreamReader(new FileInputStream(source), DEFAULT_CHARSET_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
this.nextLine = null;
|
this.nextLine = null;
|
||||||
this.ready = false;
|
this.ready = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package fr.devinsy.statoolinfos.htmlize.probes;
|
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -86,9 +84,22 @@ public class PathCounter
|
||||||
{
|
{
|
||||||
boolean result;
|
boolean result;
|
||||||
|
|
||||||
Pattern pattern = Pattern.compile("^\\d{4}-\\d{2}-\\d{2}$");
|
result = TimeMarkUtils.isDate(this.timeMark);
|
||||||
|
|
||||||
result = (pattern.matcher(this.timeMark).matches());
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is year.
|
||||||
|
*
|
||||||
|
* @return true, if is year
|
||||||
|
*/
|
||||||
|
public boolean isYear()
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
result = TimeMarkUtils.isYear(this.timeMark);
|
||||||
|
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
|
@ -103,9 +114,7 @@ public class PathCounter
|
||||||
{
|
{
|
||||||
boolean result;
|
boolean result;
|
||||||
|
|
||||||
Pattern pattern = Pattern.compile("^\\d{4}$");
|
result = TimeMarkUtils.isYear(this.timeMark);
|
||||||
|
|
||||||
result = (pattern.matcher(this.timeMark).matches());
|
|
||||||
|
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
|
@ -120,9 +129,7 @@ public class PathCounter
|
||||||
{
|
{
|
||||||
boolean result;
|
boolean result;
|
||||||
|
|
||||||
Pattern pattern = Pattern.compile("^\\d{4}W\\d{2}$");
|
result = TimeMarkUtils.isYearWeek(this.timeMark);
|
||||||
|
|
||||||
result = (pattern.matcher(this.timeMark).matches());
|
|
||||||
|
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -226,7 +226,7 @@ public class PathCounters extends HashMap<String, PathCounter>
|
||||||
|
|
||||||
for (int week = 1; week <= weekCount; week++)
|
for (int week = 1; week <= weekCount; week++)
|
||||||
{
|
{
|
||||||
String timeMark = String.format("%sW%02d", year, week);
|
String timeMark = String.format("%s-W%02d", year, week);
|
||||||
PathCounter weekCounter = get(prefix, timeMark);
|
PathCounter weekCounter = get(prefix, timeMark);
|
||||||
if (weekCounter != null)
|
if (weekCounter != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -61,46 +60,63 @@ public class Prober
|
||||||
*/
|
*/
|
||||||
public static void probe(final Configuration configuration) throws IOException, StatoolInfosException
|
public static void probe(final Configuration configuration) throws IOException, StatoolInfosException
|
||||||
{
|
{
|
||||||
|
StringList types = configuration.getProbeTypes();
|
||||||
|
|
||||||
|
PathCounters counters = new PathCounters();
|
||||||
|
|
||||||
//
|
//
|
||||||
|
if (types.containsAnyIgnoreCase("HttpAccessLog"))
|
||||||
{
|
{
|
||||||
String sourceFileName = configuration.get("conf.probe.http.accesslogs.source");
|
logger.info("== Processing HttpAccessLog.");
|
||||||
String targetFileName = configuration.get("conf.probe.http.accesslogs.target");
|
String source = configuration.getProbeHttpAccessLogSource();
|
||||||
|
logger.info("source=[{}]", source);
|
||||||
|
|
||||||
logger.info("source=[{}]", sourceFileName);
|
PathCounters data = HttpAccessLogAnalyzer.probe(source);
|
||||||
logger.info("target=[{}]", targetFileName);
|
counters.putAll(data);
|
||||||
|
}
|
||||||
|
|
||||||
if (!StringUtils.isAllBlank(sourceFileName, targetFileName))
|
//
|
||||||
|
if (types.containsAnyIgnoreCase("HttpErrorLog"))
|
||||||
{
|
{
|
||||||
PathCounters counters = HttpAccessLogAnalyzer.probe(new File(sourceFileName), new File(targetFileName));
|
logger.info("== Processing HttpErrorLog.");
|
||||||
|
String source = configuration.getProbeHttpErrorLogSource();
|
||||||
|
logger.info("source=[{}]", source);
|
||||||
|
|
||||||
writeMetrics(new File(targetFileName), counters);
|
PathCounters data = HttpErrorLogAnalyzer.probe(source);
|
||||||
|
counters.putAll(data);
|
||||||
|
}
|
||||||
|
|
||||||
// for (PathCounter counter : counters.values())
|
//
|
||||||
// {
|
if (types.containsAnyIgnoreCase("Framadate"))
|
||||||
// logger.info(counter.getPath() + " " +
|
{
|
||||||
// counter.getTimeMark() + " " + counter.getCounter());
|
logger.info("== Processing Framadate.");
|
||||||
// }
|
String source = configuration.getProbeHttpErrorLogSource();
|
||||||
|
logger.info("source=[{}]", source);
|
||||||
|
|
||||||
|
// PathCounters data = HttpErrorLogAnalyzer.probe(source);
|
||||||
|
// counters.putAll(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
logger.info("== Writing.");
|
||||||
|
File target = configuration.getProbeTarget();
|
||||||
|
logger.info("target=[{}]", target);
|
||||||
|
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Undefined target.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeMetrics(target, counters);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
{
|
{
|
||||||
PathCounter counter = counters.get("metrics.http.hits", "2020");
|
PathCounter counter = counters.get("metrics.http.hits", "2020");
|
||||||
logger.info("counter=" + counter.getCounter());
|
logger.info("counter=" + counter.getCounter());
|
||||||
logger.info("size={}", counters.size());
|
logger.info("size={}", counters.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// {
|
|
||||||
// String sourceFileName =
|
|
||||||
// configuration.get("conf.probe.httperrorlogs.source");
|
|
||||||
// String targetFileName =
|
|
||||||
// configuration.get("conf.probe.httperrorlogs.target");
|
|
||||||
// if (!StringUtils.isAllBlank(sourceFileName, targetFileName))
|
|
||||||
// {
|
|
||||||
// HttpErrorLogProber.probe(sourceFileName, targetFileName);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
171
src/fr/devinsy/statoolinfos/htmlize/probes/TimeMark.java
Normal file
171
src/fr/devinsy/statoolinfos/htmlize/probes/TimeMark.java
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class TimeMark.
|
||||||
|
*/
|
||||||
|
public class TimeMark
|
||||||
|
{
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(TimeMark.class);
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new path counter.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* the path
|
||||||
|
* @param timeMark
|
||||||
|
* the time mark
|
||||||
|
*/
|
||||||
|
public TimeMark(final String value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is date.
|
||||||
|
*
|
||||||
|
* @return true, if is date
|
||||||
|
*/
|
||||||
|
public boolean isDate()
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("^\\d{4}-\\d{2}-\\d{2}$");
|
||||||
|
|
||||||
|
result = (pattern.matcher(this.value).matches());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is year mark.
|
||||||
|
*
|
||||||
|
* @return true, if is year mark
|
||||||
|
*/
|
||||||
|
public boolean isYearMark()
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("^\\d{4}$");
|
||||||
|
|
||||||
|
result = (pattern.matcher(this.value).matches());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is year week.
|
||||||
|
*
|
||||||
|
* @return true, if is year week
|
||||||
|
*/
|
||||||
|
public boolean isYearWeek()
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("^\\d{4}W\\d{2}$");
|
||||||
|
|
||||||
|
result = (pattern.matcher(this.value).matches());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(final String value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeMark dayOf(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
TimeMark result;
|
||||||
|
|
||||||
|
String day = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.FRANCE));
|
||||||
|
result = new TimeMark(day);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Month of.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the time mark
|
||||||
|
*/
|
||||||
|
public static TimeMark monthOf(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
TimeMark result;
|
||||||
|
|
||||||
|
String month = date.format(DateTimeFormatter.ofPattern("yyyy-MM", Locale.FRANCE));
|
||||||
|
result = new TimeMark(month);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Year of.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the time mark
|
||||||
|
*/
|
||||||
|
public static TimeMark yearOf(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
TimeMark result;
|
||||||
|
|
||||||
|
String year = date.format(DateTimeFormatter.ofPattern("yyyy", Locale.FRANCE));
|
||||||
|
result = new TimeMark(year);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Year week of.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the time mark
|
||||||
|
*/
|
||||||
|
public static TimeMark yearWeekOf(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
TimeMark result;
|
||||||
|
|
||||||
|
String yearWeek = date.format(DateTimeFormatter.ofPattern("yyyyWW", Locale.FRANCE));
|
||||||
|
result = new TimeMark(yearWeek);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
254
src/fr/devinsy/statoolinfos/htmlize/probes/TimeMarkUtils.java
Normal file
254
src/fr/devinsy/statoolinfos/htmlize/probes/TimeMarkUtils.java
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.YearMonth;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.threeten.extra.YearWeek;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class TimeMarkUtils.
|
||||||
|
*/
|
||||||
|
public class TimeMarkUtils
|
||||||
|
{
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(TimeMarkUtils.class);
|
||||||
|
|
||||||
|
private static final Pattern YEAR_PATTERN = Pattern.compile("^(?<year>\\d{4})$");
|
||||||
|
private static final Pattern YEAR_MONTH_PATTERN = Pattern.compile("^(?<year>\\d{4})-(?<month>\\d{2})$");
|
||||||
|
private static final Pattern YEAR_WEEK_PATTERN = Pattern.compile("^(?<year>\\d{4})-W(?<week>\\d{2})$");
|
||||||
|
private static final Pattern DATE_PATTERN = Pattern.compile("^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new time mark utils.
|
||||||
|
*/
|
||||||
|
private TimeMarkUtils()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Day of.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String dateOf(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.FRANCE));
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is date.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return true, if is date
|
||||||
|
*/
|
||||||
|
public static boolean isDate(final String value)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
result = (DATE_PATTERN.matcher(value).matches());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is year mark.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return true, if is year mark
|
||||||
|
*/
|
||||||
|
public static boolean isYear(final String value)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
result = (YEAR_PATTERN.matcher(value).matches());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is year month.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return true, if is year month
|
||||||
|
*/
|
||||||
|
public static boolean isYearMonth(final String value)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
result = (YEAR_MONTH_PATTERN.matcher(value).matches());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is year week.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return true, if is year week
|
||||||
|
*/
|
||||||
|
public static boolean isYearWeek(final String value)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
result = (YEAR_WEEK_PATTERN.matcher(value).matches());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the date.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return the local date
|
||||||
|
*/
|
||||||
|
public static LocalDate parseDate(final String value)
|
||||||
|
{
|
||||||
|
LocalDate result;
|
||||||
|
|
||||||
|
result = LocalDate.parse(value);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the year.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
|
public static int parseYear(final String value)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = Integer.parseInt(value);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the year month.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return the year month
|
||||||
|
*/
|
||||||
|
public static YearMonth parseYearMonth(final String value)
|
||||||
|
{
|
||||||
|
YearMonth result;
|
||||||
|
|
||||||
|
result = YearMonth.parse(value);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the year week.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return the year week
|
||||||
|
*/
|
||||||
|
public static YearWeek parseYearWeek(final String value)
|
||||||
|
{
|
||||||
|
YearWeek result;
|
||||||
|
|
||||||
|
result = YearWeek.parse(value);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Month of.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String yearMonthOf(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = date.format(DateTimeFormatter.ofPattern("yyyy-MM", Locale.FRANCE));
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Year of.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String yearOf(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = date.format(DateTimeFormatter.ofPattern("yyyy", Locale.FRANCE));
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Year week of.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String yearWeekOf(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = date.format(DateTimeFormatter.ofPattern("yyyy'-W'ww", Locale.FRANCE));
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
248
src/fr/devinsy/statoolinfos/htmlize/probes/Visit.java
Normal file
248
src/fr/devinsy/statoolinfos/htmlize/probes/Visit.java
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.YearMonth;
|
||||||
|
import java.time.temporal.WeekFields;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.threeten.extra.YearWeek;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class PathCounter.
|
||||||
|
*/
|
||||||
|
public class Visit
|
||||||
|
{
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(Visit.class);
|
||||||
|
|
||||||
|
private LocalDateTime start;
|
||||||
|
private LocalDateTime end;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new visit.
|
||||||
|
*
|
||||||
|
* @param start
|
||||||
|
* the start
|
||||||
|
*/
|
||||||
|
public Visit(final LocalDateTime start)
|
||||||
|
{
|
||||||
|
this(start, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new visit.
|
||||||
|
*
|
||||||
|
* @param start
|
||||||
|
* the start
|
||||||
|
* @param end
|
||||||
|
* the end
|
||||||
|
*/
|
||||||
|
public Visit(final LocalDateTime start, final LocalDateTime end)
|
||||||
|
{
|
||||||
|
if (start == null)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Null parameter [start].");
|
||||||
|
}
|
||||||
|
else if (end == null)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Null parameter [end].");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getEnd()
|
||||||
|
{
|
||||||
|
return this.end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getStart()
|
||||||
|
{
|
||||||
|
return this.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is matching.
|
||||||
|
*
|
||||||
|
* @param year
|
||||||
|
* the year
|
||||||
|
* @return true, if is matching
|
||||||
|
*/
|
||||||
|
public boolean isMatching(final int year)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
if ((year >= this.start.getYear()) && (year <= this.end.getYear()))
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is matching.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return true, if is matching
|
||||||
|
*/
|
||||||
|
public boolean isMatching(final LocalDate date)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
if (date == null)
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LocalDate startDate = this.start.toLocalDate();
|
||||||
|
LocalDate endDate = this.end.toLocalDate();
|
||||||
|
|
||||||
|
if ((date.isBefore(startDate)) || (date.isAfter(endDate)))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is matching.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return true, if is matching
|
||||||
|
*/
|
||||||
|
public boolean isMatching(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
if (date == null)
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((date.isBefore(this.start)) || (date.isAfter(this.end)))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is matching.
|
||||||
|
*
|
||||||
|
* @param timemark
|
||||||
|
* the timemark
|
||||||
|
* @return true, if is matching
|
||||||
|
*/
|
||||||
|
public boolean isMatching(final YearMonth yearMonth)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
if (yearMonth == null)
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
YearMonth startYearMonth = YearMonth.of(this.start.getYear(), this.start.getMonth());
|
||||||
|
YearMonth endYearMonth = YearMonth.of(this.end.getYear(), this.end.getMonth());
|
||||||
|
|
||||||
|
if ((yearMonth.isBefore(startYearMonth)) || (yearMonth.isAfter(endYearMonth)))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is matching.
|
||||||
|
*
|
||||||
|
* @param year
|
||||||
|
* the year
|
||||||
|
* @param week
|
||||||
|
* the week
|
||||||
|
* @return true, if is matching
|
||||||
|
*/
|
||||||
|
public boolean isMatching(final YearWeek yearWeek)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
YearWeek startYearWeek = YearWeek.of(this.start.getYear(), this.start.get(WeekFields.ISO.weekOfYear()));
|
||||||
|
YearWeek endYearWeek = YearWeek.of(this.end.getYear(), this.end.get(WeekFields.ISO.weekOfYear()));
|
||||||
|
|
||||||
|
if ((yearWeek.isBefore(startYearWeek)) || (yearWeek.isAfter(endYearWeek)))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnd(final LocalDateTime end)
|
||||||
|
{
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStart(final LocalDateTime start)
|
||||||
|
{
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
145
src/fr/devinsy/statoolinfos/htmlize/probes/VisitCounter.java
Normal file
145
src/fr/devinsy/statoolinfos/htmlize/probes/VisitCounter.java
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class PathCounter.
|
||||||
|
*/
|
||||||
|
public class VisitCounter
|
||||||
|
{
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(VisitCounter.class);
|
||||||
|
|
||||||
|
private String path;
|
||||||
|
private String timeMark;
|
||||||
|
private long counter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new path counter.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* the path
|
||||||
|
* @param timeMark
|
||||||
|
* the time mark
|
||||||
|
*/
|
||||||
|
public VisitCounter(final String path, final String timeMark)
|
||||||
|
{
|
||||||
|
this.path = path;
|
||||||
|
this.timeMark = timeMark;
|
||||||
|
this.counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCounter()
|
||||||
|
{
|
||||||
|
return this.counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath()
|
||||||
|
{
|
||||||
|
return this.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTimeMark()
|
||||||
|
{
|
||||||
|
return this.timeMark;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inc.
|
||||||
|
*/
|
||||||
|
public void inc()
|
||||||
|
{
|
||||||
|
this.counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void inc(final long value)
|
||||||
|
{
|
||||||
|
this.counter += value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is date.
|
||||||
|
*
|
||||||
|
* @return true, if is date
|
||||||
|
*/
|
||||||
|
public boolean isDate()
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("^\\d{4}-\\d{2}-\\d{2}$");
|
||||||
|
|
||||||
|
result = (pattern.matcher(this.timeMark).matches());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is year mark.
|
||||||
|
*
|
||||||
|
* @return true, if is year mark
|
||||||
|
*/
|
||||||
|
public boolean isYearMark()
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("^\\d{4}$");
|
||||||
|
|
||||||
|
result = (pattern.matcher(this.timeMark).matches());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is year week.
|
||||||
|
*
|
||||||
|
* @return true, if is year week
|
||||||
|
*/
|
||||||
|
public boolean isYearWeek()
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("^\\d{4}W\\d{2}$");
|
||||||
|
|
||||||
|
result = (pattern.matcher(this.timeMark).matches());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCounter(final long counter)
|
||||||
|
{
|
||||||
|
this.counter = counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPath(final String path)
|
||||||
|
{
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeMark(final String timeMark)
|
||||||
|
{
|
||||||
|
this.timeMark = timeMark;
|
||||||
|
}
|
||||||
|
}
|
167
src/fr/devinsy/statoolinfos/htmlize/probes/VisitCounters.java
Normal file
167
src/fr/devinsy/statoolinfos/htmlize/probes/VisitCounters.java
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.YearMonth;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.threeten.extra.YearWeek;
|
||||||
|
|
||||||
|
import fr.devinsy.strings.StringSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class VisitCounters.
|
||||||
|
*/
|
||||||
|
public class VisitCounters extends HashMap<String, Visits>
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 7081954620691577515L;
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(VisitCounters.class);
|
||||||
|
|
||||||
|
private StringSet timeMarks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new path counters.
|
||||||
|
*/
|
||||||
|
public VisitCounters()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this.timeMarks = new StringSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute key.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* the path
|
||||||
|
* @param timeMark
|
||||||
|
* the time mark
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public String computeKey(final HttpLog log)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = String.format("%s--%s", log.getRemoteAddress(), log.getUserAgent().toString());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the counters.
|
||||||
|
*
|
||||||
|
* @return the counters
|
||||||
|
*/
|
||||||
|
public PathCounters getCounters(final String prefix)
|
||||||
|
{
|
||||||
|
PathCounters result;
|
||||||
|
|
||||||
|
result = new PathCounters();
|
||||||
|
|
||||||
|
logger.info("timemark count={}", this.timeMarks.size());
|
||||||
|
for (String timemark : this.timeMarks)
|
||||||
|
{
|
||||||
|
long count = 0;
|
||||||
|
|
||||||
|
if (TimeMarkUtils.isDate(timemark))
|
||||||
|
{
|
||||||
|
LocalDate date = TimeMarkUtils.parseDate(timemark);
|
||||||
|
|
||||||
|
for (Visits visits : this.values())
|
||||||
|
{
|
||||||
|
count += visits.count(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TimeMarkUtils.isYearMonth(timemark))
|
||||||
|
{
|
||||||
|
YearMonth yearMonth = TimeMarkUtils.parseYearMonth(timemark);
|
||||||
|
for (Visits visits : this.values())
|
||||||
|
{
|
||||||
|
count += visits.count(yearMonth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TimeMarkUtils.isYearWeek(timemark))
|
||||||
|
{
|
||||||
|
YearWeek yearWeek = TimeMarkUtils.parseYearWeek(timemark);
|
||||||
|
for (Visits visits : this.values())
|
||||||
|
{
|
||||||
|
count += visits.count(yearWeek);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TimeMarkUtils.isYear(timemark))
|
||||||
|
{
|
||||||
|
int year = TimeMarkUtils.parseYear(timemark);
|
||||||
|
for (Visits visits : this.values())
|
||||||
|
{
|
||||||
|
count += visits.count(year);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("timemark/count = {}/{}", timemark, count);
|
||||||
|
|
||||||
|
result.inc(count, prefix, timemark);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("visits counters [{}]", result.size());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put visit.
|
||||||
|
*
|
||||||
|
* @param log
|
||||||
|
* the log
|
||||||
|
*/
|
||||||
|
public void putVisit(final HttpLog log)
|
||||||
|
{
|
||||||
|
if (log != null)
|
||||||
|
{
|
||||||
|
String key = computeKey(log);
|
||||||
|
|
||||||
|
Visits visits = get(key);
|
||||||
|
if (visits == null)
|
||||||
|
{
|
||||||
|
visits = new Visits();
|
||||||
|
put(key, visits);
|
||||||
|
}
|
||||||
|
|
||||||
|
visits.add(log.getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store time marks.
|
||||||
|
*
|
||||||
|
* @param timemarks
|
||||||
|
* the timemarks
|
||||||
|
*/
|
||||||
|
public void storeTimeMarks(final String... timemarks)
|
||||||
|
{
|
||||||
|
for (String timemark : timemarks)
|
||||||
|
{
|
||||||
|
this.timeMarks.put(timemark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
209
src/fr/devinsy/statoolinfos/htmlize/probes/Visits.java
Normal file
209
src/fr/devinsy/statoolinfos/htmlize/probes/Visits.java
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.YearMonth;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.threeten.extra.YearWeek;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Visits.
|
||||||
|
*/
|
||||||
|
public class Visits extends ArrayList<Visit>
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 4172108458534266440L;
|
||||||
|
|
||||||
|
private static final int BORDER_MINUTES = 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new visits.
|
||||||
|
*/
|
||||||
|
public Visits()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
*/
|
||||||
|
public void add(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
boolean ended = false;
|
||||||
|
int index = 0;
|
||||||
|
while (!ended)
|
||||||
|
{
|
||||||
|
if (index < size())
|
||||||
|
{
|
||||||
|
Visit visit = get(index);
|
||||||
|
|
||||||
|
if (date.isBefore(visit.getStart().minusMinutes(BORDER_MINUTES)))
|
||||||
|
{
|
||||||
|
this.add(index, new Visit(date));
|
||||||
|
ended = true;
|
||||||
|
}
|
||||||
|
else if (date.isBefore(visit.getStart()))
|
||||||
|
{
|
||||||
|
visit.setStart(date);
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
Visit previous = get(index - 1);
|
||||||
|
if (previous.getEnd().isAfter(visit.getStart().minusMinutes(BORDER_MINUTES)))
|
||||||
|
{
|
||||||
|
visit.setStart(previous.getStart());
|
||||||
|
remove(index - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ended = true;
|
||||||
|
}
|
||||||
|
else if (date.isAfter(visit.getEnd().plusMinutes(BORDER_MINUTES)))
|
||||||
|
{
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
else if (date.isAfter(visit.getEnd()))
|
||||||
|
{
|
||||||
|
visit.setEnd(date);
|
||||||
|
if (index + 1 < size())
|
||||||
|
{
|
||||||
|
Visit next = get(index - 1);
|
||||||
|
if (next.getStart().isBefore(visit.getEnd().plusMinutes(BORDER_MINUTES)))
|
||||||
|
{
|
||||||
|
visit.setEnd(next.getEnd());
|
||||||
|
remove(index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ended = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Matching visit case.
|
||||||
|
ended = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
add(new Visit(date));
|
||||||
|
ended = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count.
|
||||||
|
*
|
||||||
|
* @param year
|
||||||
|
* the year
|
||||||
|
* @return the long
|
||||||
|
*/
|
||||||
|
public long count(final int year)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
for (Visit visit : this)
|
||||||
|
{
|
||||||
|
if (visit.isMatching(year))
|
||||||
|
{
|
||||||
|
result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the long
|
||||||
|
*/
|
||||||
|
public long count(final LocalDate date)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
for (Visit visit : this)
|
||||||
|
{
|
||||||
|
if (visit.isMatching(date))
|
||||||
|
{
|
||||||
|
result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count.
|
||||||
|
*
|
||||||
|
* @param yearMonth
|
||||||
|
* the year month
|
||||||
|
* @return the long
|
||||||
|
*/
|
||||||
|
public long count(final YearMonth yearMonth)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
for (Visit visit : this)
|
||||||
|
{
|
||||||
|
if (visit.isMatching(yearMonth))
|
||||||
|
{
|
||||||
|
result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count.
|
||||||
|
*
|
||||||
|
* @param year
|
||||||
|
* the year
|
||||||
|
* @param week
|
||||||
|
* the week
|
||||||
|
* @return the long
|
||||||
|
*/
|
||||||
|
public long count(final YearWeek yearWeek)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
for (Visit visit : this)
|
||||||
|
{
|
||||||
|
if (visit.isMatching(yearWeek))
|
||||||
|
{
|
||||||
|
result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue