Added sql database probing. Gitea + Minetest.
This commit is contained in:
parent
b1e841c787
commit
87a6a15f10
15 changed files with 881 additions and 110 deletions
|
@ -10,7 +10,6 @@
|
|||
</classpathentry>
|
||||
<classpathentry kind="lib" path="lib/commons-codec-1.8.jar" sourcepath="lib/commons-codec-1.8-sources.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
|
||||
<classpathentry kind="lib" path="lib/mysql-jdbc-5.0.8.jar"/>
|
||||
<classpathentry kind="lib" path="lib/UnitTesting/hamcrest-core-1.3.jar" sourcepath="lib/UnitTesting/hamcrest-core-1.3-sources.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"/>
|
||||
|
@ -29,5 +28,9 @@
|
|||
<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="lib" path="lib/json-simple-1.1.1.jar" sourcepath="lib/json-simple-1.1.1-sources.jar"/>
|
||||
<classpathentry kind="lib" path="lib/mariadb-java-client-3.0.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/postgresql-42.3.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/sqlite-jdbc-3.36.0.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/mysql-jdbc-5.0.8.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
116
README.md
116
README.md
|
@ -127,55 +127,6 @@ 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.
|
||||
|
||||
|
||||
### 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.httpaccesslog.pattern=
|
||||
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)
|
||||
|
||||
|
@ -197,6 +148,13 @@ conf.probe.httpaccesslog.pattern=
|
|||
conf.probe.gitea.data=/opt/gitea/data
|
||||
conf.probe.gitea.api.url=https://forge.libre-service.eu/
|
||||
conf.probe.gitea.token=b6598c616b1cd350b834258205da4e5e8b951005
|
||||
# jdbc:mariadb://localhost:1234/databasename
|
||||
# jdbc:mysql://localhost:1234/databasename
|
||||
# jdbc:postgresql://localhost:1234/databasename
|
||||
# jdbc:sqlite:/foo/bar/databasename.sqlite
|
||||
conf.probe.gitea.database.url=
|
||||
conf.probe.gitea.database.user=
|
||||
conf.probe.gitea.database.password=
|
||||
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
|
||||
```
|
||||
|
||||
|
@ -208,7 +166,37 @@ Configuration template:
|
|||
conf.probe.types=LibreQR
|
||||
conf.probe.httpaccesslog.file=/var/log/apache2/foo.bar.org-access.log*
|
||||
conf.probe.httpaccesslog.pattern=
|
||||
conf.probe.libreqr.data=/var/www/qrcode.libre-service.eu/data/
|
||||
conf.probe.libreqr.datafiles=/var/www/foo.bar.org/temp/
|
||||
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
|
||||
```
|
||||
|
||||
### Minetest metrics
|
||||
|
||||
Configuration template:
|
||||
|
||||
```
|
||||
conf.probe.types=Minetest
|
||||
conf.probe.minetest.logs=/home/cpm/Projets/StatoolInfos/EnvTest/minetest/minetest.log*
|
||||
|
||||
conf.probe.minetest.players.database.url=jdbc:postgresql://localhost:5432/minetestdb
|
||||
conf.probe.minetest.players.database.user=minetestdba
|
||||
conf.probe.minetest.players.database.password=XXXXXXXXXXX
|
||||
|
||||
conf.probe.minetest.worlds.database.url=jdbc:postgresql://localhost:5432/minetestdb
|
||||
conf.probe.minetest.worlds.database.user=minetestdba
|
||||
conf.probe.minetest.worlds.database.password=XXXXXXXXXXX
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
|
@ -223,3 +211,31 @@ conf.probe.httpaccesslog.pattern=
|
|||
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.httpaccesslog.pattern=
|
||||
conf.probe.privatebin.data=/var/www/paste.libre-service.eu/data/
|
||||
conf.probe.target=/srv/statoolinfos/well-known/statoolinfos/foo.bar.org-metrics.properties
|
||||
```
|
||||
|
||||
### 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=
|
||||
```
|
BIN
lib/mariadb-java-client-3.0.3.jar
Normal file
BIN
lib/mariadb-java-client-3.0.3.jar
Normal file
Binary file not shown.
BIN
lib/postgresql-42.3.3.jar
Normal file
BIN
lib/postgresql-42.3.3.jar
Normal file
Binary file not shown.
BIN
lib/sqlite-jdbc-3.36.0.3.jar
Normal file
BIN
lib/sqlite-jdbc-3.36.0.3.jar
Normal file
Binary file not shown.
|
@ -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.
|
||||
*
|
||||
|
@ -266,11 +266,9 @@ public class Configuration extends PathPropertyList
|
|||
|
||||
result = new DatabaseConfig();
|
||||
|
||||
result.setHost(get(prefix + ".db.host"));
|
||||
result.setPort(get(prefix + ".db.port"));
|
||||
result.setName(get(prefix + ".db.name"));
|
||||
result.setUser(get(prefix + ".db.user"));
|
||||
result.setPassword(get(prefix + ".db.password"));
|
||||
result.setUrl(get(prefix + ".database.url"));
|
||||
result.setUser(get(prefix + ".database.user"));
|
||||
result.setPassword(get(prefix + ".database.password"));
|
||||
|
||||
//
|
||||
return result;
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
@ -18,14 +18,14 @@
|
|||
*/
|
||||
package fr.devinsy.statoolinfos.core;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* The Class DatabaseConfig.
|
||||
*/
|
||||
public class DatabaseConfig
|
||||
{
|
||||
private String host;
|
||||
private String port;
|
||||
private String name;
|
||||
private String url;
|
||||
private String user;
|
||||
private String password;
|
||||
|
||||
|
@ -34,31 +34,19 @@ public class DatabaseConfig
|
|||
*/
|
||||
public DatabaseConfig()
|
||||
{
|
||||
this.host = null;
|
||||
this.port = null;
|
||||
this.name = null;
|
||||
this.url = null;
|
||||
this.user = null;
|
||||
this.password = null;
|
||||
}
|
||||
|
||||
public String getHost()
|
||||
{
|
||||
return this.host;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getPassword()
|
||||
{
|
||||
return this.password;
|
||||
}
|
||||
|
||||
public String getPort()
|
||||
public String getUrl()
|
||||
{
|
||||
return this.port;
|
||||
return this.url;
|
||||
}
|
||||
|
||||
public String getUser()
|
||||
|
@ -66,14 +54,26 @@ public class DatabaseConfig
|
|||
return this.user;
|
||||
}
|
||||
|
||||
public void setHost(final String host)
|
||||
/**
|
||||
* Checks if is sets the.
|
||||
*
|
||||
* @return true, if is sets the
|
||||
*/
|
||||
public boolean isSet()
|
||||
{
|
||||
this.host = host;
|
||||
boolean result;
|
||||
|
||||
if (StringUtils.isAnyBlank(this.url, this.user))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
public void setName(final String name)
|
||||
{
|
||||
this.name = name;
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setPassword(final String password)
|
||||
|
@ -81,13 +81,37 @@ public class DatabaseConfig
|
|||
this.password = password;
|
||||
}
|
||||
|
||||
public void setPort(final String port)
|
||||
public void setUrl(final String url)
|
||||
{
|
||||
this.port = port;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public void setUser(final String user)
|
||||
{
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String result;
|
||||
|
||||
String password;
|
||||
if (StringUtils.isBlank(this.password))
|
||||
{
|
||||
password = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
password = "**********";
|
||||
}
|
||||
|
||||
result = String.format("[%s,%s,%s]", this.url, this.user, password);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,8 +159,10 @@ public class Prober
|
|||
logger.info("apiURL=[{}]", apiURL);
|
||||
String apiToken = configuration.get("conf.probe.gitea.api.token");
|
||||
logger.info("apiToken=[{}]", apiToken == null ? "null" : "************************");
|
||||
DatabaseConfig database = configuration.getDatabaseConfig("conf.probe.gitea");
|
||||
logger.info("database={}", database.toString());
|
||||
|
||||
PathCounters metrics = GiteaProber.probe(FilesUtils.searchByWildcard(httpLogs), httpAccessLogRegex, apiURL, apiToken, dataDirectory);
|
||||
PathCounters metrics = GiteaProber.probe(FilesUtils.searchByWildcard(httpLogs), httpAccessLogRegex, apiURL, apiToken, dataDirectory, database);
|
||||
counters.putAll(metrics);
|
||||
}
|
||||
|
||||
|
@ -187,9 +189,13 @@ public class Prober
|
|||
{
|
||||
logger.info("== Probing Minetest.");
|
||||
String source = configuration.get("conf.probe.minetest.logs");
|
||||
DatabaseConfig database = configuration.getDatabaseConfig("conf.probe.minetest.players");
|
||||
logger.info("source=[{}]", source);
|
||||
DatabaseConfig playerDatabase = configuration.getDatabaseConfig("conf.probe.minetest.players");
|
||||
logger.info("players database={}", playerDatabase.toString());
|
||||
DatabaseConfig worldDatabase = configuration.getDatabaseConfig("conf.probe.minetest.worlds");
|
||||
logger.info("wordls database={}", worldDatabase.toString());
|
||||
|
||||
PathCounters data = MinetestProber.probe(source, database);
|
||||
PathCounters data = MinetestProber.probe(source, playerDatabase, worldDatabase);
|
||||
counters.putAll(data);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ package fr.devinsy.statoolinfos.metrics.gitea;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -27,6 +28,7 @@ import org.json.simple.parser.ParseException;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import fr.devinsy.statoolinfos.core.DatabaseConfig;
|
||||
import fr.devinsy.statoolinfos.core.StatoolInfosException;
|
||||
import fr.devinsy.statoolinfos.metrics.PathCounters;
|
||||
import fr.devinsy.statoolinfos.metrics.UserCounters;
|
||||
|
@ -36,6 +38,7 @@ import fr.devinsy.statoolinfos.metrics.http.HttpStatusCategory;
|
|||
import fr.devinsy.statoolinfos.metrics.util.DatabaseProber;
|
||||
import fr.devinsy.statoolinfos.metrics.util.DatafilesProber;
|
||||
import fr.devinsy.statoolinfos.util.Files;
|
||||
import fr.devinsy.statoolinfos.util.sql.SQLDatabase;
|
||||
import fr.devinsy.strings.StringList;
|
||||
|
||||
/**
|
||||
|
@ -67,7 +70,8 @@ public class GiteaProber
|
|||
* @throws StatoolInfosException
|
||||
* the statool infos exception
|
||||
*/
|
||||
public static PathCounters probe(final Files httpLogs, final String httpLogRegex, final String apiURL, final String apiToken, final File dataPath) throws IOException, StatoolInfosException
|
||||
public static PathCounters probe(final Files httpLogs, final String httpLogRegex, final String apiURL, final String apiToken, final File dataPath, final DatabaseConfig databaseConfig)
|
||||
throws IOException, StatoolInfosException
|
||||
{
|
||||
PathCounters result;
|
||||
|
||||
|
@ -77,7 +81,23 @@ public class GiteaProber
|
|||
result = probeHttpAccessLog(httpLogs, httpLogRegex);
|
||||
|
||||
// metrics.service.database.bytes
|
||||
result.putAll(DatabaseProber.probe(null));
|
||||
try
|
||||
{
|
||||
if (databaseConfig.isSet())
|
||||
{
|
||||
SQLDatabase database = new SQLDatabase(databaseConfig.getUrl(), databaseConfig.getUser(), databaseConfig.getPassword());
|
||||
database.open();
|
||||
result.putAll(DatabaseProber.probe(database));
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("GITEA Database undefined.");
|
||||
}
|
||||
}
|
||||
catch (SQLException exception)
|
||||
{
|
||||
logger.error("ERROR with database.", exception);
|
||||
}
|
||||
|
||||
// metrics.service.files.bytes
|
||||
// metrics.service.files.count
|
||||
|
|
|
@ -19,13 +19,17 @@
|
|||
package fr.devinsy.statoolinfos.metrics.minetest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import fr.devinsy.statoolinfos.core.DatabaseConfig;
|
||||
import fr.devinsy.statoolinfos.core.StatoolInfosException;
|
||||
import fr.devinsy.statoolinfos.metrics.PathCounters;
|
||||
import fr.devinsy.statoolinfos.util.sql.SQLDatabase;
|
||||
import fr.devinsy.strings.StringList;
|
||||
|
||||
/**
|
||||
* The Class MinetestProber.
|
||||
|
@ -51,7 +55,7 @@ public class MinetestProber
|
|||
* @throws StatoolInfosException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static PathCounters probe(final String logs, final DatabaseConfig databaseConfig) throws IOException, StatoolInfosException
|
||||
public static PathCounters probe(final String logs, final DatabaseConfig playerDatabaseConfig, final DatabaseConfig worldDatabaseConfig) throws IOException, StatoolInfosException
|
||||
{
|
||||
PathCounters result;
|
||||
|
||||
|
@ -68,6 +72,52 @@ public class MinetestProber
|
|||
// metrics.metaverse.logs.unknown
|
||||
result = MinetestLogAnalyzer.probe(logs);
|
||||
|
||||
// metrics.service.database.bytes
|
||||
long databaseSize = 0;
|
||||
try
|
||||
{
|
||||
System.out.println("Probing database [" + playerDatabaseConfig.getUrl() + "]");
|
||||
if (playerDatabaseConfig.isSet())
|
||||
{
|
||||
SQLDatabase database = new SQLDatabase(playerDatabaseConfig.getUrl(), playerDatabaseConfig.getUser(), playerDatabaseConfig.getPassword());
|
||||
database.open();
|
||||
databaseSize += database.getDatabaseSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("Minetest Players Database undefined.");
|
||||
}
|
||||
}
|
||||
catch (SQLException exception)
|
||||
{
|
||||
logger.error("ERROR with database.", exception);
|
||||
}
|
||||
|
||||
if (!StringUtils.equals(playerDatabaseConfig.getUrl(), worldDatabaseConfig.getUrl()))
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Probing database [" + worldDatabaseConfig.getUrl() + "]");
|
||||
if (worldDatabaseConfig.isSet())
|
||||
{
|
||||
SQLDatabase database = new SQLDatabase(worldDatabaseConfig.getUrl(), worldDatabaseConfig.getUser(), worldDatabaseConfig.getPassword());
|
||||
database.open();
|
||||
databaseSize += database.getDatabaseSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("Minetest Worlds Database undefined.");
|
||||
}
|
||||
}
|
||||
catch (SQLException exception)
|
||||
{
|
||||
logger.error("ERROR with database.", exception);
|
||||
}
|
||||
}
|
||||
|
||||
StringList timemarks = result.getNowTimeMarks();
|
||||
result.set(databaseSize, "metrics.service.database.bytes", timemarks);
|
||||
|
||||
// result.putAll(MumbleDatabaseAnalyzer.probe());
|
||||
// metrics.service.accounts
|
||||
// metrics.service.database.bytes
|
||||
|
|
|
@ -23,8 +23,9 @@ import java.io.IOException;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import fr.devinsy.statoolinfos.core.DatabaseConfig;
|
||||
import fr.devinsy.statoolinfos.metrics.PathCounters;
|
||||
import fr.devinsy.statoolinfos.util.sql.SQLDatabase;
|
||||
import fr.devinsy.strings.StringList;
|
||||
|
||||
/**
|
||||
* The Class DatabaseProber.
|
||||
|
@ -49,30 +50,21 @@ public class DatabaseProber
|
|||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public static PathCounters probe(final DatabaseConfig config) throws IOException
|
||||
public static PathCounters probe(final SQLDatabase database) throws IOException
|
||||
{
|
||||
PathCounters result;
|
||||
|
||||
result = new PathCounters();
|
||||
|
||||
if (config != null)
|
||||
if ((database != null) && (database.isOpened()))
|
||||
{
|
||||
System.out.println("Probing directory [" + config.getName() + "]");
|
||||
}
|
||||
System.out.println("Probing database [" + database.getUrl() + "]");
|
||||
|
||||
// if ((directory != null) && (directory.exists()) &&
|
||||
// (directory.isDirectory()))
|
||||
// {
|
||||
// StringList timemarks = result.getNowTimeMarks();
|
||||
//
|
||||
// // metrics.service.database.bytes
|
||||
// long size = FileUtils.sizeOfDirectory(directory);
|
||||
// result.set(size, prefix + ".files.bytes", timemarks);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// System.out.println("WARNING: datafile path not valid.");
|
||||
// }
|
||||
// metrics.service.database.bytes
|
||||
long bytes = database.getDatabaseSize();
|
||||
StringList timemarks = result.getNowTimeMarks();
|
||||
result.set(bytes, "metrics.service.database.bytes", timemarks);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2018-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.util.sql;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* The Class ClosedDatabaseException.
|
||||
*/
|
||||
public class ClosedDatabaseException extends SQLException
|
||||
{
|
||||
private static final long serialVersionUID = 9220220563426218282L;
|
||||
|
||||
/**
|
||||
* Instantiates a new closed database exception.
|
||||
*/
|
||||
public ClosedDatabaseException()
|
||||
{
|
||||
super("Invalid database status for this operation: closed.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new closed database exception.
|
||||
*
|
||||
* @param message
|
||||
* the message
|
||||
*/
|
||||
public ClosedDatabaseException(final String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new closed database exception.
|
||||
*
|
||||
* @param message
|
||||
* the message
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
public ClosedDatabaseException(final String message, final Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new closed database exception.
|
||||
*
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
public ClosedDatabaseException(final Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2018-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.util.sql;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* The Class OpenedDatabaseException.
|
||||
*/
|
||||
public class OpenedDatabaseException extends SQLException
|
||||
{
|
||||
private static final long serialVersionUID = -8218498455798186368L;
|
||||
|
||||
/**
|
||||
* Instantiates a new opened database exception.
|
||||
*/
|
||||
public OpenedDatabaseException()
|
||||
{
|
||||
super("Invalid database status for this operation: opened.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new opened database exception.
|
||||
*
|
||||
* @param message
|
||||
* the message
|
||||
*/
|
||||
public OpenedDatabaseException(final String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new opened database exception.
|
||||
*
|
||||
* @param message
|
||||
* the message
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
public OpenedDatabaseException(final String message, final Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new opened database exception.
|
||||
*
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
public OpenedDatabaseException(final Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
}
|
||||
}
|
441
src/fr/devinsy/statoolinfos/util/sql/SQLDatabase.java
Normal file
441
src/fr/devinsy/statoolinfos/util/sql/SQLDatabase.java
Normal file
|
@ -0,0 +1,441 @@
|
|||
/*
|
||||
* Copyright (C) 2013-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.util.sql;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The Class SQLDatabase.
|
||||
*/
|
||||
public class SQLDatabase
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(SQLDatabase.class);;
|
||||
|
||||
public enum Driver
|
||||
{
|
||||
HSQL,
|
||||
MARIADB,
|
||||
MYSQL,
|
||||
NONE,
|
||||
POSTGRES,
|
||||
SQLITE
|
||||
};
|
||||
|
||||
public enum Status
|
||||
{
|
||||
OPENED,
|
||||
CLOSED
|
||||
};
|
||||
|
||||
private Status status;
|
||||
private Driver driver;
|
||||
private String url;
|
||||
private String login;
|
||||
private String password;
|
||||
private Connection connection;
|
||||
|
||||
/**
|
||||
* This method opens a database session.
|
||||
*
|
||||
* @param driverClassName
|
||||
* the driver class name
|
||||
* @param url
|
||||
* the url
|
||||
* @param login
|
||||
* the login
|
||||
* @param password
|
||||
* the password
|
||||
*/
|
||||
public SQLDatabase(final String url, final String login, final String password)
|
||||
{
|
||||
if (StringUtils.isBlank(url))
|
||||
{
|
||||
throw new IllegalArgumentException("url is null.");
|
||||
}
|
||||
else if (StringUtils.isBlank(login))
|
||||
{
|
||||
throw new IllegalArgumentException("login is null.");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.status = Status.CLOSED;
|
||||
this.driver = Driver.NONE;
|
||||
this.url = url;
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
this.connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close.
|
||||
*/
|
||||
public void close()
|
||||
{
|
||||
if (this.connection != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.connection.close();
|
||||
}
|
||||
catch (SQLException exception)
|
||||
{
|
||||
logger.error("Error closing database.", exception);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.status = Status.CLOSED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the connection.
|
||||
*
|
||||
* @return the connection
|
||||
* @throws SQLException
|
||||
* the SQL exception
|
||||
*/
|
||||
public Connection getConnection() throws SQLException
|
||||
{
|
||||
Connection result;
|
||||
|
||||
if (isClosed())
|
||||
{
|
||||
throw new SQLException("Database not opened.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.connection != null)
|
||||
{
|
||||
result = this.connection;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Connection not initialized.");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the database size.
|
||||
*
|
||||
* @return the database size
|
||||
*/
|
||||
public long getDatabaseSize()
|
||||
{
|
||||
long result;
|
||||
|
||||
try
|
||||
{
|
||||
if (isOpened())
|
||||
{
|
||||
switch (this.driver)
|
||||
{
|
||||
case HSQL:
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case MARIADB:
|
||||
case MYSQL:
|
||||
{
|
||||
String sql = "SELECT SUM(data_length + index_length) FROM information_schema.tables where table_schema = (select database());";
|
||||
result = queryNumber(sql);
|
||||
}
|
||||
break;
|
||||
|
||||
case POSTGRES:
|
||||
{
|
||||
String sql = "SELECT pg_database_size(pg_database.datname) FROM pg_database WHERE pg_database.datname = (select current_catalog);";
|
||||
result = queryNumber(sql);
|
||||
}
|
||||
break;
|
||||
|
||||
case SQLITE:
|
||||
{
|
||||
File file = new File(this.url.replace("jdbc:sqlite:", ""));
|
||||
result = file.length();
|
||||
}
|
||||
break;
|
||||
|
||||
case NONE:
|
||||
default:
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
catch (SQLException exception)
|
||||
{
|
||||
logger.error("ERROR querying database size.", exception);
|
||||
result = 0;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the driver.
|
||||
*
|
||||
* @return the driver
|
||||
*/
|
||||
public Driver getDriver()
|
||||
{
|
||||
Driver result;
|
||||
|
||||
result = this.driver;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the login.
|
||||
*
|
||||
* @return the login
|
||||
*/
|
||||
public String getLogin()
|
||||
{
|
||||
String result;
|
||||
|
||||
result = this.login;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the password.
|
||||
*
|
||||
* @return the password
|
||||
*/
|
||||
public String getPassword()
|
||||
{
|
||||
String result;
|
||||
|
||||
result = this.password;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the url.
|
||||
*
|
||||
* @return the url
|
||||
*/
|
||||
public String getUrl()
|
||||
{
|
||||
String result;
|
||||
|
||||
result = this.url;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is closed.
|
||||
*
|
||||
* @return true, if is closed
|
||||
*/
|
||||
public boolean isClosed()
|
||||
{
|
||||
boolean result;
|
||||
|
||||
if (this.status == Status.CLOSED)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is opened.
|
||||
*
|
||||
* @return true, if is opened
|
||||
*/
|
||||
public boolean isOpened()
|
||||
{
|
||||
boolean result;
|
||||
|
||||
result = !isClosed();
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open.
|
||||
*
|
||||
* @throws SQLException
|
||||
* the SQL exception
|
||||
*/
|
||||
public void open() throws SQLException
|
||||
{
|
||||
try
|
||||
{
|
||||
//
|
||||
close();
|
||||
|
||||
//
|
||||
if (this.url == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Undefined source.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.url.startsWith("jdbc:sqlite:"))
|
||||
{
|
||||
this.driver = Driver.SQLITE;
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
}
|
||||
else if (this.url.startsWith("jdbc:postgresql:"))
|
||||
{
|
||||
Class.forName("org.postgresql.Driver");
|
||||
this.driver = Driver.POSTGRES;
|
||||
}
|
||||
else if (this.url.startsWith("jdbc:mysql:"))
|
||||
{
|
||||
Class.forName("com.mysql.jdbc.Driver");
|
||||
this.driver = Driver.MYSQL;
|
||||
}
|
||||
else if (this.url.startsWith("jdbc:mariadb:"))
|
||||
{
|
||||
Class.forName("org.mariadb.jdbc.Driver");
|
||||
this.driver = Driver.MARIADB;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SQLException("Unknown database type.");
|
||||
}
|
||||
|
||||
this.connection = DriverManager.getConnection(this.url, this.login, this.password);
|
||||
this.status = Status.OPENED;
|
||||
logger.info("Single connection opened with [{}].", this.url);
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException exception)
|
||||
{
|
||||
throw new SQLException("ERROR with driver name.", exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query number.
|
||||
*
|
||||
* @param sql
|
||||
* the sql
|
||||
* @return the long
|
||||
* @throws SQLException
|
||||
* the SQL exception
|
||||
*/
|
||||
public long queryNumber(final String sql) throws SQLException
|
||||
{
|
||||
long result;
|
||||
|
||||
if (isClosed())
|
||||
{
|
||||
throw new ClosedDatabaseException();
|
||||
}
|
||||
else
|
||||
{
|
||||
Connection connection = null;
|
||||
Statement statement = null;
|
||||
ResultSet resultSet = null;
|
||||
try
|
||||
{
|
||||
connection = getConnection();
|
||||
connection.setAutoCommit(true);
|
||||
statement = connection.createStatement();
|
||||
resultSet = statement.executeQuery(sql);
|
||||
|
||||
resultSet.next();
|
||||
result = resultSet.getLong(1);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SQLUtils.closeQuietly(statement, resultSet);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the login.
|
||||
*
|
||||
* @param login
|
||||
* the new login
|
||||
*/
|
||||
public void setLogin(final String login)
|
||||
{
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password.
|
||||
*
|
||||
* @param password
|
||||
* the new password
|
||||
*/
|
||||
public void setPassword(final String password)
|
||||
{
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the url.
|
||||
*
|
||||
* @param url
|
||||
* the new url
|
||||
*/
|
||||
public void setUrl(final String url)
|
||||
{
|
||||
this.url = url;
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
|
@ -16,7 +16,7 @@
|
|||
* 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.util;
|
||||
package fr.devinsy.statoolinfos.util.sql;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
|
@ -25,6 +25,7 @@ import java.sql.SQLException;
|
|||
import java.sql.Statement;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -244,6 +245,32 @@ public final class SQLUtils
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* To date time.
|
||||
*
|
||||
* @param source
|
||||
* the source
|
||||
* @return the date time
|
||||
*/
|
||||
public static LocalDateTime toDateTime(final java.sql.Timestamp source)
|
||||
{
|
||||
LocalDateTime result;
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
result = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
long seconds = source.getTime() / 1000;
|
||||
long nanos = (source.getTime() - seconds * 1000) * 1000000;
|
||||
result = LocalDateTime.ofEpochSecond(seconds, (int) nanos, ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* To date time.
|
||||
*
|
||||
|
@ -269,4 +296,54 @@ public final class SQLUtils
|
|||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* To timestamp.
|
||||
*
|
||||
* @param source
|
||||
* the source
|
||||
* @return the java.sql. timestamp
|
||||
*/
|
||||
public static java.sql.Timestamp toTimestamp(final Date source)
|
||||
{
|
||||
java.sql.Timestamp result;
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
result = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new java.sql.Timestamp(source.getTime() * 1000);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* To timestamp.
|
||||
*
|
||||
* @param source
|
||||
* the source
|
||||
* @return the java.sql. timestamp
|
||||
*/
|
||||
public static java.sql.Timestamp toTimestamp(final LocalDateTime source)
|
||||
{
|
||||
java.sql.Timestamp result;
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
result = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
long seconds = source.toEpochSecond(ZoneOffset.UTC);
|
||||
long milliseconds = source.getNano() / 1000000;
|
||||
result = new java.sql.Timestamp(seconds * 1000 + milliseconds);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue