Compare commits

..

35 commits

Author SHA1 Message Date
20a58e2b1d Build 0.5.0 2022-01-23 03:49:07 +01:00
d644e334a8 Added custom access log pattern config in README. 2022-01-23 03:48:29 +01:00
18c386b91c Prepared next version. 2022-01-23 03:39:43 +01:00
2ee42fd197 Improved code. 2022-01-22 19:29:44 +01:00
defa20b003 Improved http access log regex. 2022-01-22 19:29:18 +01:00
87b44605c5 Restricted federation stats to active organizations only. 2022-01-22 19:28:52 +01:00
8a106f01c7 Upgraded commons-io lib. 2022-01-22 16:54:57 +01:00
8aaf2f345c Improved access http parsing. 2022-01-22 16:54:41 +01:00
6850f3b57a Added method http metric. 2022-01-22 16:54:10 +01:00
6bf8037cc5 Improved status management in organizations and services display. 2022-01-22 13:05:28 +01:00
251d4ef761 Improved property date get. 2022-01-22 03:30:18 +01:00
a1b0c34645 Fixed emoji sorting in organization list and service list views. 2022-01-21 19:41:41 +01:00
ebff7251e8 Added Let's encrypt detection for bot filtering. 2022-01-21 00:55:08 +01:00
1c4b9cfe87 Added date tips in header column with monthly label. 2022-01-21 00:43:37 +01:00
1d36510ac3 Replaced 0 value with emoji in tables. 2022-01-21 00:31:33 +01:00
0e47ac2dae Added visits.ipv4 and visits.ipv6 management. 2022-01-20 19:25:02 +01:00
00d778c9f3 Imporved error message. 2022-01-20 16:27:25 +01:00
eee023346f Clean script file. 2022-01-20 16:26:34 +01:00
9fdb7beb46 Fixed unmanaged crawl exception. 2022-01-18 13:08:15 +01:00
35c3f91609 Improved about page. 2022-01-17 04:36:40 +01:00
4099a9a5fb Added metrics configuration templates in README. 2022-01-16 05:55:13 +01:00
2e59500d69 Added asset filter in http visit definition. 2022-01-13 17:56:21 +01:00
f1361c9d25 Fixed visit and visitor new definition. 2022-01-13 12:55:17 +01:00
f6d433de00 Fixed bug in error nginx time parsing. 2022-01-13 12:53:49 +01:00
79441007b0 Fixed label display in 2 data graph. 2022-01-13 12:52:33 +01:00
3feafb815c Improved code. 2022-01-11 16:04:15 +01:00
f02a3b7dd4 Added bot pattern for mod_jk dummy connection in http logs. 2022-01-11 16:02:24 +01:00
6c220602fd Improved code. 2022-01-11 16:01:51 +01:00
a667d59072 Removed success filter in http log visits compute. 2022-01-11 02:15:24 +01:00
88a1cd4c29 Added asterisk month in organization list view. 2022-01-11 00:29:16 +01:00
ab9e8c6b56 Added contributor. 2022-01-09 12:12:46 +01:00
b3f9d37480 Fixed DataTables path after upgrade. 2022-01-09 11:14:32 +01:00
9f7de0cde4 Fixed former member display in organization page. 2022-01-08 19:12:08 +01:00
fd19427700 Improved UserAgent analyze. 2022-01-06 10:24:55 +01:00
07de9414b9 Fixed empty log file case. 2022-01-05 14:06:47 +01:00
56 changed files with 1107 additions and 252 deletions

View file

@ -15,7 +15,6 @@
<classpathentry kind="lib" path="lib/hsqldb-2.3.0.jar"/> <classpathentry kind="lib" path="lib/hsqldb-2.3.0.jar"/>
<classpathentry kind="lib" path="lib/UnitTesting/junit-4.12.jar" sourcepath="lib/UnitTesting/junit-4.12-sources.jar"/> <classpathentry kind="lib" path="lib/UnitTesting/junit-4.12.jar" sourcepath="lib/UnitTesting/junit-4.12-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-cli-1.4.jar" sourcepath="lib/commons-cli-1.4-sources.jar"/> <classpathentry kind="lib" path="lib/commons-cli-1.4.jar" sourcepath="lib/commons-cli-1.4-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-io-2.7.jar" sourcepath="lib/commons-io-2.7-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-lang3-3.11.jar" sourcepath="lib/commons-lang3-3.11-sources.jar"/> <classpathentry kind="lib" path="lib/commons-lang3-3.11.jar" sourcepath="lib/commons-lang3-3.11-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-text-1.9.jar" sourcepath="lib/commons-text-1.9-sources.jar"/> <classpathentry kind="lib" path="lib/commons-text-1.9.jar" sourcepath="lib/commons-text-1.9-sources.jar"/>
<classpathentry kind="lib" path="lib/tika-core-1.24.1.jar" sourcepath="lib/tika-core-1.24.1-sources.jar"/> <classpathentry kind="lib" path="lib/tika-core-1.24.1.jar" sourcepath="lib/tika-core-1.24.1-sources.jar"/>
@ -28,5 +27,6 @@
<classpathentry kind="lib" path="lib/Logs/log4j-api-2.17.1.jar" sourcepath="lib/Logs/log4j-api-2.17.1-sources.jar"/> <classpathentry kind="lib" path="lib/Logs/log4j-api-2.17.1.jar" sourcepath="lib/Logs/log4j-api-2.17.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-core-2.17.1.jar" sourcepath="lib/Logs/log4j-core-2.17.1-sources.jar"/> <classpathentry kind="lib" path="lib/Logs/log4j-core-2.17.1.jar" sourcepath="lib/Logs/log4j-core-2.17.1-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/log4j-slf4j-impl-2.17.1.jar" sourcepath="lib/Logs/log4j-slf4j-impl-2.17.1-sources.jar"/> <classpathentry kind="lib" path="lib/Logs/log4j-slf4j-impl-2.17.1.jar" sourcepath="lib/Logs/log4j-slf4j-impl-2.17.1-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-io-2.11.0.jar" sourcepath="lib/commons-io-2.11.0-sources.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

104
README.md
View file

@ -19,7 +19,6 @@ I am glad to use the beautiful artwork of David Revoy (http://www.peppercarrot.c
* Source: https://framagit.org/Deevad/cat-avatar-generator * Source: https://framagit.org/Deevad/cat-avatar-generator
* Originally inspired of the code for "MonsterID" by Andreas Gohr http://www.splitbrain.org/go/monsterid. * Originally inspired of the code for "MonsterID" by Andreas Gohr http://www.splitbrain.org/go/monsterid.
### Cicle-icons ### Cicle-icons
I am glad to use the generous artwork of ElegantThemes.com : I am glad to use the generous artwork of ElegantThemes.com :
@ -90,15 +89,19 @@ Usage:
``` ```
### Generate metrics files ## Generate metrics files
### Basics
Create a configuration file `/srv/statoolInfos/conf/foo.bar.org.conf`: Create a configuration file `/srv/statoolInfos/conf/foo.bar.org.conf`:
``` ```
conf.probe.types=HttpAccessLog, HttpErrorLog conf.probe.types=<metrictype1>, <metrictype2>
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log* conf.probe.metrictype1param1.file=<value>
conf.probe.httperrorlog.file=/var/log/apache2/foo.bar.org-error.log* conf.probe.metrictype1param2.file=<value>
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org.metrics conf.probe.metrictype2param1.file=<value>
conf.probe.metrictype2param2.file=<value>
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
``` ```
Generate the metric file for the first time: Generate the metric file for the first time:
@ -114,3 +117,92 @@ Create a cron file to update the metric file everyday:
``` ```
Warning: in previous day mode, the metrics generated are overwrited for the last month, the last week and the last day. So, six weeks in logs are required. Warning: in previous day mode, the metrics generated are overwrited for the last month, the last week and the last day. So, six weeks in logs are required.
### Web metrics
Configuration template:
```
conf.probe.types=HttpAccessLog, HttpErrorLog
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
conf.probe.httperrorlog.file=/var/log/apache2/foo.bar.org-error.log*
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
# Custom access log pattern with Java regex.
# Default: "^(?<remoteAddress>[a-zA-F0-9\\\\:\\\\.]+) - (?<remoteUser>[^\\[]+) \\[(?<time>[^\\]]+)\\] \"(?<request>.*)\" (?<status>\\d+) (?<bodyBytesSent>\\d+) \"(?<referer>.*)\" \"(?<userAgent>[^\"]*)\".*$"
conf.probe.httpaccesslog.pattern=
```
### Minetest metrics
Configuration template:
```
conf.probe.types=Minetest
conf.probe.minetest.logs=/home/cpm/Projets/StatoolInfos/EnvTest/minetest/minetest.log*
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
### Mumble metrics
Configuration template:
```
conf.probe.types=Mumble
conf.probe.mumble.logs=/var/log/mumble-server/mumble-server.log*
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
### PrivateBin metrics (experimental)
Warning: works fine if database, image and comment options are disabled.
Configuration template:
```
conf.probe.types=PrivateBin
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
conf.probe.privatebin.data=/var/www/paste.libre-service.eu/data/
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
### Framdadate metrics (coming soon)
Configuration template:
```
conf.probe.types=Framadate
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
### Gitea metrics (coming soon)
Configuration template:
```
conf.probe.types=Gitea
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
### LibreQR metrics (coming soon)
Configuration template:
```
conf.probe.types=LibreQR
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
conf.probe.libreqr.data=/var/www/qrcode.libre-service.eu/data/
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```
### Nextcloud metrics (coming soon)
Configuration template:
```
conf.probe.types=Nextcloud
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
```

View file

@ -1,3 +1,3 @@
#Build Number for ANT. Do not edit! #Build Number for ANT. Do not edit!
#Thu Dec 23 01:59:59 CET 2021 #Sun Jan 23 03:49:04 CET 2022
build.number=2 build.number=1

View file

@ -1,4 +1,4 @@
product.name=statoolinfos product.name=statoolinfos
product.revision.major=0 product.revision.major=0
product.revision.minor=4 product.revision.minor=5
product.revision.snapshot= product.revision.snapshot=

Binary file not shown.

BIN
lib/commons-io-2.11.0.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,19 +1,19 @@
#!/bin/bash #!/bin/bash
# Optional environment settings: # Optional environment settings:
# export LOG4J_CONFIGURATION_FILE="toto.properties" # export LOG4J_CONFIGURATION_FILE="toto.properties"
# export LOG4J_LEVEL=ERROR # export LOG4J_LEVEL=ERROR
# https://logging.apache.org/log4j/log4j-2.11.2/manual/configuration.html#System_Properties # https://logging.apache.org/log4j/log4j-2.11.2/manual/configuration.html#System_Properties
# Java check. # Java check.
javaCheck=`which java` javaCheck=`which java`
if [[ "$javaCheck" =~ ^/.* ]]; then if [[ "$javaCheck" =~ ^/.* ]]; then
#echo "Java requirement............... OK" #echo "Java requirement............... OK"
# Optional system properties: # Optional system properties:
# LOGFILE="-Dlog4j2.configurationFile=../../log4j2.properties" # LOGFILE="-Dlog4j2.configurationFile=../../log4j2.properties"
# LOGLEVEL="-Dlog4j2.level=ERROR" # LOGLEVEL="-Dlog4j2.level=ERROR"
# https://logging.apache.org/log4j/log4j-2.11.2/manual/configuration.html#System_Properties # https://logging.apache.org/log4j/log4j-2.11.2/manual/configuration.html#System_Properties
java -Djava.awt.headless=true $LOGFILE $LOGLEVEL -jar "$(dirname "$0")"/statoolinfos.jar $@ java -Djava.awt.headless=true $LOGFILE $LOGLEVEL -jar "$(dirname "$0")"/statoolinfos.jar $@
else else

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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.
* *
@ -81,6 +81,60 @@ public class Federation extends PathPropertyList
} }
} }
/**
* Gets the organizations active.
*
* @return the organizations active
*/
public Organizations getActiveOrganizations()
{
Organizations result;
result = this.organizations.filterActiveFor(getTechnicalName());
//
return result;
}
/**
* Gets the active services.
*
* @return the active services
*/
public long getActiveServiceCount()
{
long result;
result = 0;
for (Organization organization : getActiveOrganizations())
{
result += organization.getActiveServiceCount();
}
//
return result;
}
/**
* Gets the active services.
*
* @return the active services
*/
public Services getActiveServices()
{
Services result;
result = new Services();
for (Organization organization : getActiveOrganizations())
{
result.addAll(organization.getActiveServices());
}
//
return result;
}
/** /**
* Gets the contact email. * Gets the contact email.
* *
@ -396,7 +450,7 @@ public class Federation extends PathPropertyList
int result; int result;
result = 0; result = 0;
for (Organization organization : this.organizations) for (Organization organization : getActiveOrganizations())
{ {
result += organization.getServiceCount(); result += organization.getServiceCount();
} }
@ -405,6 +459,26 @@ public class Federation extends PathPropertyList
return result; return result;
} }
/**
* Gets the all services.
*
* @return the all services
*/
public Services getServices()
{
Services result;
result = new Services();
for (Organization organization : getActiveOrganizations())
{
result.addAll(organization.getServices());
}
//
return result;
}
/** /**
* Gets the all services. * Gets the all services.
* *
@ -436,7 +510,7 @@ public class Federation extends PathPropertyList
result = new Softwares(); result = new Softwares();
for (Service service : getServicesAll()) for (Service service : getServices())
{ {
if (StringUtils.isNotBlank(service.getSoftwareName())) if (StringUtils.isNotBlank(service.getSoftwareName()))
{ {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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.
* *
@ -42,6 +42,17 @@ import fr.devinsy.statoolinfos.util.URLUtils;
public class Organization extends PathPropertyList public class Organization extends PathPropertyList
{ {
private static final long serialVersionUID = -2709210934548224213L; private static final long serialVersionUID = -2709210934548224213L;
/**
* The Enum Status.
*/
public enum Status
{
ACTIVE,
IDLE,
AWAY
}
private Federation federation; private Federation federation;
private Services services; private Services services;
private File inputFile; private File inputFile;
@ -75,6 +86,51 @@ public class Organization extends PathPropertyList
this.crawlJournal = new CrawlJournal(); this.crawlJournal = new CrawlJournal();
} }
/**
* Gets the active services.
*
* @return the active services
*/
public Services getActiveServices()
{
Services result;
result = new Services();
for (Service service : this.services)
{
if (service.isActive())
{
result.add(service);
}
}
//
return result;
}
/**
* Gets the service active count.
*
* @return the service active count
*/
public int getActiveServiceCount()
{
int result;
result = 0;
for (Service service : this.services)
{
if (service.isActive())
{
result += 1;
}
}
//
return result;
}
/** /**
* Gets the age. * Gets the age.
* *
@ -439,6 +495,44 @@ public class Organization extends PathPropertyList
return result; return result;
} }
/**
* Gets the status member of.
*
* @param entityName
* the entity name
* @return the status member of
*/
public Status getMemberStatusOf(final String entityName)
{
Status result;
String value = get("organization.memberof." + entityName + ".status");
if (StringUtils.isBlank(value))
{
result = null;
}
else if (StringUtils.equalsIgnoreCase(value, "ACTIVE"))
{
result = Status.ACTIVE;
}
else if (StringUtils.equalsIgnoreCase(value, "IDLE"))
{
result = Status.IDLE;
}
else if (StringUtils.equalsIgnoreCase(value, "AWAY"))
{
result = Status.AWAY;
}
else
{
result = null;
}
//
return result;
}
/** /**
* Gets the metric month values all. * Gets the metric month values all.
* *
@ -616,21 +710,6 @@ public class Organization extends PathPropertyList
return result; return result;
} }
/**
* Gets the service active count.
*
* @return the service active count
*/
public int getServiceActiveCount()
{
int result;
result = this.services.getBy(Service.Status.OK).size();
//
return result;
}
/** /**
* Gets the service count. * Gets the service count.
* *
@ -666,6 +745,42 @@ public class Organization extends PathPropertyList
return result; return result;
} }
/**
* Gets the status.
*
* @return the status
*/
public Status getStatus()
{
Status result;
String value = get("organization.status.level", "organization.status");
if (StringUtils.isBlank(value))
{
result = null;
}
else if (StringUtils.equalsIgnoreCase(value, "ACTIVE"))
{
result = Status.ACTIVE;
}
else if (StringUtils.equalsIgnoreCase(value, "IDLE"))
{
result = Status.IDLE;
}
else if (StringUtils.equalsIgnoreCase(value, "AWAY"))
{
result = Status.AWAY;
}
else
{
result = null;
}
//
return result;
}
/** /**
* Gets the technical guide website. * Gets the technical guide website.
* *
@ -860,6 +975,83 @@ public class Organization extends PathPropertyList
return result; return result;
} }
/**
* Checks if is active.
*
* @return true, if is active
*/
public boolean isActive()
{
boolean result;
if (getStatus() == Status.ACTIVE)
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is away.
*
* @return true, if is away
*/
public boolean isAway()
{
boolean result;
Status status = getStatus();
if (status == Status.AWAY)
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is away for.
*
* @param entityName
* the entity name
* @return true, if is away for
*/
public boolean isAwayFor(final String entityName)
{
boolean result;
Status memberStatus = getMemberStatusOf(entityName);
LocalDate endDate = getDate("organization.memberof." + entityName + ".enddate");
if (memberStatus == Status.AWAY)
{
result = true;
}
else if ((endDate == null) || (endDate.isAfter(LocalDate.now())))
{
result = false;
}
else
{
result = true;
}
//
return result;
}
/** /**
* Checks if is default. * Checks if is default.
* *

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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.
* *
@ -36,6 +36,31 @@ public class Organizations extends ArrayList<Organization>
super(); super();
} }
/**
* Filter member of.
*
* @param entityName
* the entity name
* @return the organizations
*/
public Organizations filterActiveFor(final String entityName)
{
Organizations result;
result = new Organizations();
for (Organization organization : this)
{
if ((!organization.isAway()) && (!organization.isAwayFor(entityName)))
{
result.add(organization);
}
}
//
return result;
}
/** /**
* Filter by social network. * Filter by social network.
* *
@ -85,18 +110,18 @@ public class Organizations extends ArrayList<Organization>
} }
/** /**
* Gets the service active count. * Gets the active service count.
* *
* @return the service active count * @return the active service count
*/ */
public int getServiceActiveCount() public int getActiveServiceCount()
{ {
int result; int result;
result = 0; result = 0;
for (Organization organization : this) for (Organization organization : this)
{ {
result += organization.getServiceCount(); result += organization.getActiveServiceCount();
} }
// //

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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.
* *
@ -489,7 +489,8 @@ public class Service extends PathPropertyList
MonthValues values = getMetricMonthValues("metrics.service.users"); MonthValues values = getMetricMonthValues("metrics.service.users");
values = values.extract(YearMonth.now().minusMonths(1), YearMonth.now().minusMonths(1)); YearMonth previousMonth = YearMonth.now().minusMonths(1);
values = values.extract(previousMonth, previousMonth);
result = (long) values.sum(); result = (long) values.sum();
@ -506,7 +507,7 @@ public class Service extends PathPropertyList
{ {
long result; long result;
MonthValues values = getMetricMonthValues("metrics.http.visits.humans"); MonthValues values = getMetricMonthValues("metrics.http.visits");
values = values.extract(YearMonth.now().minusMonths(1), YearMonth.now().minusMonths(1)); values = values.extract(YearMonth.now().minusMonths(1), YearMonth.now().minusMonths(1));
@ -859,6 +860,59 @@ public class Service extends PathPropertyList
return result; return result;
} }
/**
* Checks if is active.
*
* @return true, if is active
*/
public boolean isActive()
{
boolean result;
if (((getStatus() == Service.Status.OK) || (getStatus() == Status.WARNING) || (getStatus() == Status.ERROR)) && (!isAway()))
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is away.
*
* @return true, if is away
*/
public boolean isAway()
{
boolean result;
if (getEndDate() == null)
{
result = false;
}
else
{
LocalDate endDate = getDate("service.enddate");
if ((endDate == null) || (endDate.isAfter(LocalDate.now())))
{
result = false;
}
else
{
result = true;
}
}
//
return result;
}
/** /**
* Checks if is registration client. * Checks if is registration client.
* *

View file

@ -65,6 +65,32 @@ public class StatoolInfosUtils
public static final DateTimeFormatter PATTERN_SHORTDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy", Locale.FRANCE); public static final DateTimeFormatter PATTERN_SHORTDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy", Locale.FRANCE);
public static final DateTimeFormatter PATTERN_LONGDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy HH':'mm", Locale.FRANCE); public static final DateTimeFormatter PATTERN_LONGDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy HH':'mm", Locale.FRANCE);
/**
* Default if zero.
*
* @param value
* the value
* @param defaultValue
* the default value
* @return the string
*/
public static String defaultIfZero(final long value, final String defaultValue)
{
String result;
if (value == 0)
{
result = defaultValue;
}
else
{
result = String.valueOf(value);
}
//
return result;
}
/** /**
* Epoch to local date time. * Epoch to local date time.
* *

View file

@ -117,21 +117,24 @@ public class Crawler
logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage()); logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.CONNECTERROR); this.journal.add(url, parentURL, CrawlStatus.CONNECTERROR);
downloadFile = null; downloadFile = null;
exception.printStackTrace(); }
catch (java.net.SocketException exception)
{
logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.CONNECTERROR);
downloadFile = null;
} }
catch (FileNotFoundException exception) catch (FileNotFoundException exception)
{ {
logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage()); logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.URLNOTFOUND); this.journal.add(url, parentURL, CrawlStatus.URLNOTFOUND);
downloadFile = null; downloadFile = null;
exception.printStackTrace();
} }
catch (IOException exception) catch (IOException exception)
{ {
logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage()); logger.error("ERROR: crawl failed for [{}]: {}", url.toString(), exception.getMessage());
this.journal.add(url, parentURL, CrawlStatus.DOWNLOADERROR); this.journal.add(url, parentURL, CrawlStatus.DOWNLOADERROR);
downloadFile = null; downloadFile = null;
exception.printStackTrace();
} }
if (downloadFile != null) if (downloadFile != null)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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.
* *
@ -60,7 +60,7 @@ public class CategoryPage
logger.info("Htmlize category pages."); logger.info("Htmlize category pages.");
for (Category category : categories) for (Category category : categories)
{ {
Services services = federation.getServicesAll().getBy(category); Services services = federation.getServices().getBy(category);
String page = CategoryPage.htmlize(category, services); String page = CategoryPage.htmlize(category, services);
FileUtils.write(new File(htmlizeDirectory, "category-" + category.getTechnicalName() + ".xhtml"), page, StandardCharsets.UTF_8); FileUtils.write(new File(htmlizeDirectory, "category-" + category.getTechnicalName() + ".xhtml"), page, StandardCharsets.UTF_8);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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.
* *
@ -528,7 +528,7 @@ public class ChartHtmlizer
{ {
for (YearWeek timestamp = startTarget; !timestamp.isAfter(endTarget); timestamp = timestamp.plusWeeks(1)) for (YearWeek timestamp = startTarget; !timestamp.isAfter(endTarget); timestamp = timestamp.plusWeeks(1))
{ {
LocalDate date = timestamp.atDay(DayOfWeek.MONDAY).plusWeeks(1); LocalDate date = timestamp.atDay(DayOfWeek.MONDAY).plusDays(6);
String timestampLabel = date.format(DateTimeFormatter.ofPattern("yyyy-MMM-dd", Locale.FRANCE)); String timestampLabel = date.format(DateTimeFormatter.ofPattern("yyyy-MMM-dd", Locale.FRANCE));
chart.getLabels().add(timestampLabel); chart.getLabels().add(timestampLabel);
@ -1271,8 +1271,7 @@ public class ChartHtmlizer
{ {
String result; String result;
result = htmlizeServiceCountYearChart(federation.getServicesAll(), result = htmlizeServiceCountYearChart(federation.getServices(), StatoolInfosUtils.parseDate(federation.getStartDate()).getYear());
StatoolInfosUtils.parseDate(federation.getStartDate()).getYear());
// //
return result; return result;

View file

@ -69,8 +69,8 @@ public class FederationMetricSummaryPage
data.setContent("metricMenuView", FederationMetricMenuView.htmlize(federation, TypeMenu.SUMMARY, view, period)); data.setContent("metricMenuView", FederationMetricMenuView.htmlize(federation, TypeMenu.SUMMARY, view, period));
FederationMetricHtmlizer.htmlize(data, "http.hits.humans", federation, view, period, "metrics.http.hits.humans", ChartColor.GREEN); FederationMetricHtmlizer.htmlize(data, "http.hits.humans", federation, view, period, "metrics.http.hits.humans", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "http.visitors.humans", federation, view, period, "metrics.http.visitors.humans", ChartColor.GREEN); FederationMetricHtmlizer.htmlize(data, "http.visitors", federation, view, period, "metrics.http.visitors", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "http.visits.humans", federation, view, period, "metrics.http.visits.humans", ChartColor.GREEN); FederationMetricHtmlizer.htmlize(data, "http.visits", federation, view, period, "metrics.http.visits", ChartColor.GREEN);
// //
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricSummaryView.xhtml", data).toString(); String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricSummaryView.xhtml", data).toString();

View file

@ -98,24 +98,29 @@ public class FederationMetricWebPage
FederationMetricHtmlizer.htmlize(data, "http.ip.ipv4", federation, view, period, "metrics.http.ip.ipv4", ChartColor.YELLOW); FederationMetricHtmlizer.htmlize(data, "http.ip.ipv4", federation, view, period, "metrics.http.ip.ipv4", ChartColor.YELLOW);
FederationMetricHtmlizer.htmlize(data, "http.ip.ipv6", federation, view, period, "metrics.http.ip.ipv6", ChartColor.GREEN); FederationMetricHtmlizer.htmlize(data, "http.ip.ipv6", federation, view, period, "metrics.http.ip.ipv6", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "http.requesters", federation, view, period, "metrics.http.requesters", ChartColor.BLUE);
FederationMetricHtmlizer.htmlize(data, "http.requesters-humansbots", federation, view, period, "http.requesters (humans + bots)", "metrics.http.requesters.humans", ChartColor.GREEN,
"metrics.http.requesters.bots", ChartColor.YELLOW);
FederationMetricHtmlizer.htmlize(data, "http.requesters.humans", federation, view, period, "metrics.http.requesters.humans", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "http.requesters.bots", federation, view, period, "metrics.http.requesters.bots", ChartColor.YELLOW);
FederationMetricHtmlizer.htmlize(data, "http.requesters-ipv4ipv6", federation, view, period, "http.requesters (ipv4 + ipv6)", "metrics.http.requesters.ipv4", ChartColor.YELLOW,
"metrics.http.requesters.ipv6", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "http.requesters.ipv4", federation, view, period, "metrics.http.requesters.ipv4", ChartColor.YELLOW);
FederationMetricHtmlizer.htmlize(data, "http.requesters.ipv6", federation, view, period, "metrics.http.requesters.ipv6", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "http.visitors", federation, view, period, "metrics.http.visitors", ChartColor.BLUE); FederationMetricHtmlizer.htmlize(data, "http.visitors", federation, view, period, "metrics.http.visitors", ChartColor.BLUE);
FederationMetricHtmlizer.htmlize(data, "http.visitors-humansbots", federation, view, period, "http.visitors (humans + bots)", "metrics.http.visitors.humans", ChartColor.GREEN,
"metrics.http.visitors.bots", ChartColor.YELLOW);
FederationMetricHtmlizer.htmlize(data, "http.visitors.humans", federation, view, period, "metrics.http.visitors.humans", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "http.visitors.bots", federation, view, period, "metrics.http.visitors.bots", ChartColor.YELLOW);
FederationMetricHtmlizer.htmlize(data, "http.visitors-ipv4ipv6", federation, view, period, "http.visitors (ipv4 + ipv6)", "metrics.http.visitors.ipv4", ChartColor.YELLOW, FederationMetricHtmlizer.htmlize(data, "http.visitors-ipv4ipv6", federation, view, period, "http.visitors (ipv4 + ipv6)", "metrics.http.visitors.ipv4", ChartColor.YELLOW,
"metrics.http.visitors.ipv6", ChartColor.GREEN); "metrics.http.visitors.ipv6", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "http.visitors.ipv4", federation, view, period, "metrics.http.visitors.ipv4", ChartColor.YELLOW); FederationMetricHtmlizer.htmlize(data, "http.visitors.ipv4", federation, view, period, "metrics.http.visitors.ipv4", ChartColor.YELLOW);
FederationMetricHtmlizer.htmlize(data, "http.visitors.ipv6", federation, view, period, "metrics.http.visitors.ipv6", ChartColor.GREEN); FederationMetricHtmlizer.htmlize(data, "http.visitors.ipv6", federation, view, period, "metrics.http.visitors.ipv6", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "http.visits", federation, view, period, "metrics.http.visits", ChartColor.BLUE); FederationMetricHtmlizer.htmlize(data, "http.visits", federation, view, period, "metrics.http.visits", ChartColor.BLUE);
FederationMetricHtmlizer.htmlize(data, "http.visits-ipv4ipv6", federation, view, period, "http.visits (ipv4 + ipv6)", "metrics.http.visits.ipv4", ChartColor.YELLOW,
FederationMetricHtmlizer.htmlize(data, "http.visits-humansbots", federation, view, period, "http.visits (humans + bots)", "metrics.http.visits.humans", ChartColor.GREEN, "metrics.http.visits.ipv6", ChartColor.GREEN);
"metrics.http.visits.bots", ChartColor.YELLOW); FederationMetricHtmlizer.htmlize(data, "http.visits.ipv4", federation, view, period, "metrics.http.visits.ipv4", ChartColor.YELLOW);
FederationMetricHtmlizer.htmlize(data, "http.visits.bots", federation, view, period, "metrics.http.visits.bots", ChartColor.YELLOW); FederationMetricHtmlizer.htmlize(data, "http.visits.ipv6", federation, view, period, "metrics.http.visits.ipv6", ChartColor.GREEN);
FederationMetricHtmlizer.htmlize(data, "http.visits.humans", federation, view, period, "metrics.http.visits.humans", ChartColor.GREEN);
// //
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricWebView.xhtml", data).toString(); String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricWebView.xhtml", data).toString();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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.
* *
@ -78,7 +78,7 @@ public class FederationOrganizationsPage
TagDataManager data = new TagDataManager(); TagDataManager data = new TagDataManager();
data.setContent("federationHeaderView", FederationHeaderView.htmlize(federation)); data.setContent("federationHeaderView", FederationHeaderView.htmlize(federation));
data.setContent("organizationListView", OrganizationListView.htmlize(federation.getOrganizations())); data.setContent("organizationListView", OrganizationListView.htmlize(federation.getActiveOrganizations()));
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/federationOrganizations.xhtml", data).toString(); String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/federationOrganizations.xhtml", data).toString();

View file

@ -78,7 +78,7 @@ public class FederationServicesPage
TagDataManager data = new TagDataManager(); TagDataManager data = new TagDataManager();
data.setContent("federationHeaderView", FederationHeaderView.htmlize(federation)); data.setContent("federationHeaderView", FederationHeaderView.htmlize(federation));
data.setContent("serviceListView", ServiceListView.htmlize(federation.getServicesAll())); data.setContent("serviceListView", ServiceListView.htmlize(federation.getServices()));
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/federationServices.xhtml", data).toString(); String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/federationServices.xhtml", data).toString();

View file

@ -64,19 +64,19 @@ public class FederationStatsPage
data.setContent("federationHeaderView", FederationHeaderView.htmlize(federation)); data.setContent("federationHeaderView", FederationHeaderView.htmlize(federation));
data.setContent("turnoutChart", ChartHtmlizer.htmlizeOrganizationTurnoutChart(federation.getOrganizations())); data.setContent("turnoutChart", ChartHtmlizer.htmlizeOrganizationTurnoutChart(federation.getActiveOrganizations()));
data.setContent("organizationCountryChart", ChartHtmlizer.htmlizeOrganizationCountryChart(federation.getOrganizations())); data.setContent("organizationCountryChart", ChartHtmlizer.htmlizeOrganizationCountryChart(federation.getActiveOrganizations()));
data.setContent("organizationCountChart", ChartHtmlizer.htmlizeOrganizationCountChart(federation)); data.setContent("organizationCountChart", ChartHtmlizer.htmlizeOrganizationCountChart(federation));
data.setContent("organizationInOutChart", ChartHtmlizer.htmlizeOrganizationInOutChart(federation)); data.setContent("organizationInOutChart", ChartHtmlizer.htmlizeOrganizationInOutChart(federation));
data.setContent("hostServerTypeChart", ChartHtmlizer.htmlizeHostServerTypeChart(federation.getServicesAll())); data.setContent("hostServerTypeChart", ChartHtmlizer.htmlizeHostServerTypeChart(federation.getServices()));
data.setContent("hostProviderTypeChart", ChartHtmlizer.htmlizeHostProviderTypeChart(federation.getServicesAll())); data.setContent("hostProviderTypeChart", ChartHtmlizer.htmlizeHostProviderTypeChart(federation.getServices()));
data.setContent("serviceInstallTypeChart", ChartHtmlizer.htmlizeServiceInstallTypeChart(federation.getServicesAll())); data.setContent("serviceInstallTypeChart", ChartHtmlizer.htmlizeServiceInstallTypeChart(federation.getServices()));
data.setContent("serviceCountryChart", ChartHtmlizer.htmlizeServiceCountryChart(federation.getServicesAll())); data.setContent("serviceCountryChart", ChartHtmlizer.htmlizeServiceCountryChart(federation.getServices()));
// //
{ {
RegistrationStats stats = StatAgent.statRegistrationTypes(federation.getServicesAll()); RegistrationStats stats = StatAgent.statRegistrationTypes(federation.getServices());
data.setContent("registrationTypeChart", ChartHtmlizer.htmlizeRegistrationBarChart(stats)); data.setContent("registrationTypeChart", ChartHtmlizer.htmlizeRegistrationBarChart(stats));
data.setContent("registrationNoneTypeChart", ChartHtmlizer.htmlizeRegistrationNonePieChart(stats)); data.setContent("registrationNoneTypeChart", ChartHtmlizer.htmlizeRegistrationNonePieChart(stats));
@ -86,14 +86,14 @@ public class FederationStatsPage
} }
data.setContent("serviceCountYearChart", ChartHtmlizer.htmlizeServiceCountYearChart(federation)); data.setContent("serviceCountYearChart", ChartHtmlizer.htmlizeServiceCountYearChart(federation));
data.setContent("serviceDateStatusChart", ChartHtmlizer.htmlizeServiceDateStatusChart(federation.getServicesAll())); data.setContent("serviceDateStatusChart", ChartHtmlizer.htmlizeServiceDateStatusChart(federation.getServices()));
data.setContent("softwareDistributionChart", ChartHtmlizer.htmlizeSoftwareDistributionChart()); data.setContent("softwareDistributionChart", ChartHtmlizer.htmlizeSoftwareDistributionChart());
data.setContent("softwareDistributionPieChart", ChartHtmlizer.htmlizeSoftwareDistributionPieChart(federation.getServicesAll())); data.setContent("softwareDistributionPieChart", ChartHtmlizer.htmlizeSoftwareDistributionPieChart(federation.getServicesAll()));
data.setContent("categoryDistributionChart", ChartHtmlizer.htmlizeCategoryDistributionChart()); data.setContent("categoryDistributionChart", ChartHtmlizer.htmlizeCategoryDistributionChart());
data.setContent("categoryDistributionPieChart", ChartHtmlizer.htmlizeCatergoryDistributionPieChart(federation.getServicesAll())); data.setContent("categoryDistributionPieChart", ChartHtmlizer.htmlizeCatergoryDistributionPieChart(federation.getServicesAll()));
data.setContent("hostNameChart", ChartHtmlizer.htmlizeHostNamePieChart(federation.getServicesAll())); data.setContent("hostNameChart", ChartHtmlizer.htmlizeHostNamePieChart(federation.getServices()));
// //
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/federationStats.xhtml", data).toString(); String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/federationStats.xhtml", data).toString();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2021-2022 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.
* *
@ -81,7 +81,7 @@ public class FederationUptimePage
TagDataManager data = new TagDataManager(); TagDataManager data = new TagDataManager();
data.setContent("headerView", FederationHeaderView.htmlize(federation)); data.setContent("headerView", FederationHeaderView.htmlize(federation));
data.setContent("uptimeView", UptimeView.htmlize(federation.getServicesAll(), journal)); data.setContent("uptimeView", UptimeView.htmlize(federation.getActiveServices(), journal));
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/uptimePage.xhtml", data).toString(); String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/uptimePage.xhtml", data).toString();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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.
* *
@ -19,6 +19,7 @@
package fr.devinsy.statoolinfos.htmlize; package fr.devinsy.statoolinfos.htmlize;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -27,6 +28,7 @@ import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.core.Organization; import fr.devinsy.statoolinfos.core.Organization;
import fr.devinsy.statoolinfos.core.Organizations; import fr.devinsy.statoolinfos.core.Organizations;
import fr.devinsy.statoolinfos.core.StatoolInfosException; import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.core.StatoolInfosUtils;
import fr.devinsy.xidyn.XidynException; import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.data.TagDataManager; import fr.devinsy.xidyn.data.TagDataManager;
import fr.devinsy.xidyn.presenters.PresenterUtils; import fr.devinsy.xidyn.presenters.PresenterUtils;
@ -59,7 +61,12 @@ public class OrganizationListView
TagDataManager data = new TagDataManager(); TagDataManager data = new TagDataManager();
data.setContent("organizationCount", organizations.size()); data.setContent("organizationCount", organizations.size());
data.setContent("serviceCount", organizations.getServiceCount()); data.setContent("serviceCount", organizations.getActiveServiceCount());
String monthLabel = LocalDate.now().minusMonths(1).format(DateTimeFormatter.ofPattern("MMMM yyyy")).replace(" ", "&#160;");
data.setContent("monthLabel", monthLabel);
data.setAttribute("userCountHeaderColumn", "title", monthLabel);
data.setAttribute("visitCountHeaderColumn", "title", monthLabel);
int index = 0; int index = 0;
for (Organization organization : organizations.sortByReverseServiceCount()) for (Organization organization : organizations.sortByReverseServiceCount())
@ -74,9 +81,9 @@ public class OrganizationListView
data.setEscapedContent("organizationListLine", index, "organizationListLineUrlLink", organization.getWebsiteURL().toString()); data.setEscapedContent("organizationListLine", index, "organizationListLineUrlLink", organization.getWebsiteURL().toString());
data.setEscapedAttribute("organizationListLine", index, "organizationListLineUrlLink", "href", organization.getWebsiteURL().toString()); data.setEscapedAttribute("organizationListLine", index, "organizationListLineUrlLink", "href", organization.getWebsiteURL().toString());
} }
data.setContent("organizationListLine", index, "organizationListLineServiceCount", organization.getServiceActiveCount()); data.setContent("organizationListLine", index, "organizationListLineServiceCount", StatoolInfosUtils.defaultIfZero(organization.getActiveServiceCount(), "😿"));
data.setContent("organizationListLine", index, "organizationListLineUserCount", organization.getPreviousMonthUserCount()); data.setContent("organizationListLine", index, "organizationListLineUserCount", StatoolInfosUtils.defaultIfZero(organization.getPreviousMonthUserCount(), "😢"));
data.setContent("organizationListLine", index, "organizationListLineVisitCount", organization.getPreviousMonthVisitCount()); data.setContent("organizationListLine", index, "organizationListLineVisitCount", StatoolInfosUtils.defaultIfZero(organization.getPreviousMonthVisitCount(), "😞"));
data.setContent("organizationListLine", index, "organizationListLineDate", organization.getCrawledDate().format(DateTimeFormatter.ofPattern("dd/MM/YYYY"))); data.setContent("organizationListLine", index, "organizationListLineDate", organization.getCrawledDate().format(DateTimeFormatter.ofPattern("dd/MM/YYYY")));
data.setAttribute("organizationListLine", index, "organizationListLineDate", "title", organization.getCrawledDate().format(DateTimeFormatter.ofPattern("HH:mm:ss"))); data.setAttribute("organizationListLine", index, "organizationListLineDate", "title", organization.getCrawledDate().format(DateTimeFormatter.ofPattern("HH:mm:ss")));

View file

@ -70,8 +70,8 @@ public class OrganizationMetricSummaryPage
data.setContent("metricMenuView", OrganizationMetricMenuView.htmlize(organization, TypeMenu.SUMMARY, view, period)); data.setContent("metricMenuView", OrganizationMetricMenuView.htmlize(organization, TypeMenu.SUMMARY, view, period));
OrganizationMetricHtmlizer.htmlize(data, "http.hits.humans", organization, view, period, "metrics.http.hits.humans", ChartColor.GREEN); OrganizationMetricHtmlizer.htmlize(data, "http.hits.humans", organization, view, period, "metrics.http.hits.humans", ChartColor.GREEN);
OrganizationMetricHtmlizer.htmlize(data, "http.visitors.humans", organization, view, period, "metrics.http.visitors.humans", ChartColor.GREEN); OrganizationMetricHtmlizer.htmlize(data, "http.visitors", organization, view, period, "metrics.http.visitors", ChartColor.GREEN);
OrganizationMetricHtmlizer.htmlize(data, "http.visits.humans", organization, view, period, "metrics.http.visits.humans", ChartColor.GREEN); OrganizationMetricHtmlizer.htmlize(data, "http.visits", organization, view, period, "metrics.http.visits", ChartColor.GREEN);
// //
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricSummaryView.xhtml", data).toString(); String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricSummaryView.xhtml", data).toString();

View file

@ -107,24 +107,29 @@ public class OrganizationMetricWebPage
OrganizationMetricHtmlizer.htmlize(data, "http.ip.ipv4", organization, view, period, "metrics.http.ip.ipv4", ChartColor.YELLOW); OrganizationMetricHtmlizer.htmlize(data, "http.ip.ipv4", organization, view, period, "metrics.http.ip.ipv4", ChartColor.YELLOW);
OrganizationMetricHtmlizer.htmlize(data, "http.ip.ipv6", organization, view, period, "metrics.http.ip.ipv6", ChartColor.GREEN); OrganizationMetricHtmlizer.htmlize(data, "http.ip.ipv6", organization, view, period, "metrics.http.ip.ipv6", ChartColor.GREEN);
OrganizationMetricHtmlizer.htmlize(data, "http.requesters", organization, view, period, "metrics.http.requesters", ChartColor.BLUE);
OrganizationMetricHtmlizer.htmlize(data, "http.requesters-humansbots", organization, view, period, "http.requesters (humans + bots)", "metrics.http.requesters.humans", ChartColor.GREEN,
"metrics.http.requesters.bots", ChartColor.YELLOW);
OrganizationMetricHtmlizer.htmlize(data, "http.requesters.humans", organization, view, period, "metrics.http.requesters.humans", ChartColor.GREEN);
OrganizationMetricHtmlizer.htmlize(data, "http.requesters.bots", organization, view, period, "metrics.http.requesters.bots", ChartColor.YELLOW);
OrganizationMetricHtmlizer.htmlize(data, "http.requesters-ipv4ipv6", organization, view, period, "http.requesters(ipv4 + ipv6)", "metrics.http.requesters.ipv4", ChartColor.YELLOW,
"metrics.http.requesters.ipv6", ChartColor.GREEN);
OrganizationMetricHtmlizer.htmlize(data, "http.requesters.ipv4", organization, view, period, "metrics.http.requesters.ipv4", ChartColor.YELLOW);
OrganizationMetricHtmlizer.htmlize(data, "http.requesters.ipv6", organization, view, period, "metrics.http.requesters.ipv6", ChartColor.GREEN);
OrganizationMetricHtmlizer.htmlize(data, "http.visitors", organization, view, period, "metrics.http.visitors", ChartColor.BLUE); OrganizationMetricHtmlizer.htmlize(data, "http.visitors", organization, view, period, "metrics.http.visitors", ChartColor.BLUE);
OrganizationMetricHtmlizer.htmlize(data, "http.visitors-humansbots", organization, view, period, "http.visitors (humans + bots)", "metrics.http.visitors.humans", ChartColor.GREEN,
"metrics.http.visitors.bots", ChartColor.YELLOW);
OrganizationMetricHtmlizer.htmlize(data, "http.visitors.humans", organization, view, period, "metrics.http.visitors.humans", ChartColor.GREEN);
OrganizationMetricHtmlizer.htmlize(data, "http.visitors.bots", organization, view, period, "metrics.http.visitors.bots", ChartColor.YELLOW);
OrganizationMetricHtmlizer.htmlize(data, "http.visitors-ipv4ipv6", organization, view, period, "http.visitors (ipv4 + ipv6)", "metrics.http.visitors.ipv4", ChartColor.YELLOW, OrganizationMetricHtmlizer.htmlize(data, "http.visitors-ipv4ipv6", organization, view, period, "http.visitors (ipv4 + ipv6)", "metrics.http.visitors.ipv4", ChartColor.YELLOW,
"metrics.http.visitors.ipv6", ChartColor.GREEN); "metrics.http.visitors.ipv6", ChartColor.GREEN);
OrganizationMetricHtmlizer.htmlize(data, "http.visitors.ipv4", organization, view, period, "metrics.http.visitors.ipv4", ChartColor.YELLOW); OrganizationMetricHtmlizer.htmlize(data, "http.visitors.ipv4", organization, view, period, "metrics.http.visitors.ipv4", ChartColor.YELLOW);
OrganizationMetricHtmlizer.htmlize(data, "http.visitors.ipv6", organization, view, period, "metrics.http.visitors.ipv6", ChartColor.GREEN); OrganizationMetricHtmlizer.htmlize(data, "http.visitors.ipv6", organization, view, period, "metrics.http.visitors.ipv6", ChartColor.GREEN);
OrganizationMetricHtmlizer.htmlize(data, "http.visits", organization, view, period, "metrics.http.visits", ChartColor.BLUE); OrganizationMetricHtmlizer.htmlize(data, "http.visits", organization, view, period, "metrics.http.visits", ChartColor.BLUE);
OrganizationMetricHtmlizer.htmlize(data, "http.visits-ipv4ipv6", organization, view, period, "http.visits (ipv4 + ipv6)", "metrics.http.visits.ipv4", ChartColor.YELLOW,
OrganizationMetricHtmlizer.htmlize(data, "http.visits-humansbots", organization, view, period, "http.visits (humans + bots)", "metrics.http.visits.humans", ChartColor.GREEN, "metrics.http.visits.ipv6", ChartColor.GREEN);
"metrics.http.visits.bots", ChartColor.YELLOW); OrganizationMetricHtmlizer.htmlize(data, "http.visits.ipv4", organization, view, period, "metrics.http.visits.ipv4", ChartColor.YELLOW);
OrganizationMetricHtmlizer.htmlize(data, "http.visits.bots", organization, view, period, "metrics.http.visits.bots", ChartColor.YELLOW); OrganizationMetricHtmlizer.htmlize(data, "http.visits.ipv6", organization, view, period, "metrics.http.visits.ipv6", ChartColor.GREEN);
OrganizationMetricHtmlizer.htmlize(data, "http.visits.humans", organization, view, period, "metrics.http.visits.humans", ChartColor.GREEN);
// //
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricWebView.xhtml", data).toString(); String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricWebView.xhtml", data).toString();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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,6 +18,7 @@
*/ */
package fr.devinsy.statoolinfos.htmlize; package fr.devinsy.statoolinfos.htmlize;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -27,6 +28,7 @@ import org.slf4j.LoggerFactory;
import fr.devinsy.statoolinfos.core.Service; import fr.devinsy.statoolinfos.core.Service;
import fr.devinsy.statoolinfos.core.Services; import fr.devinsy.statoolinfos.core.Services;
import fr.devinsy.statoolinfos.core.StatoolInfosException; import fr.devinsy.statoolinfos.core.StatoolInfosException;
import fr.devinsy.statoolinfos.core.StatoolInfosUtils;
import fr.devinsy.xidyn.XidynException; import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.data.DisplayMode; import fr.devinsy.xidyn.data.DisplayMode;
import fr.devinsy.xidyn.data.TagDataManager; import fr.devinsy.xidyn.data.TagDataManager;
@ -67,6 +69,11 @@ public class ServiceListView
} }
else else
{ {
String monthLabel = LocalDate.now().minusMonths(1).format(DateTimeFormatter.ofPattern("MMMM yyyy")).replace(" ", "&#160;");
data.setContent("monthLabel", monthLabel);
data.setAttribute("userCountHeaderColumn", "title", monthLabel);
data.setAttribute("visitCountHeaderColumn", "title", monthLabel);
int index = 0; int index = 0;
for (Service service : services.sortByName()) for (Service service : services.sortByName())
{ {
@ -88,9 +95,8 @@ public class ServiceListView
data.setEscapedContent("serviceListLine", index, "serviceListLineSoftwareLink", service.getSoftwareName()); data.setEscapedContent("serviceListLine", index, "serviceListLineSoftwareLink", service.getSoftwareName());
data.setAttribute("serviceListLine", index, "serviceListLineSoftwareLink", "href", "software-" + service.getSoftwareTechnicalName() + ".xhtml"); data.setAttribute("serviceListLine", index, "serviceListLineSoftwareLink", "href", "software-" + service.getSoftwareTechnicalName() + ".xhtml");
data.setContent("serviceListLine", index, "serviceListLineUserCount", service.getPreviousMonthUserCount()); data.setContent("serviceListLine", index, "serviceListLineUserCount", StatoolInfosUtils.defaultIfZero(service.getPreviousMonthUserCount(), "😢"));
data.setContent("serviceListLine", index, "serviceListLineVisitCount", StatoolInfosUtils.defaultIfZero(service.getPreviousMonthVisitCount(), "😞"));
data.setContent("serviceListLine", index, "serviceListLineVisitCount", service.getPreviousMonthVisitCount());
data.setEscapedContent("serviceListLine", index, "serviceListLineDate", service.getCrawledDate().format(DateTimeFormatter.ofPattern("dd/MM/YYYY"))); data.setEscapedContent("serviceListLine", index, "serviceListLineDate", service.getCrawledDate().format(DateTimeFormatter.ofPattern("dd/MM/YYYY")));
data.setEscapedAttribute("serviceListLine", index, "serviceListLineDate", "title", service.getCrawledDate().format(DateTimeFormatter.ofPattern("HH:mm:ss"))); data.setEscapedAttribute("serviceListLine", index, "serviceListLineDate", "title", service.getCrawledDate().format(DateTimeFormatter.ofPattern("HH:mm:ss")));

View file

@ -70,8 +70,8 @@ public class ServiceMetricSummaryPage
data.setContent("metricMenuView", ServiceMetricMenuView.htmlize(service, TypeMenu.SUMMARY, view, period)); data.setContent("metricMenuView", ServiceMetricMenuView.htmlize(service, TypeMenu.SUMMARY, view, period));
ServiceMetricHtmlizer.htmlize(data, "http.hits.humans", service, view, period, "metrics.http.hits.humans", ChartColor.GREEN); ServiceMetricHtmlizer.htmlize(data, "http.hits.humans", service, view, period, "metrics.http.hits.humans", ChartColor.GREEN);
ServiceMetricHtmlizer.htmlize(data, "http.visitors.humans", service, view, period, "metrics.http.visitors.humans", ChartColor.GREEN); ServiceMetricHtmlizer.htmlize(data, "http.visitors", service, view, period, "metrics.http.visitors", ChartColor.GREEN);
ServiceMetricHtmlizer.htmlize(data, "http.visits.humans", service, view, period, "metrics.http.visits.humans", ChartColor.GREEN); ServiceMetricHtmlizer.htmlize(data, "http.visits", service, view, period, "metrics.http.visits", ChartColor.GREEN);
// //
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricSummaryView.xhtml", data).toString(); String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricSummaryView.xhtml", data).toString();

View file

@ -106,24 +106,29 @@ public class ServiceMetricWebPage
ServiceMetricHtmlizer.htmlize(data, "http.ip.ipv4", service, view, period, "metrics.http.ip.ipv4", ChartColor.YELLOW); ServiceMetricHtmlizer.htmlize(data, "http.ip.ipv4", service, view, period, "metrics.http.ip.ipv4", ChartColor.YELLOW);
ServiceMetricHtmlizer.htmlize(data, "http.ip.ipv6", service, view, period, "metrics.http.ip.ipv6", ChartColor.GREEN); ServiceMetricHtmlizer.htmlize(data, "http.ip.ipv6", service, view, period, "metrics.http.ip.ipv6", ChartColor.GREEN);
ServiceMetricHtmlizer.htmlize(data, "http.visitors", service, view, period, "metrics.http.ip", ChartColor.BLUE); ServiceMetricHtmlizer.htmlize(data, "http.requesters", service, view, period, "metrics.http.requesters", ChartColor.BLUE);
ServiceMetricHtmlizer.htmlize(data, "http.visitors-humansbots", service, view, period, "http.visitors (humans + bots)", "metrics.http.visitors.humans", ChartColor.GREEN, ServiceMetricHtmlizer.htmlize(data, "http.requesters-humansbots", service, view, period, "http.requesters (humans + bots)", "metrics.http.requesters.humans", ChartColor.GREEN,
"metrics.http.visitors.bots", ChartColor.YELLOW); "metrics.http.requesters.bots", ChartColor.YELLOW);
ServiceMetricHtmlizer.htmlize(data, "http.visitors.humans", service, view, period, "metrics.http.visitors.humans", ChartColor.GREEN); ServiceMetricHtmlizer.htmlize(data, "http.requesters.humans", service, view, period, "metrics.http.requesters.humans", ChartColor.GREEN);
ServiceMetricHtmlizer.htmlize(data, "http.visitors.bots", service, view, period, "metrics.http.visitors.bots", ChartColor.YELLOW); ServiceMetricHtmlizer.htmlize(data, "http.requesters.bots", service, view, period, "metrics.http.requesters.bots", ChartColor.YELLOW);
ServiceMetricHtmlizer.htmlize(data, "http.requesters-ipv4ipv6", service, view, period, "http.requesters (ipv4 + ipv6)", "metrics.http.requesters.ipv4", ChartColor.YELLOW,
"metrics.http.requesters.ipv6", ChartColor.GREEN);
ServiceMetricHtmlizer.htmlize(data, "http.requesters.ipv4", service, view, period, "metrics.http.requesters.ipv4", ChartColor.YELLOW);
ServiceMetricHtmlizer.htmlize(data, "http.requesters.ipv6", service, view, period, "metrics.http.requesters.ipv6", ChartColor.GREEN);
ServiceMetricHtmlizer.htmlize(data, "http.visitors", service, view, period, "metrics.http.visitors", ChartColor.BLUE);
ServiceMetricHtmlizer.htmlize(data, "http.visitors-ipv4ipv6", service, view, period, "http.visitors (ipv4 + ipv6)", "metrics.http.visitors.ipv4", ChartColor.YELLOW, ServiceMetricHtmlizer.htmlize(data, "http.visitors-ipv4ipv6", service, view, period, "http.visitors (ipv4 + ipv6)", "metrics.http.visitors.ipv4", ChartColor.YELLOW,
"metrics.http.visitors.ipv6", ChartColor.GREEN); "metrics.http.visitors.ipv6", ChartColor.GREEN);
ServiceMetricHtmlizer.htmlize(data, "http.visitors.ipv4", service, view, period, "metrics.http.visitors.ipv4", ChartColor.YELLOW); ServiceMetricHtmlizer.htmlize(data, "http.visitors.ipv4", service, view, period, "metrics.http.visitors.ipv4", ChartColor.YELLOW);
ServiceMetricHtmlizer.htmlize(data, "http.visitors.ipv6", service, view, period, "metrics.http.visitors.ipv6", ChartColor.GREEN); ServiceMetricHtmlizer.htmlize(data, "http.visitors.ipv6", service, view, period, "metrics.http.visitors.ipv6", ChartColor.GREEN);
ServiceMetricHtmlizer.htmlize(data, "http.visits", service, view, period, "metrics.http.visits", ChartColor.BLUE); ServiceMetricHtmlizer.htmlize(data, "http.visits", service, view, period, "metrics.http.visits", ChartColor.BLUE);
ServiceMetricHtmlizer.htmlize(data, "http.visits-ipv4ipv6", service, view, period, "http.visits (ipv4 + ipv6)", "metrics.http.visits.ipv4", ChartColor.YELLOW,
ServiceMetricHtmlizer.htmlize(data, "http.visits-humansbots", service, view, period, "http.visits (humans + bots)", "metrics.http.visits.humans", ChartColor.GREEN, "metrics.http.visits.ipv6", ChartColor.GREEN);
"metrics.http.visits.bots", ChartColor.YELLOW); ServiceMetricHtmlizer.htmlize(data, "http.visits.ipv4", service, view, period, "metrics.http.visits.ipv4", ChartColor.YELLOW);
ServiceMetricHtmlizer.htmlize(data, "http.visits.bots", service, view, period, "metrics.http.visits.bots", ChartColor.YELLOW); ServiceMetricHtmlizer.htmlize(data, "http.visits.ipv6", service, view, period, "metrics.http.visits.ipv6", ChartColor.GREEN);
ServiceMetricHtmlizer.htmlize(data, "http.visits.humans", service, view, period, "metrics.http.visits.humans", ChartColor.GREEN);
// //
String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricWebView.xhtml", data).toString(); String content = PresenterUtils.dynamize("/fr/devinsy/statoolinfos/htmlize/serviceMetricWebView.xhtml", data).toString();

View file

@ -53,7 +53,7 @@ public class ServicesPage
File htmlizeDirectory = HtmlizerContext.instance().getHtmlizeDirectory(); File htmlizeDirectory = HtmlizerContext.instance().getHtmlizeDirectory();
logger.info("Htmlize services page."); logger.info("Htmlize services page.");
String page = ServicesPage.htmlize(federation.getServicesAll()); String page = ServicesPage.htmlize(federation.getServices());
FileUtils.write(new File(htmlizeDirectory, "services.xhtml"), page, StandardCharsets.UTF_8); FileUtils.write(new File(htmlizeDirectory, "services.xhtml"), page, StandardCharsets.UTF_8);
} }

View file

@ -58,7 +58,7 @@ public class SoftwarePage
Softwares catalog = federation.getSoftwares(); Softwares catalog = federation.getSoftwares();
for (Software software : catalog.values()) for (Software software : catalog.values())
{ {
Services services = federation.getServicesAll().getBy(software); Services services = federation.getServices().getBy(software);
String page = SoftwarePage.htmlize(software, services); String page = SoftwarePage.htmlize(software, services);
FileUtils.write(new File(htmlizeDirectory, "software-" + software.getTechnicalName() + ".xhtml"), page, StandardCharsets.UTF_8); FileUtils.write(new File(htmlizeDirectory, "software-" + software.getTechnicalName() + ".xhtml"), page, StandardCharsets.UTF_8);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2021-2022 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.
* *
@ -156,7 +156,7 @@ public class UptimeView
} }
int index = 0; int index = 0;
for (Service service : services.getBy(Service.Status.OK).sortByName()) for (Service service : services.sortByName())
{ {
// //
data.setAttribute("line", index, "lineLogo", "src", service.getLogoFileName()); data.setAttribute("line", index, "lineLogo", "src", service.getLogoFileName());

View file

@ -21,19 +21,7 @@
<ul> <ul>
<li><a href="https://forge.devinsy.fr/devinsy/statoolinfos">https://forge.devinsy.fr/devinsy/statoolinfos</a></li> <li><a href="https://forge.devinsy.fr/devinsy/statoolinfos">https://forge.devinsy.fr/devinsy/statoolinfos</a></li>
</ul> </ul>
<p>Contributors:</p> <p>Contributors: Angie, MrFlos, Quentin Duchemin, Fabrice61, Thomas @TConstans, @labecasse, Antoine Jaba, @setop, Jérémy Collot,
<ul> Pilou, Kepon, Laurent Sleto…</p>
<li>Angie</li>
<li>MrFlos</li>
<li>Quentin Duchemin</li>
<li>Fabrice61</li>
<li>Thomas @TConstans</li>
<li>@labecasse</li>
<li>Antoine Jaba</li>
<li>@setop</li>
<li>Jérémy Collot</li>
<li>Pilou</li>
<li>Kepon</li>
</ul>
</body> </body>
</html> </html>

View file

@ -21,8 +21,8 @@
<th style="width: 200px;">Membre</th> <th style="width: 200px;">Membre</th>
<th style="width: 250px;">URL</th> <th style="width: 250px;">URL</th>
<th style="width: 10px;">Services</th> <th style="width: 10px;">Services</th>
<th style="width: 10px;">Utilisateurs mensuels</th> <th id="userCountHeaderColumn" style="width: 10px;">Utilisateurs mensuels<sup>*</sup></th>
<th style="width: 10px;">Visites mensuelles</th> <th id="visitCountHeaderColumn" style="width: 10px;">Visites mensuelles<sup>*</sup></th>
<th style="width: 10px;">Date</th> <th style="width: 10px;">Date</th>
</tr> </tr>
</thead> </thead>
@ -42,19 +42,53 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div id="month_asterisk">(*) chiffres de <span id="monthLabel">n/a</span></div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() $(document).ready(function()
{ {
$.fn.dataTable.moment( 'DD/MM/YYYY' ); $.fn.dataTable.moment('DD/MM/YYYY');
$.extend($.fn.dataTable.ext.type.order,
{
"custom-sort-asc": function(x, y)
{
if (!(!isNaN(x) || !isNaN(y)))
return 0;
else if (isNaN(x))
return -1;
else if (isNaN(y))
return +1;
else
return x-y;
},
"custom-sort-desc": function(x, y)
{
if (!(!isNaN(x) || !isNaN(y)))
return 0;
else if (isNaN(x))
return +1;
else if (isNaN(y))
return -1;
else
return y-x;
}
} );
$('#organizations').DataTable( $('#organizations').DataTable(
{ {
paging: false, paging: false,
ordering: true, ordering: true,
"order": [[ 2, "desc" ]], "order": [[ 2, "desc" ]],
language: dataTableFrench language: dataTableFrench,
}); "columnDefs":
[
{ targets: 2, "type": 'custom-sort' },
{ targets: 3, "type": 'custom-sort' },
{ targets: 4, "type": 'custom-sort' }
]
});
} ); } );
</script> </script>
</body> </body>

View file

@ -52,8 +52,8 @@
<th class="" style="width: 225px;">Organisation</th> <th class="" style="width: 225px;">Organisation</th>
<th class="">URL</th> <th class="">URL</th>
<th class="">Logiciel</th> <th class="">Logiciel</th>
<th class="" style="width: 100px;">Utilisateurs mensuels</th> <th id="userCountHeaderColumn" class="" style="width: 100px;">Utilisateurs mensuels<sup>*</sup></th>
<th class="" style="width: 10px;">Visites mensuelles</th> <th id="visitCountHeaderColumn" class="" style="width: 10px;">Visites mensuelles<sup>*</sup></th>
<th class="" style="width: 25px;">Statut</th> <th class="" style="width: 25px;">Statut</th>
<th class="" style="width: 25px;" colspan="5">Inscription</th> <th class="" style="width: 25px;" colspan="5">Inscription</th>
<th class="" style="width: 25px;" colspan="5">Liens</th> <th class="" style="width: 25px;" colspan="5">Liens</th>
@ -131,19 +131,51 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div id="month_asterisk">(*) chiffres de <span id="monthLabel">n/a</span></div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() $(document).ready(function()
{ {
$.fn.dataTable.moment( 'DD/MM/YYYY' ); $.fn.dataTable.moment('DD/MM/YYYY');
$.extend($.fn.dataTable.ext.type.order,
{
"custom-sort-asc": function(x, y)
{
if (!(!isNaN(x) || !isNaN(y)))
return 0;
else if (isNaN(x))
return -1;
else if (isNaN(y))
return +1;
else
return x-y;
},
"custom-sort-desc": function(x, y)
{
if (!(!isNaN(x) || !isNaN(y)))
return 0;
else if (isNaN(x))
return +1;
else if (isNaN(y))
return -1;
else
return y-x;
}
} );
$('#serviceListTable').DataTable( $('#serviceListTable').DataTable(
{ {
paging: false, paging: false,
ordering: true, ordering: true,
"order": [[ 2, "desc" ]], "order": [[ 2, "desc" ]],
language: dataTableFrench language: dataTableFrench,
}); "columnDefs":
[
{ targets: 4, "type": 'custom-sort' },
{ targets: 5, "type": 'custom-sort' }
]
});
}); });
</script> </script>
</body> </body>

View file

@ -16,8 +16,8 @@
<div id="metricMenuView" /> <div id="metricMenuView" />
<div id="charts" style="display: block;"> <div id="charts" style="display: block;">
<div id="http.hits.humans" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.hits.humans" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.visitors.humans" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.visitors" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.visits.humans" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.visits" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
</div> </div>
</div> </div>
</body> </body>

View file

@ -50,23 +50,31 @@
<div id="http.ip.humans" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.ip.humans" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.ip.bots" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.ip.bots" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<h2>http.visitors</h2> <h2>http.requesters</h2>
<div id="http.requesters" style="width: 450px; height: 300px; border: 1px solid #e7e7e7;"/>
<div id="http.requesters-ipv4ipv6" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.requesters.ipv4" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.requesters.ipv6" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<br/>
<div id="http.requesters-humansbots" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.requesters.humans" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.requesters.bots" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<h2>Visiteurs</h2>
<div id="http.visitors" style="width: 450px; height: 300px; border: 1px solid #e7e7e7;"/> <div id="http.visitors" style="width: 450px; height: 300px; border: 1px solid #e7e7e7;"/>
<div id="http.visitors-ipv4ipv6" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.visitors-ipv4ipv6" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.visitors.ipv4" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.visitors.ipv4" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.visitors.ipv6" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.visitors.ipv6" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<br/>
<div id="http.visitors-humansbots" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.visitors.humans" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.visitors.bots" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<h2>http.visits</h2> <h2>Visites</h2>
<div id="http.visits" style="width: 450px; height: 300px; border: 1px solid #e7e7e7;"/> <div id="http.visits" style="width: 450px; height: 300px; border: 1px solid #e7e7e7;"/>
<div id="http.visits-humansbots" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.visits-ipv4ipv6" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.visits.humans" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.visits.ipv4" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<div id="http.visits.bots" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/> <div id="http.visits.ipv6" style="width: 450px; height: 300px; display: inline-block; border: 1px solid #e7e7e7;"/>
<br/>
</div> </div>
</div> </div>
</body> </body>

File diff suppressed because one or more lines are too long

View file

@ -21,6 +21,7 @@ package fr.devinsy.statoolinfos.metrics.http;
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.Pattern;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -35,6 +36,8 @@ public class HttpAccessLog
{ {
private static Logger logger = LoggerFactory.getLogger(HttpAccessLog.class); private static Logger logger = LoggerFactory.getLogger(HttpAccessLog.class);
public static final Pattern ASSET_PATTERN = Pattern.compile("^.*\\.(avi|css|gif|ico|jpeg|jpg|js|mp3|mp4|ogg|png|svg|wav) HTTP.*$");
private String ip; private String ip;
private String remoteUser; private String remoteUser;
private LocalDateTime time; private LocalDateTime time;
@ -79,6 +82,36 @@ public class HttpAccessLog
return this.ip; return this.ip;
} }
/**
* Gets the method.
*
* @return the method
*/
public HttpMethod getMethod()
{
HttpMethod result;
if (this.request == null)
{
result = HttpMethod.UNKNOWN;
}
else
{
int space = this.request.indexOf(' ');
if (space == -1)
{
result = HttpMethod.UNKNOWN;
}
else
{
result = HttpMethod.of(this.request.substring(0, space));
}
}
//
return result;
}
public String getReferer() public String getReferer()
{ {
return this.referer; return this.referer;
@ -231,6 +264,29 @@ public class HttpAccessLog
return result; return result;
} }
/**
* Checks if is visit.
*
* @return true, if is visit
*/
public boolean isVisit()
{
boolean result;
if ((this.status.getCategory() == HttpStatusCategory.SUCCESS) && (!isBot()) && (this.request.startsWith("GET ")) &&
(!ASSET_PATTERN.matcher(this.request).matches()))
{
result = true;
}
else
{
result = false;
}
//
return result;
}
public void setBodyBytesSent(final long bodyBytesSent) public void setBodyBytesSent(final long bodyBytesSent)
{ {
this.bodyBytesSent = bodyBytesSent; this.bodyBytesSent = bodyBytesSent;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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.
* *
@ -47,23 +47,26 @@ public class HttpAccessLogAnalyzer
// '"$request" $status $body_bytes_sent ' // '"$request" $status $body_bytes_sent '
// '"$http_referer" "$http_user_agent"'; // '"$http_referer" "$http_user_agent"';
public static final Pattern COMBINED_PATTERN = Pattern.compile( public static final Pattern COMBINED_PATTERN = Pattern.compile(
"^(?<remoteAddress>[a-zA-F0-9\\\\:\\\\.]+) - (?<remoteUser>[^\\[]+) \\[(?<time>[^\\]]+)\\] \"(?<request>[^\"]*)\" (?<status>\\d+) (?<bodyBytesSent>\\d+) \"(?<referer>[^\"]*)\" \"(?<userAgent>[^\"]*)\".*$"); "^(?<remoteAddress>[a-zA-F0-9\\\\:\\\\.]+) - (?<remoteUser>[^\\[]+) \\[(?<time>[^\\]]+)\\] \"(?<request>.*)\" (?<status>\\d+) (?<bodyBytesSent>\\d+) \"(?<referer>.*)\" \"(?<userAgent>[^\"]*)\".*$");
private int errorCount; private int errorCount;
private PathCounters counters; private PathCounters counters;
private VisitCounters visits;
private VisitCounters botVisits;
private VisitCounters humanVisits;
private IpCounters ips; private IpCounters ips;
private IpCounters ipv4; private IpCounters ipv4;
private IpCounters ipv6; private IpCounters ipv6;
private IpCounters botIps; private IpCounters botIps;
private IpCounters humanIps; private IpCounters humanIps;
private VisitorCounters requesters;
private VisitorCounters ipv4Requesters;
private VisitorCounters ipv6Requesters;
private VisitorCounters botRequesters;
private VisitorCounters humanRequesters;
private VisitCounters visits;
private VisitCounters ipv4Visits;
private VisitCounters ipv6Visits;
private VisitorCounters visitors; private VisitorCounters visitors;
private VisitorCounters ipv4Visitors; private VisitorCounters ipv4Visitors;
private VisitorCounters ipv6Visitors; private VisitorCounters ipv6Visitors;
private VisitorCounters botVisitors;
private VisitorCounters humanVisitors;
/** /**
* Instantiates a new http access log prober. * Instantiates a new http access log prober.
@ -71,20 +74,25 @@ public class HttpAccessLogAnalyzer
public HttpAccessLogAnalyzer() public HttpAccessLogAnalyzer()
{ {
this.counters = new PathCounters(); this.counters = new PathCounters();
this.visits = new VisitCounters();
this.botVisits = new VisitCounters();
this.humanVisits = new VisitCounters();
this.ips = new IpCounters(); this.ips = new IpCounters();
this.ipv4 = new IpCounters(); this.ipv4 = new IpCounters();
this.ipv6 = new IpCounters(); this.ipv6 = new IpCounters();
this.botIps = new IpCounters(); this.botIps = new IpCounters();
this.humanIps = new IpCounters(); this.humanIps = new IpCounters();
this.requesters = new VisitorCounters();
this.ipv4Requesters = new VisitorCounters();
this.ipv6Requesters = new VisitorCounters();
this.humanRequesters = new VisitorCounters();
this.botRequesters = new VisitorCounters();
this.visits = new VisitCounters();
this.ipv4Visits = new VisitCounters();
this.ipv6Visits = new VisitCounters();
this.visitors = new VisitorCounters(); this.visitors = new VisitorCounters();
this.ipv4Visitors = new VisitorCounters(); this.ipv4Visitors = new VisitorCounters();
this.ipv6Visitors = new VisitorCounters(); this.ipv6Visitors = new VisitorCounters();
this.botVisitors = new VisitorCounters();
this.humanVisitors = new VisitorCounters();
} }
/** /**
@ -105,15 +113,19 @@ public class HttpAccessLogAnalyzer
result.putAll(this.botIps.getCounters("metrics.http.ip.bots")); result.putAll(this.botIps.getCounters("metrics.http.ip.bots"));
result.putAll(this.humanIps.getCounters("metrics.http.ip.humans")); result.putAll(this.humanIps.getCounters("metrics.http.ip.humans"));
result.putAll(this.requesters.getCounters("metrics.http.requesters"));
result.putAll(this.ipv4Requesters.getCounters("metrics.http.requesters.ipv4"));
result.putAll(this.ipv6Requesters.getCounters("metrics.http.requesters.ipv6"));
result.putAll(this.botRequesters.getCounters("metrics.http.requesters.bots"));
result.putAll(this.humanRequesters.getCounters("metrics.http.requesters.humans"));
result.putAll(this.visits.getCounters("metrics.http.visits")); result.putAll(this.visits.getCounters("metrics.http.visits"));
result.putAll(this.botVisits.getCounters("metrics.http.visits.bots")); result.putAll(this.ipv4Visits.getCounters("metrics.http.visits.ipv4"));
result.putAll(this.humanVisits.getCounters("metrics.http.visits.humans")); result.putAll(this.ipv6Visits.getCounters("metrics.http.visits.ipv6"));
result.putAll(this.visitors.getCounters("metrics.http.visitors")); result.putAll(this.visitors.getCounters("metrics.http.visitors"));
result.putAll(this.ipv4Visitors.getCounters("metrics.http.visitors.ipv4")); result.putAll(this.ipv4Visitors.getCounters("metrics.http.visitors.ipv4"));
result.putAll(this.ipv6Visitors.getCounters("metrics.http.visitors.ipv6")); result.putAll(this.ipv6Visitors.getCounters("metrics.http.visitors.ipv6"));
result.putAll(this.botVisitors.getCounters("metrics.http.visitors.bots"));
result.putAll(this.humanVisitors.getCounters("metrics.http.visitors.humans"));
// //
return result; return result;
@ -237,7 +249,7 @@ public class HttpAccessLogAnalyzer
} }
// metrics.http.pages.* = // metrics.http.pages.* =
if ((isPage(log.getRequest())) && (log.getStatus().getCategory() == HttpStatusCategory.SUCCESS)) if ((log.getStatus().getCategory() == HttpStatusCategory.SUCCESS) && (isPage(log.getRequest())))
{ {
this.counters.inc("metrics.http.pages", year, yearMonth, yearWeek, date); this.counters.inc("metrics.http.pages", year, yearMonth, yearWeek, date);
} }
@ -267,48 +279,75 @@ public class HttpAccessLogAnalyzer
this.humanIps.put(log.getIp(), year, yearMonth, yearWeek, date); this.humanIps.put(log.getIp(), year, yearMonth, yearWeek, date);
} }
// metrics.http.visits.* = // metrics.http.requesters.* =
this.visits.putVisit(log); this.requesters.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date);
this.visits.storeTimeMarks(year, yearMonth, yearWeek, date);
if (log.isBot()) // metrics.http.requesters.ipv4.* =
{ // metrics.http.requesters.ipv6.* =
this.botVisits.putVisit(log);
this.botVisits.storeTimeMarks(year, yearMonth, yearWeek, date);
}
else
{
this.humanVisits.putVisit(log);
this.humanVisits.storeTimeMarks(year, yearMonth, yearWeek, date);
}
//
// metrics.http.visitors.* =
this.visitors.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date);
// metrics.http.visitors.ipv4.* =
// metrics.http.visitors.ipv6.* =
if (log.isIPv4()) if (log.isIPv4())
{ {
this.ipv4Visitors.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date); this.ipv4Requesters.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date);
} }
else else
{ {
this.ipv6Visitors.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date); this.ipv6Requesters.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date);
} }
// metrics.http.visitors.bots.* // metrics.http.requesters.bots.*
// metrics.http.visitors.humans.* // metrics.http.requesters.humans.*
if (log.isBot()) if (log.isBot())
{ {
this.botVisitors.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date); this.botRequesters.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date);
} }
else else
{ {
this.humanVisitors.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date); this.humanRequesters.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date);
} }
// metrics.http.visits.* =
// metrics.http.visits.ipv4.* =
// metrics.http.visits.ipv6.* =
// metrics.http.visitors.* =
// metrics.http.visitors.ipv4.* =
// metrics.http.visitors.ipv6.* =
if (log.isVisit())
{
// metrics.http.visits.* =
// metrics.http.visits.ipv4.* =
// metrics.http.visits.ipv6.* =
this.visits.putVisit(log);
this.visits.storeTimeMarks(year, yearMonth, yearWeek, date);
if (log.isIPv4())
{
this.ipv4Visits.putVisit(log);
this.ipv4Visits.storeTimeMarks(year, yearMonth, yearWeek, date);
}
else
{
this.ipv6Visits.putVisit(log);
this.ipv6Visits.storeTimeMarks(year, yearMonth, yearWeek, date);
}
// metrics.http.visitors.* =
// metrics.http.visitors.ipv4.* =
// metrics.http.visitors.ipv6.* =
this.visitors.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date);
if (log.isIPv4())
{
this.ipv4Visitors.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date);
}
else
{
this.ipv6Visitors.put(log.getIp(), log.getUserAgent(), year, yearMonth, yearWeek, date);
}
}
// metrics.http.methods.XXXX
String method = log.getMethod().toString();
this.counters.inc("metrics.http.methods." + method, year, yearMonth, yearWeek, date);
// metrics.http.status.XXXX // metrics.http.status.XXXX
String status = String.valueOf(log.getStatus().getCode()); String status = String.valueOf(log.getStatus().getCode());
this.counters.inc("metrics.http.status." + status, year, yearMonth, yearWeek, date); this.counters.inc("metrics.http.status." + status, year, yearMonth, yearWeek, date);

View file

@ -84,6 +84,8 @@ public class HttpErrorLogAnalyzer
{ {
if ((file != null) && (!file.isFile()) || (file.exists())) if ((file != null) && (!file.isFile()) || (file.exists()))
{ {
System.out.println("Probing file [" + file.getAbsolutePath() + "]");
// //
Pattern pattern; Pattern pattern;
if (LineIterator.readFirstLine(file).startsWith("[")) if (LineIterator.readFirstLine(file).startsWith("["))
@ -167,7 +169,14 @@ public class HttpErrorLogAnalyzer
if (matcher.matches()) if (matcher.matches())
{ {
result = new HttpErrorLog(); result = new HttpErrorLog();
result.setTime(LocalDateTime.parse(matcher.group("time"), DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss.SSSSSS yyyy").withLocale(Locale.ENGLISH))); if (pattern == APACHE_ERROR_PATTERN)
{
result.setTime(LocalDateTime.parse(matcher.group("time"), DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss.SSSSSS yyyy").withLocale(Locale.ENGLISH)));
}
else if (pattern == NGINX_ERROR_PATTERN)
{
result.setTime(LocalDateTime.parse(matcher.group("time"), DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss").withLocale(Locale.ENGLISH)));
}
result.setLevel(matcher.group("level")); result.setLevel(matcher.group("level"));
} }
else else

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2022 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.metrics.http;
/**
* The Class HttpMethod.
*/
public enum HttpMethod
{
GET,
HEAD,
POST,
OPTIONS,
CONNECT,
TRACE,
PUT,
PATCH,
DELETE,
UNKNOWN;
/**
* Parses the.
*
* @param value
* the value
* @return the http method
*/
public static HttpMethod of(final String value)
{
HttpMethod result;
if (value == null)
{
result = null;
}
else
{
try
{
result = valueOf(value);
}
catch (IllegalArgumentException exception)
{
result = UNKNOWN;
}
}
//
return result;
}
}

View file

@ -47,6 +47,8 @@ public class UserAgent
/** /**
* Gets the browser. * Gets the browser.
*
* WARNING: MUST BE GREATLY IMPROVED
* *
* @return the browser * @return the browser
*/ */
@ -54,18 +56,34 @@ public class UserAgent
{ {
UserAgentBrowser result; UserAgentBrowser result;
if (StringUtils.containsIgnoreCase(this.source, "Firefox")) if (StringUtils.containsIgnoreCase(this.source, "Chrome/"))
{
result = UserAgentBrowser.FIREFOX;
}
else if (StringUtils.containsIgnoreCase(this.source, "Chrome"))
{ {
result = UserAgentBrowser.CHROME; result = UserAgentBrowser.CHROME;
} }
else if (StringUtils.containsIgnoreCase(this.source, "Chromium/"))
{
result = UserAgentBrowser.CHROMIUM;
}
else if (StringUtils.containsIgnoreCase(this.source, "Firefox/"))
{
result = UserAgentBrowser.FIREFOX;
}
else if (StringUtils.containsIgnoreCase(this.source, "Lynx")) else if (StringUtils.containsIgnoreCase(this.source, "Lynx"))
{ {
result = UserAgentBrowser.LYNX; result = UserAgentBrowser.LYNX;
} }
else if (StringUtils.containsIgnoreCase(this.source, "MSIE "))
{
result = UserAgentBrowser.MSIE;
}
else if (StringsUtils.containsAnyIgnoreCase(this.source, "Opera", "OPR/"))
{
result = UserAgentBrowser.OPERA;
}
else if (StringUtils.containsIgnoreCase(this.source, "Safari/"))
{
result = UserAgentBrowser.SAFARI;
}
else else
{ {
result = UserAgentBrowser.OTHER; result = UserAgentBrowser.OTHER;
@ -77,6 +95,8 @@ public class UserAgent
/** /**
* Gets the device. * Gets the device.
*
* WARNING: MUST BE GREATLY IMPROVED
* *
* @return the device * @return the device
*/ */
@ -84,13 +104,21 @@ public class UserAgent
{ {
UserAgentDevice result; UserAgentDevice result;
if (StringsUtils.containsAnyIgnoreCase(this.source, "iOS", "Android")) if (StringsUtils.containsAnyIgnoreCase(this.source, "Playstation"))
{
result = UserAgentDevice.CONSOLE;
}
else if (StringsUtils.containsAnyIgnoreCase(this.source, "Desktop"))
{
result = UserAgentDevice.PC;
}
else if (StringsUtils.containsAnyIgnoreCase(this.source, "Android", "iPhone"))
{ {
result = UserAgentDevice.PHONE; result = UserAgentDevice.PHONE;
} }
else if (StringsUtils.containsAnyIgnoreCase(this.source, "Playstation")) else if (StringsUtils.containsAnyIgnoreCase(this.source, "iPad"))
{ {
result = UserAgentDevice.CONSOLE; result = UserAgentDevice.TABLET;
} }
else else
{ {
@ -110,18 +138,42 @@ public class UserAgent
{ {
UserAgentOS result; UserAgentOS result;
if (StringUtils.containsIgnoreCase(this.source, "Firefox")) if (StringUtils.containsIgnoreCase(this.source, "Android"))
{ {
result = UserAgentOS.ANDROID; result = UserAgentOS.ANDROID;
} }
else if (StringUtils.containsIgnoreCase(this.source, "Chrome")) else if (StringUtils.containsIgnoreCase(this.source, "FreeBSD"))
{ {
result = UserAgentOS.FREEBSD; result = UserAgentOS.FREEBSD;
} }
else if (StringUtils.containsIgnoreCase(this.source, "Lynx")) else if (StringsUtils.containsAnyIgnoreCase(this.source, "Debian", "Gentoo", "Linux aarch", "Linux arm", "Linux i586", "Linux i686", "Linux x64", "Linux x86_64"))
{ {
result = UserAgentOS.GNULINUX; result = UserAgentOS.GNULINUX;
} }
else if (StringsUtils.containsAnyIgnoreCase(this.source, "Debian", "Gentoo", "Linux aarch", "Linux arm", "Linux i586", "Linux i686", "Linux x64", "Linux x86_64"))
{
result = UserAgentOS.GNULINUX;
}
else if (StringsUtils.containsAnyIgnoreCase(this.source, "iPhone"))
{
result = UserAgentOS.IOS;
}
else if (StringsUtils.containsAnyIgnoreCase(this.source, "Macintosh", "Mac OS X", "Mac OS Desktop"))
{
result = UserAgentOS.MACOS;
}
else if (StringUtils.containsIgnoreCase(this.source, "windows"))
{
result = UserAgentOS.MSWINDOWS;
}
else if (StringUtils.containsIgnoreCase(this.source, "NetBSD"))
{
result = UserAgentOS.NETBSD;
}
else if (StringUtils.containsIgnoreCase(this.source, "OpenBSD"))
{
result = UserAgentOS.OPENBSD;
}
else else
{ {
result = UserAgentOS.OTHER; result = UserAgentOS.OTHER;
@ -134,6 +186,8 @@ public class UserAgent
/** /**
* Gets the type. * Gets the type.
* *
* WARNING: MUST BE GREATLY IMPROVED
*
* @return the type * @return the type
*/ */
public UserAgentType getType() public UserAgentType getType()

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2021-2022 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,6 +18,9 @@
*/ */
package fr.devinsy.statoolinfos.metrics.http; package fr.devinsy.statoolinfos.metrics.http;
/**
* The Enum UserAgentOS.
*/
public enum UserAgentOS public enum UserAgentOS
{ {
ANDROID, ANDROID,
@ -28,5 +31,5 @@ public enum UserAgentOS
MACOS, MACOS,
NETBSD, NETBSD,
OPENBSD, OPENBSD,
OTHER OTHER,
} }

View file

@ -176,7 +176,7 @@ public class VisitCounters extends HashMap<String, Visits>
*/ */
public void putVisit(final HttpAccessLog log) public void putVisit(final HttpAccessLog log)
{ {
if ((log != null) && (log.getStatus().getCategory() == HttpStatusCategory.SUCCESS)) if (log != null)
{ {
String key = computeKey(log); String key = computeKey(log);

View file

@ -13,8 +13,10 @@ HeadlessChrome/
^Go-http-client ^Go-http-client
^GoModuleMirror/ ^GoModuleMirror/
^HotJava/ ^HotJava/
internal dummy connection
^Java/ ^Java/
^JGit/ ^JGit/
Let's Encrypt validation server;
^MastoPeek ^MastoPeek
^mattermost- ^mattermost-
^Misskey/ ^Misskey/

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2021-2022 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.
* *
@ -83,6 +83,7 @@ public class MinetestLogAnalyzer
result.putAll(this.counters); result.putAll(this.counters);
result.putAll(this.activePlayers.getCounters("metrics.service.users")); result.putAll(this.activePlayers.getCounters("metrics.service.users"));
result.putAll(this.activePlayers.getCounters("metrics.service.accounts.active"));
result.putAll(this.ips.getCounters("metrics.service.ip")); result.putAll(this.ips.getCounters("metrics.service.ip"));
result.putAll(this.ipv4.getCounters("metrics.service.ip.ipv4")); result.putAll(this.ipv4.getCounters("metrics.service.ip.ipv4"));
result.putAll(this.ipv6.getCounters("metrics.service.ip.ipv6")); result.putAll(this.ipv6.getCounters("metrics.service.ip.ipv6"));
@ -161,6 +162,7 @@ public class MinetestLogAnalyzer
// metrics.metaverse.logs.warning // metrics.metaverse.logs.warning
// metrics.metaverse.logs.error // metrics.metaverse.logs.error
// metrics.metaverse.logs.none // metrics.metaverse.logs.none
// metrics.metaverse.logs.unknown
if (log.getLevel() == MinetestLogLevel.ACTION) if (log.getLevel() == MinetestLogLevel.ACTION)
{ {
this.counters.inc("metrics.metaverse.logs.action", year, yearMonth, yearWeek, date); this.counters.inc("metrics.metaverse.logs.action", year, yearMonth, yearWeek, date);
@ -182,14 +184,13 @@ public class MinetestLogAnalyzer
this.counters.inc("metrics.metaverse.logs.unknown", year, yearMonth, yearWeek, date); this.counters.inc("metrics.metaverse.logs.unknown", year, yearMonth, yearWeek, date);
} }
// metrics.metaverse.players.active // metrics.service.users (= metrics.metaverse.players.active)
// metrics.service.users
this.activePlayers.put(log.getNickname(), year, yearMonth, yearWeek, date); this.activePlayers.put(log.getNickname(), year, yearMonth, yearWeek, date);
// metrics.metaverse.players.max // metrics.metaverse.players.max
// TODO // TODO
// metrics.metaverse.joiners -- // metrics.metaverse.joiners
if (log.getMessage().contains(" joins game.")) if (log.getMessage().contains(" joins game."))
{ {
this.counters.inc("metrics.metaverse.joiners", year, yearMonth, yearWeek, date); this.counters.inc("metrics.metaverse.joiners", year, yearMonth, yearWeek, date);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2021-2022 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.
* *
@ -55,12 +55,24 @@ public class MinetestProber
{ {
PathCounters result; PathCounters result;
// metrics.service.users, metrics.service.accounts.active
// metrics.metaverse.joiners
// metrics.service.ip
// metrics.service.ip.ipv4
// metrics.service.ip.ipv6
// metrics.metaverse.logs
// metrics.metaverse.logs.action
// metrics.metaverse.logs.warning
// metrics.metaverse.logs.error
// metrics.metaverse.logs.none
// metrics.metaverse.logs.unknown
result = MinetestLogAnalyzer.probe(logs); result = MinetestLogAnalyzer.probe(logs);
// metrics.metaverse.players // result.putAll(MumbleDatabaseAnalyzer.probe());
// accounts // metrics.service.accounts
// database size // metrics.service.database.bytes
// file size
// metrics.service.files.bytes
// //
return result; return result;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org> * Copyright (C) 2020-2022 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.
* *
@ -21,8 +21,11 @@ package fr.devinsy.statoolinfos.properties;
import java.io.File; import java.io.File;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.time.LocalDate;
import java.time.Year; import java.time.Year;
import java.time.YearMonth; import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -255,22 +258,13 @@ public class PathPropertyList extends ArrayList<PathProperty> implements PathPro
pattern = prefix + "."; pattern = prefix + ".";
} }
boolean ended = false; for (PathProperty current : this)
Iterator<PathProperty> iterator = iterator();
while (!ended)
{ {
if (iterator.hasNext()) if (StringUtils.startsWith(current.getPath(), pattern))
{ {
PathProperty current = iterator.next(); result.add(current);
if (StringUtils.startsWith(current.getPath(), pattern))
{
result.add(current);
}
}
else
{
ended = true;
} }
} }
} }
@ -310,6 +304,69 @@ public class PathPropertyList extends ArrayList<PathProperty> implements PathPro
return result; return result;
} }
/**
* Gets the date.
*
* @param path
* the path
* @return the date
*/
public LocalDate getDate(final String path)
{
LocalDate result;
String value = get(path);
if (value == null)
{
result = null;
}
else
{
String pattern;
if (value.matches("\\d{1,2}/\\d{1,2}/\\d{4}"))
{
pattern = "dd/MM/yyyy";
}
else if (value.matches("\\d{4}-\\d{2}-\\d{2}"))
{
pattern = "yyyy-MM-dd";
}
else if (value.matches("\\d{1,2}/\\d{4}"))
{
value = "01/" + value;
pattern = "dd/MM/yyyy";
}
else if (value.matches("\\d{4}-\\d{2}"))
{
value = value + "-01";
pattern = "yyyy-MM-dd";
}
else
{
pattern = null;
}
if (pattern == null)
{
result = null;
}
else
{
try
{
result = LocalDate.parse(value, DateTimeFormatter.ofPattern(pattern));
}
catch (DateTimeParseException exception)
{
result = null;
}
}
}
//
return result;
}
/** /**
* Gets the index property. * Gets the index property.
* *

View file

@ -87,7 +87,7 @@ public class StatAgent
CategoryStat stat = new CategoryStat(category); CategoryStat stat = new CategoryStat(category);
StringSet organizations = new StringSet(); StringSet organizations = new StringSet();
for (Service service : federation.getServicesAll()) for (Service service : federation.getServices())
{ {
String softwareName = service.getSoftwareName(); String softwareName = service.getSoftwareName();
if (category.getSoftwares().containsIgnoreCase(softwareName)) if (category.getSoftwares().containsIgnoreCase(softwareName))
@ -195,7 +195,7 @@ public class StatAgent
SoftwareStat stat = new SoftwareStat(software.getName()); SoftwareStat stat = new SoftwareStat(software.getName());
stat.getCategories().addAll(categories.findBySoftware(software.getName())); stat.getCategories().addAll(categories.findBySoftware(software.getName()));
StringSet organizations = new StringSet(); StringSet organizations = new StringSet();
for (Service service : federation.getServicesAll()) for (Service service : federation.getServices())
{ {
Software current = catalog.get(service.getSoftwareName()); Software current = catalog.get(service.getSoftwareName());
if (current == software) if (current == software)

View file

@ -154,7 +154,7 @@ public class LineIterator
} }
else else
{ {
result = null; result = "";
} }
} }
finally finally