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.
|
||||
*
|
||||
|
@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import fr.devinsy.statoolinfos.crawl.CrawlCache;
|
||||
import fr.devinsy.statoolinfos.properties.PathProperties;
|
||||
import fr.devinsy.statoolinfos.properties.PathPropertyList;
|
||||
import fr.devinsy.strings.StringList;
|
||||
|
||||
/**
|
||||
* The Class PathProperty.
|
||||
|
@ -346,6 +347,80 @@ public class Configuration extends PathPropertyList
|
|||
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.
|
||||
*
|
||||
|
|
|
@ -18,18 +18,14 @@
|
|||
*/
|
||||
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -45,62 +41,42 @@ public class HttpAccessLogAnalyzer
|
|||
|
||||
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.
|
||||
*/
|
||||
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
|
||||
* the line
|
||||
* @return the http log
|
||||
* @return the counters
|
||||
*/
|
||||
public static HttpLog parseLog(final String line)
|
||||
public PathCounters getCounters()
|
||||
{
|
||||
HttpLog result;
|
||||
PathCounters result;
|
||||
|
||||
//
|
||||
// log_format combined '$remote_addr - $remote_user [$time_local] '
|
||||
// '"$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>[^\"]*)";
|
||||
result = new PathCounters();
|
||||
result.putAll(this.counters);
|
||||
|
||||
String combinedPattern = String.format("^%s - %s \\[%s\\] \"%s\" %s %s \"%s\" \"%s\".*$",
|
||||
remoteAddressPattern, remoteUserPattern, timePattern, requestPattern, statusPattern, bodyBytesSentPattern,
|
||||
refererPattern, httpUserAgentPattern);
|
||||
result.putAll(this.ips.getCounters("metrics.http.ip"));
|
||||
result.putAll(this.ipv4.getCounters("metrics.http.ip.ipv4"));
|
||||
result.putAll(this.ipv6.getCounters("metrics.http.ip.ipv6"));
|
||||
|
||||
// logger.info("pattern=[{}]", combinedPattern);
|
||||
|
||||
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;
|
||||
}
|
||||
result.putAll(this.visits.getCounters("metrics.http.visits"));
|
||||
|
||||
//
|
||||
return result;
|
||||
|
@ -109,86 +85,31 @@ public class HttpAccessLogAnalyzer
|
|||
/**
|
||||
* Probe.
|
||||
*
|
||||
* @param source
|
||||
* the source
|
||||
* @param target
|
||||
* the target
|
||||
* @param file
|
||||
* the file
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
* @throws StatoolInfosException
|
||||
* 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();
|
||||
|
||||
int errorCount = 0;
|
||||
for (File file : source.getParentFile().listFiles())
|
||||
LineIterator iterator = new LineIterator(file);
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
// if (file.getName().startsWith(source.getName()))
|
||||
if (file.getName().equals(source.getName()))
|
||||
String line = iterator.next();
|
||||
|
||||
try
|
||||
{
|
||||
errorCount += probe(result, source);
|
||||
probeLine(line);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.warn("Error parsing line [{}][{}]", line, exception.getMessage());
|
||||
exception.printStackTrace();
|
||||
this.errorCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
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
|
||||
{
|
||||
result = 0;
|
||||
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)
|
||||
{
|
||||
exception.printStackTrace();
|
||||
result += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly(in);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,9 +120,10 @@ public class HttpAccessLogAnalyzer
|
|||
* @param 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("==================");
|
||||
if (log == null)
|
||||
|
@ -220,64 +142,174 @@ public class HttpAccessLogAnalyzer
|
|||
String date = log.getDate();
|
||||
|
||||
// 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())
|
||||
{
|
||||
counters.inc("metrics.http.hits.ipv4", year, yearMonth, yearWeek, date);
|
||||
this.counters.inc("metrics.http.hits.ipv4", year, yearMonth, yearWeek, date);
|
||||
}
|
||||
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
|
||||
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
|
||||
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.* =
|
||||
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.* =
|
||||
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
|
||||
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
|
||||
UserAgentOS os = log.getHttpUserAgent().getOS();
|
||||
counters.inc("metrics.http.browsers." + os.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
||||
UserAgentOS os = log.getUserAgent().getOS();
|
||||
this.counters.inc("metrics.http.browsers." + os.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
||||
|
||||
// metrics.http.browsers.XXXXX
|
||||
UserAgentBrowser browser = log.getHttpUserAgent().getBrowser();
|
||||
counters.inc("metrics.http.browsers." + browser.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
||||
UserAgentBrowser browser = log.getUserAgent().getBrowser();
|
||||
this.counters.inc("metrics.http.browsers." + browser.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
||||
|
||||
// metrics.http.devices.XXXXX =
|
||||
UserAgentDevice device = log.getHttpUserAgent().getDevice();
|
||||
counters.inc("metrics.http.devices." + device.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
||||
|
||||
// metrics.http.countries.XX =
|
||||
UserAgentDevice device = log.getUserAgent().getDevice();
|
||||
this.counters.inc("metrics.http.devices." + device.toString().toLowerCase(), year, yearMonth, yearWeek, date);
|
||||
|
||||
// metrics.http.ip.* =
|
||||
// metrics.http.ip.ipv4.* =
|
||||
// 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.* =
|
||||
this.visits.putVisit(log);
|
||||
this.visits.storeTimeMarks(year, yearMonth, yearWeek, date);
|
||||
|
||||
// metrics.http.countries.XX =
|
||||
|
||||
// metrics.http.errors.* =
|
||||
// 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.
|
||||
*
|
||||
|
@ -18,16 +18,12 @@
|
|||
*/
|
||||
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -35,86 +31,68 @@ import org.slf4j.LoggerFactory;
|
|||
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";
|
||||
|
||||
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.
|
||||
*
|
||||
* @param source
|
||||
* the source
|
||||
* @param target
|
||||
* the target
|
||||
* @param file
|
||||
* the file
|
||||
* @throws IOException
|
||||
* 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;
|
||||
|
||||
counters = new PathCounters();
|
||||
|
||||
for (File file : source.getParentFile().listFiles())
|
||||
LineIterator iterator = new LineIterator(file);
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
if (file.getName().startsWith(source.getName()))
|
||||
String line = iterator.next();
|
||||
|
||||
try
|
||||
{
|
||||
probe(counters, source);
|
||||
probeLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
in = new BufferedReader(new InputStreamReader(new FileInputStream(source), DEFAULT_CHARSET_NAME));
|
||||
|
||||
boolean ended = false;
|
||||
while (!ended)
|
||||
catch (Exception exception)
|
||||
{
|
||||
String line = in.readLine();
|
||||
|
||||
if (line == null)
|
||||
{
|
||||
ended = true;
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(line))
|
||||
{
|
||||
probe(counters, line);
|
||||
}
|
||||
logger.warn("Error parsing line [{}][{}]", line, exception.getMessage());
|
||||
exception.printStackTrace();
|
||||
this.errorCount += 1;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -125,7 +103,7 @@ public class HttpErrorLogProber
|
|||
* @param line
|
||||
* the line
|
||||
*/
|
||||
public static void probe(final PathCounters counters, final String line)
|
||||
public void probeLine(final String line)
|
||||
{
|
||||
//
|
||||
LocalDateTime date;
|
||||
|
@ -137,18 +115,52 @@ public class HttpErrorLogProber
|
|||
String week = date.format(DateTimeFormatter.ofPattern("yyyyWW", Locale.FRANCE));
|
||||
String day = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.FRANCE));
|
||||
|
||||
// General HTTP access logs.
|
||||
|
||||
// metrics.http.errors
|
||||
counters.inc("metrics.http.errors", year);
|
||||
counters.inc("metrics.http.errors", month);
|
||||
counters.inc("metrics.http.errors", week);
|
||||
counters.inc("metrics.http.errors", day);
|
||||
this.counters.inc("metrics.http.errors", year, month, week, day);
|
||||
|
||||
// metrics.http.hits.ipv4
|
||||
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);
|
||||
// metrics.http.errors.php
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 long bodyBytesSent;
|
||||
private String referer;
|
||||
private UserAgent httpUserAgent;
|
||||
private UserAgent userAgent;
|
||||
|
||||
/**
|
||||
* Instantiates a new http log.
|
||||
|
@ -60,7 +60,7 @@ public class HttpLog
|
|||
this.status = null;
|
||||
this.bodyBytesSent = 0;
|
||||
this.referer = null;
|
||||
this.httpUserAgent = null;
|
||||
this.userAgent = null;
|
||||
}
|
||||
|
||||
public long getBodyBytesSent()
|
||||
|
@ -78,11 +78,6 @@ public class HttpLog
|
|||
return result;
|
||||
}
|
||||
|
||||
public UserAgent getHttpUserAgent()
|
||||
{
|
||||
return this.httpUserAgent;
|
||||
}
|
||||
|
||||
public String getReferer()
|
||||
{
|
||||
return this.referer;
|
||||
|
@ -113,6 +108,11 @@ public class HttpLog
|
|||
return this.time;
|
||||
}
|
||||
|
||||
public UserAgent getUserAgent()
|
||||
{
|
||||
return this.userAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the year.
|
||||
*
|
||||
|
@ -128,7 +128,7 @@ public class HttpLog
|
|||
}
|
||||
else
|
||||
{
|
||||
result = this.time.format(DateTimeFormatter.ofPattern("yyyy", Locale.FRANCE));
|
||||
result = TimeMarkUtils.yearOf(this.time);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -150,7 +150,7 @@ public class HttpLog
|
|||
}
|
||||
else
|
||||
{
|
||||
result = this.time.format(DateTimeFormatter.ofPattern("yyyy-MM", Locale.FRANCE));
|
||||
result = TimeMarkUtils.yearMonthOf(this.time);
|
||||
}
|
||||
//
|
||||
return result;
|
||||
|
@ -170,8 +170,7 @@ public class HttpLog
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
result = this.time.format(DateTimeFormatter.ofPattern("yyyy'W'ww", Locale.FRANCE));
|
||||
result = TimeMarkUtils.yearWeekOf(this.time);
|
||||
}
|
||||
//
|
||||
return result;
|
||||
|
@ -184,7 +183,7 @@ public class HttpLog
|
|||
{
|
||||
boolean result;
|
||||
|
||||
result = StringsUtils.containsAnyIgnoreCase(this.httpUserAgent.toString(), "bot", "monitoring");
|
||||
result = StringsUtils.containsAnyIgnoreCase(this.userAgent.toString(), "bot", "monitoring");
|
||||
|
||||
//
|
||||
return result;
|
||||
|
@ -237,11 +236,6 @@ public class HttpLog
|
|||
this.bodyBytesSent = bodyBytesSent;
|
||||
}
|
||||
|
||||
public void setHttpUserAgent(final UserAgent httpUserAgent)
|
||||
{
|
||||
this.httpUserAgent = httpUserAgent;
|
||||
}
|
||||
|
||||
public void setReferer(final String referer)
|
||||
{
|
||||
this.referer = referer;
|
||||
|
@ -272,6 +266,11 @@ public class HttpLog
|
|||
this.time = time;
|
||||
}
|
||||
|
||||
public void setUserAgent(final UserAgent userAgent)
|
||||
{
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* To string.
|
||||
*
|
||||
|
@ -291,7 +290,7 @@ public class HttpLog
|
|||
buffer.append("[status=").append(this.status.getCode()).append("]");
|
||||
buffer.append("[bodyBytesSent=").append(this.bodyBytesSent).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();
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ public class HttpLogIterator
|
|||
try
|
||||
{
|
||||
String line = this.iterator.next();
|
||||
result = HttpAccessLogAnalyzer.parseLog(line);
|
||||
result = HttpAccessLogAnalyzer.parseNginxCombinedLog(line);
|
||||
}
|
||||
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.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -51,7 +52,15 @@ public class LineIterator
|
|||
*/
|
||||
public LineIterator(final File source) throws IOException
|
||||
{
|
||||
this.in = new BufferedReader(new InputStreamReader(new FileInputStream(source), DEFAULT_CHARSET_NAME));
|
||||
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.nextLine = null;
|
||||
this.ready = false;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
*/
|
||||
package fr.devinsy.statoolinfos.htmlize.probes;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -86,9 +84,22 @@ public class PathCounter
|
|||
{
|
||||
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;
|
||||
|
@ -103,9 +114,7 @@ public class PathCounter
|
|||
{
|
||||
boolean result;
|
||||
|
||||
Pattern pattern = Pattern.compile("^\\d{4}$");
|
||||
|
||||
result = (pattern.matcher(this.timeMark).matches());
|
||||
result = TimeMarkUtils.isYear(this.timeMark);
|
||||
|
||||
//
|
||||
return result;
|
||||
|
@ -120,9 +129,7 @@ public class PathCounter
|
|||
{
|
||||
boolean result;
|
||||
|
||||
Pattern pattern = Pattern.compile("^\\d{4}W\\d{2}$");
|
||||
|
||||
result = (pattern.matcher(this.timeMark).matches());
|
||||
result = TimeMarkUtils.isYearWeek(this.timeMark);
|
||||
|
||||
//
|
||||
return result;
|
||||
|
|
|
@ -226,7 +226,7 @@ public class PathCounters extends HashMap<String, PathCounter>
|
|||
|
||||
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);
|
||||
if (weekCounter != null)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.io.FileNotFoundException;
|
|||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -61,46 +60,63 @@ public class Prober
|
|||
*/
|
||||
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");
|
||||
String targetFileName = configuration.get("conf.probe.http.accesslogs.target");
|
||||
logger.info("== Processing HttpAccessLog.");
|
||||
String source = configuration.getProbeHttpAccessLogSource();
|
||||
logger.info("source=[{}]", source);
|
||||
|
||||
logger.info("source=[{}]", sourceFileName);
|
||||
logger.info("target=[{}]", targetFileName);
|
||||
|
||||
if (!StringUtils.isAllBlank(sourceFileName, targetFileName))
|
||||
{
|
||||
PathCounters counters = HttpAccessLogAnalyzer.probe(new File(sourceFileName), new File(targetFileName));
|
||||
|
||||
writeMetrics(new File(targetFileName), counters);
|
||||
|
||||
// for (PathCounter counter : counters.values())
|
||||
// {
|
||||
// logger.info(counter.getPath() + " " +
|
||||
// counter.getTimeMark() + " " + counter.getCounter());
|
||||
// }
|
||||
|
||||
{
|
||||
PathCounter counter = counters.get("metrics.http.hits", "2020");
|
||||
logger.info("counter=" + counter.getCounter());
|
||||
logger.info("size={}", counters.size());
|
||||
}
|
||||
|
||||
}
|
||||
PathCounters data = HttpAccessLogAnalyzer.probe(source);
|
||||
counters.putAll(data);
|
||||
}
|
||||
|
||||
//
|
||||
// {
|
||||
// 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);
|
||||
// }
|
||||
// }
|
||||
if (types.containsAnyIgnoreCase("HttpErrorLog"))
|
||||
{
|
||||
logger.info("== Processing HttpErrorLog.");
|
||||
String source = configuration.getProbeHttpErrorLogSource();
|
||||
logger.info("source=[{}]", source);
|
||||
|
||||
PathCounters data = HttpErrorLogAnalyzer.probe(source);
|
||||
counters.putAll(data);
|
||||
}
|
||||
|
||||
//
|
||||
if (types.containsAnyIgnoreCase("Framadate"))
|
||||
{
|
||||
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");
|
||||
logger.info("counter=" + counter.getCounter());
|
||||
logger.info("size={}", counters.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
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