Added Minetest log analyze.
This commit is contained in:
parent
0bed68260a
commit
8b87eed546
11 changed files with 1025 additions and 8 deletions
|
@ -253,6 +253,29 @@ public class Configuration extends PathPropertyList
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the database config.
|
||||||
|
*
|
||||||
|
* @param prefix
|
||||||
|
* the prefix
|
||||||
|
* @return the database config
|
||||||
|
*/
|
||||||
|
public DatabaseConfig getDatabaseConfig(final String prefix)
|
||||||
|
{
|
||||||
|
DatabaseConfig result;
|
||||||
|
|
||||||
|
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"));
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the edito directory.
|
* Gets the edito directory.
|
||||||
*
|
*
|
||||||
|
|
93
src/fr/devinsy/statoolinfos/core/DatabaseConfig.java
Normal file
93
src/fr/devinsy/statoolinfos/core/DatabaseConfig.java
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class DatabaseConfig.
|
||||||
|
*/
|
||||||
|
public class DatabaseConfig
|
||||||
|
{
|
||||||
|
private String host;
|
||||||
|
private String port;
|
||||||
|
private String name;
|
||||||
|
private String user;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new database config.
|
||||||
|
*/
|
||||||
|
public DatabaseConfig()
|
||||||
|
{
|
||||||
|
this.host = null;
|
||||||
|
this.port = null;
|
||||||
|
this.name = 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()
|
||||||
|
{
|
||||||
|
return this.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUser()
|
||||||
|
{
|
||||||
|
return this.user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHost(final String host)
|
||||||
|
{
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(final String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(final String password)
|
||||||
|
{
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(final String port)
|
||||||
|
{
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(final String user)
|
||||||
|
{
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,11 +34,13 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import fr.devinsy.statoolinfos.core.Configuration;
|
import fr.devinsy.statoolinfos.core.Configuration;
|
||||||
|
import fr.devinsy.statoolinfos.core.DatabaseConfig;
|
||||||
import fr.devinsy.statoolinfos.core.Factory;
|
import fr.devinsy.statoolinfos.core.Factory;
|
||||||
import fr.devinsy.statoolinfos.core.StatoolInfosException;
|
import fr.devinsy.statoolinfos.core.StatoolInfosException;
|
||||||
import fr.devinsy.statoolinfos.core.StatoolInfosUtils;
|
import fr.devinsy.statoolinfos.core.StatoolInfosUtils;
|
||||||
import fr.devinsy.statoolinfos.metrics.http.HttpAccessLogAnalyzer;
|
import fr.devinsy.statoolinfos.metrics.http.HttpAccessLogAnalyzer;
|
||||||
import fr.devinsy.statoolinfos.metrics.http.HttpErrorLogAnalyzer;
|
import fr.devinsy.statoolinfos.metrics.http.HttpErrorLogAnalyzer;
|
||||||
|
import fr.devinsy.statoolinfos.metrics.minetest.MinetestProber;
|
||||||
import fr.devinsy.statoolinfos.properties.PathProperties;
|
import fr.devinsy.statoolinfos.properties.PathProperties;
|
||||||
import fr.devinsy.statoolinfos.properties.PathProperty;
|
import fr.devinsy.statoolinfos.properties.PathProperty;
|
||||||
import fr.devinsy.statoolinfos.properties.PathPropertyUtils;
|
import fr.devinsy.statoolinfos.properties.PathPropertyUtils;
|
||||||
|
@ -138,6 +140,17 @@ public class Prober
|
||||||
// counters.putAll(data);
|
// counters.putAll(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
if (types.containsAnyIgnoreCase("Minetest"))
|
||||||
|
{
|
||||||
|
logger.info("== Processing Minetest.");
|
||||||
|
String source = configuration.get("conf.probe.minetest.logs");
|
||||||
|
DatabaseConfig database = configuration.getDatabaseConfig("conf.probe.minetest.players");
|
||||||
|
|
||||||
|
PathCounters data = MinetestProber.probe(source, database);
|
||||||
|
counters.putAll(data);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
if (types.containsAnyIgnoreCase("Mumble"))
|
if (types.containsAnyIgnoreCase("Mumble"))
|
||||||
{
|
{
|
||||||
|
|
|
@ -204,6 +204,7 @@ public class HttpAccessLog
|
||||||
{
|
{
|
||||||
result = this.ip.contains(".");
|
result = this.ip.contains(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -225,6 +226,7 @@ public class HttpAccessLog
|
||||||
{
|
{
|
||||||
result = this.ip.contains(":");
|
result = this.ip.contains(":");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.metrics.minetest;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import fr.devinsy.statoolinfos.metrics.PathCounters;
|
||||||
|
import fr.devinsy.strings.StringSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class ActivePlayerCounters.
|
||||||
|
*/
|
||||||
|
public class ActivePlayerCounters extends HashMap<String, StringSet>
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 8340304752282908677L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new active player counters.
|
||||||
|
*/
|
||||||
|
public ActivePlayerCounters()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the.
|
||||||
|
*
|
||||||
|
* @param timeMark
|
||||||
|
* the time mark
|
||||||
|
* @return the string set
|
||||||
|
*/
|
||||||
|
public StringSet get(final String timeMark)
|
||||||
|
{
|
||||||
|
StringSet result;
|
||||||
|
|
||||||
|
result = super.get(timeMark);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the counters.
|
||||||
|
*
|
||||||
|
* @return the counters
|
||||||
|
*/
|
||||||
|
public PathCounters getCounters(final String prefix)
|
||||||
|
{
|
||||||
|
PathCounters result;
|
||||||
|
|
||||||
|
result = new PathCounters();
|
||||||
|
|
||||||
|
for (String timeMark : keySet())
|
||||||
|
{
|
||||||
|
StringSet set = get(timeMark);
|
||||||
|
result.inc(set.size(), prefix, timeMark);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put.
|
||||||
|
*
|
||||||
|
* @param timemark
|
||||||
|
* the timemark
|
||||||
|
* @param nickname
|
||||||
|
* the nick name
|
||||||
|
*/
|
||||||
|
public void put(final String nickname, final String timemark)
|
||||||
|
{
|
||||||
|
StringSet set = super.get(timemark);
|
||||||
|
if (set == null)
|
||||||
|
{
|
||||||
|
set = new StringSet();
|
||||||
|
put(timemark, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
set.put(nickname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put.
|
||||||
|
*
|
||||||
|
* @param nickname
|
||||||
|
* the nickname
|
||||||
|
* @param timeMarks
|
||||||
|
* the time marks
|
||||||
|
*/
|
||||||
|
public void put(final String nickname, final String... timeMarks)
|
||||||
|
{
|
||||||
|
for (String timeMark : timeMarks)
|
||||||
|
{
|
||||||
|
put(nickname, timeMark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
240
src/fr/devinsy/statoolinfos/metrics/minetest/MinetestLog.java
Normal file
240
src/fr/devinsy/statoolinfos/metrics/minetest/MinetestLog.java
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.metrics.minetest;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import fr.devinsy.statoolinfos.metrics.TimeMarkUtils;
|
||||||
|
import fr.devinsy.strings.StringList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class MinetestLog.
|
||||||
|
*/
|
||||||
|
public class MinetestLog
|
||||||
|
{
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(MinetestLog.class);
|
||||||
|
|
||||||
|
// Cpm [2a01:e0a:22:ce10::adc5:a] joins game. List of players: Cpm
|
||||||
|
public static final Pattern JOIN_PATTERN = Pattern.compile("^(?<nickname>\\S+) \\[(?<ip>.+)\\] joins game\\..*$");
|
||||||
|
public static final Pattern NICK_PATTERN = Pattern
|
||||||
|
.compile(
|
||||||
|
"^(player )?(?<nickname>\\S+) (activates |crafts |damaged by |digs |has gottern award |leaves game |moves stuff |places node |respawns |right-clicks object |takes stuff |times out\\.).*$");
|
||||||
|
|
||||||
|
private LocalDateTime time;
|
||||||
|
private MinetestLogLevel level;
|
||||||
|
private String module;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new http access log.
|
||||||
|
*/
|
||||||
|
public MinetestLog()
|
||||||
|
{
|
||||||
|
this.time = null;
|
||||||
|
this.level = null;
|
||||||
|
this.module = null;
|
||||||
|
this.message = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDate()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = this.time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.FRANCE));
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ip.
|
||||||
|
*
|
||||||
|
* @return the ip
|
||||||
|
*/
|
||||||
|
public String getIp()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
Matcher matcher = JOIN_PATTERN.matcher(this.message);
|
||||||
|
if (matcher.matches())
|
||||||
|
{
|
||||||
|
result = matcher.group("ip");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MinetestLogLevel getLevel()
|
||||||
|
{
|
||||||
|
return this.level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return this.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModule()
|
||||||
|
{
|
||||||
|
return this.module;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the nickname.
|
||||||
|
*
|
||||||
|
* @return the nickname
|
||||||
|
*/
|
||||||
|
public String getNickname()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
Matcher matcher = NICK_PATTERN.matcher(this.message);
|
||||||
|
if (matcher.matches())
|
||||||
|
{
|
||||||
|
result = matcher.group("nickname");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getTime()
|
||||||
|
{
|
||||||
|
return this.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the year.
|
||||||
|
*
|
||||||
|
* @return the year
|
||||||
|
*/
|
||||||
|
public String getYear()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
if (this.time == null)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = TimeMarkUtils.yearOf(this.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the year month.
|
||||||
|
*
|
||||||
|
* @return the year month
|
||||||
|
*/
|
||||||
|
public String getYearMonth()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
if (this.time == null)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = TimeMarkUtils.yearMonthOf(this.time);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the year week.
|
||||||
|
*
|
||||||
|
* @return the year week
|
||||||
|
*/
|
||||||
|
public String getYearWeek()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
if (this.time == null)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = TimeMarkUtils.yearWeekOf(this.time);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevel(final MinetestLogLevel level)
|
||||||
|
{
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(final String message)
|
||||||
|
{
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModule(final String module)
|
||||||
|
{
|
||||||
|
this.module = module;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime(final LocalDateTime time)
|
||||||
|
{
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To string.
|
||||||
|
*
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
StringList buffer = new StringList();
|
||||||
|
|
||||||
|
buffer.append("[time=").append(this.time).append("]");
|
||||||
|
|
||||||
|
result = buffer.toString();
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,278 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.metrics.minetest;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import fr.devinsy.statoolinfos.core.StatoolInfosException;
|
||||||
|
import fr.devinsy.statoolinfos.metrics.PathCounters;
|
||||||
|
import fr.devinsy.statoolinfos.metrics.http.IpCounters;
|
||||||
|
import fr.devinsy.statoolinfos.util.FilesUtils;
|
||||||
|
import fr.devinsy.statoolinfos.util.IpUtils;
|
||||||
|
import fr.devinsy.statoolinfos.util.LineIterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class HttpAccessLogProber.
|
||||||
|
*/
|
||||||
|
public class MinetestLogAnalyzer
|
||||||
|
{
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(MinetestLogAnalyzer.class);
|
||||||
|
|
||||||
|
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
|
||||||
|
|
||||||
|
// log_format combined '$remote_addr - $remote_user [$time_local] '
|
||||||
|
// '"$request" $status $body_bytes_sent '
|
||||||
|
// '"$http_referer" "$http_user_agent"';
|
||||||
|
public static final Pattern MINETEST_LOG_PATTERN = Pattern.compile(
|
||||||
|
"^(?<datetime>\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}): (?<level>[^\\[]*)\\[(?<module>[^\\]]+)\\]: (?<message>.*)$");
|
||||||
|
|
||||||
|
private int errorCount;
|
||||||
|
private PathCounters counters;
|
||||||
|
private ActivePlayerCounters activePlayers;
|
||||||
|
private IpCounters ips;
|
||||||
|
private IpCounters ipv4;
|
||||||
|
private IpCounters ipv6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new http access log prober.
|
||||||
|
*/
|
||||||
|
public MinetestLogAnalyzer()
|
||||||
|
{
|
||||||
|
this.counters = new PathCounters();
|
||||||
|
this.activePlayers = new ActivePlayerCounters();
|
||||||
|
this.ips = new IpCounters();
|
||||||
|
this.ipv4 = new IpCounters();
|
||||||
|
this.ipv6 = new IpCounters();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the counters.
|
||||||
|
*
|
||||||
|
* @return the counters
|
||||||
|
*/
|
||||||
|
public PathCounters getCounters()
|
||||||
|
{
|
||||||
|
PathCounters result;
|
||||||
|
|
||||||
|
result = new PathCounters();
|
||||||
|
result.putAll(this.counters);
|
||||||
|
|
||||||
|
result.putAll(this.activePlayers.getCounters("metrics.metaverse.players.active"));
|
||||||
|
result.putAll(this.ips.getCounters("metrics.metaverse.ip"));
|
||||||
|
result.putAll(this.ipv4.getCounters("metrics.metaverse.ip.ipv4"));
|
||||||
|
result.putAll(this.ipv6.getCounters("metrics.metaverse.ip.ipv6"));
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probe.
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
* the file
|
||||||
|
* @throws IOException
|
||||||
|
* Signals that an I/O exception has occurred.
|
||||||
|
* @throws StatoolInfosException
|
||||||
|
* the statool infos exception
|
||||||
|
*/
|
||||||
|
public void probe(final File file) throws IOException
|
||||||
|
{
|
||||||
|
System.out.println("Probing file [" + file.getAbsolutePath() + "]");
|
||||||
|
|
||||||
|
//
|
||||||
|
LineIterator iterator = new LineIterator(file);
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
String line = iterator.next();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if ((!StringUtils.isBlank(line)) && (!StringUtils.startsWith(line, " ")) && (!StringUtils.startsWith(line, "-")))
|
||||||
|
{
|
||||||
|
MinetestLog log = parseLog(line);
|
||||||
|
if (log == null)
|
||||||
|
{
|
||||||
|
logger.warn("LINE IS NOT MATCHING [{}]", line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
probeLog(log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.warn("Error parsing line [{}][{}]", line, exception.getMessage());
|
||||||
|
exception.printStackTrace();
|
||||||
|
this.errorCount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probe log.
|
||||||
|
*
|
||||||
|
* @param log
|
||||||
|
* the log
|
||||||
|
*/
|
||||||
|
public void probeLog(final MinetestLog log)
|
||||||
|
{
|
||||||
|
// logger.info("==================");
|
||||||
|
if (log != null)
|
||||||
|
{
|
||||||
|
// logger.info("LINE IS MATCHING [{}]", log);
|
||||||
|
// logger.info(log.getHttpUserAgent().toString());
|
||||||
|
|
||||||
|
// General HTTP access logs.
|
||||||
|
String year = log.getYear();
|
||||||
|
String yearMonth = log.getYearMonth();
|
||||||
|
String yearWeek = log.getYearWeek();
|
||||||
|
String date = log.getDate();
|
||||||
|
|
||||||
|
// metrics.metaverse.logs
|
||||||
|
this.counters.inc("metrics.metaverse.logs", year, yearMonth, yearWeek, date);
|
||||||
|
|
||||||
|
// metrics.metaverse.logs.action
|
||||||
|
// metrics.metaverse.logs.warning
|
||||||
|
// metrics.metaverse.logs.error
|
||||||
|
// metrics.metaverse.logs.none
|
||||||
|
if (log.getLevel() == MinetestLogLevel.ACTION)
|
||||||
|
{
|
||||||
|
this.counters.inc("metrics.metaverse.logs.action", year, yearMonth, yearWeek, date);
|
||||||
|
}
|
||||||
|
else if (log.getLevel() == MinetestLogLevel.WARNING)
|
||||||
|
{
|
||||||
|
this.counters.inc("metrics.metaverse.logs.warning", year, yearMonth, yearWeek, date);
|
||||||
|
}
|
||||||
|
else if (log.getLevel() == MinetestLogLevel.ERROR)
|
||||||
|
{
|
||||||
|
this.counters.inc("metrics.metaverse.logs.error", year, yearMonth, yearWeek, date);
|
||||||
|
}
|
||||||
|
else if (log.getLevel() == MinetestLogLevel.NONE)
|
||||||
|
{
|
||||||
|
this.counters.inc("metrics.metaverse.logs.none", year, yearMonth, yearWeek, date);
|
||||||
|
}
|
||||||
|
else if (log.getLevel() == MinetestLogLevel.UNKNOWN)
|
||||||
|
{
|
||||||
|
this.counters.inc("metrics.metaverse.logs.unknown", year, yearMonth, yearWeek, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
// metrics.metaverse.players.active
|
||||||
|
this.activePlayers.put(log.getNickname(), year, yearMonth, yearWeek, date);
|
||||||
|
|
||||||
|
// metrics.metaverse.players.max
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// metrics.metaverse.joins --
|
||||||
|
if (log.getMessage().contains(" joins game."))
|
||||||
|
{
|
||||||
|
this.counters.inc("metrics.metaverse.joins", year, yearMonth, yearWeek, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
// metrics.metaverse.ip
|
||||||
|
// metrics.metaverse.ip.ipv4
|
||||||
|
// metrics.metaverse.ip.ipv6
|
||||||
|
String ip = log.getIp();
|
||||||
|
if (ip != null)
|
||||||
|
{
|
||||||
|
this.ips.put(ip, year, yearMonth, yearWeek, date);
|
||||||
|
|
||||||
|
if (IpUtils.isIpv4(ip))
|
||||||
|
{
|
||||||
|
this.ipv4.put(ip, year, yearMonth, yearWeek, date);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.ipv6.put(ip, year, yearMonth, yearWeek, date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// metrics.metaverse.games (visits)
|
||||||
|
// metrics.metaverse.games.duration (visits)
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the log.
|
||||||
|
*
|
||||||
|
* @param line
|
||||||
|
* the line
|
||||||
|
* @return the http log
|
||||||
|
*/
|
||||||
|
public static MinetestLog parseLog(final String line)
|
||||||
|
{
|
||||||
|
MinetestLog result;
|
||||||
|
|
||||||
|
Matcher matcher = MINETEST_LOG_PATTERN.matcher(line);
|
||||||
|
if (matcher.matches())
|
||||||
|
{
|
||||||
|
result = new MinetestLog();
|
||||||
|
result.setTime(LocalDateTime.parse(matcher.group("datetime"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withLocale(Locale.ENGLISH)));
|
||||||
|
result.setLevel(MinetestLogLevel.of(matcher.group("level")));
|
||||||
|
result.setModule(matcher.group("module"));
|
||||||
|
result.setMessage(matcher.group("message"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probe.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @throws IOException
|
||||||
|
* Signals that an I/O exception has occurred.
|
||||||
|
* @throws StatoolInfosException
|
||||||
|
* the statool infos exception
|
||||||
|
*/
|
||||||
|
public static PathCounters probe(final String source) throws IOException, StatoolInfosException
|
||||||
|
{
|
||||||
|
PathCounters result;
|
||||||
|
|
||||||
|
MinetestLogAnalyzer analyzer = new MinetestLogAnalyzer();
|
||||||
|
|
||||||
|
for (File file : FilesUtils.searchByWildcard(source))
|
||||||
|
{
|
||||||
|
analyzer.probe(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = analyzer.getCounters();
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.metrics.minetest;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Enum MinetestLogLevel.
|
||||||
|
*/
|
||||||
|
public enum MinetestLogLevel
|
||||||
|
{
|
||||||
|
ACTION,
|
||||||
|
WARNING,
|
||||||
|
ERROR,
|
||||||
|
NONE,
|
||||||
|
UNKNOWN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of.
|
||||||
|
*
|
||||||
|
* @param httpCode
|
||||||
|
* the code
|
||||||
|
* @return the http status category
|
||||||
|
*/
|
||||||
|
public static MinetestLogLevel of(final String value)
|
||||||
|
{
|
||||||
|
MinetestLogLevel result;
|
||||||
|
|
||||||
|
if (StringUtils.equals(value, "ACTION"))
|
||||||
|
{
|
||||||
|
result = ACTION;
|
||||||
|
}
|
||||||
|
else if (StringUtils.equals(value, "WARNING"))
|
||||||
|
{
|
||||||
|
result = WARNING;
|
||||||
|
}
|
||||||
|
else if (StringUtils.equals(value, "ERROR"))
|
||||||
|
{
|
||||||
|
result = ERROR;
|
||||||
|
}
|
||||||
|
else if (StringUtils.equals(value, "NONE"))
|
||||||
|
{
|
||||||
|
result = NONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.minetest;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class HttpAccesLogStat.
|
||||||
|
*/
|
||||||
|
public class MinetestLogStat
|
||||||
|
{
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(MinetestLogStat.class);
|
||||||
|
|
||||||
|
private int hitCount;
|
||||||
|
private int hitIpv4Count;
|
||||||
|
private int hitIpv6Count;
|
||||||
|
|
||||||
|
private int pageCount;
|
||||||
|
private int pageIpv4Count;
|
||||||
|
private int pageIpv6Count;
|
||||||
|
|
||||||
|
private int byteCount;
|
||||||
|
private int byteIpv4Count;
|
||||||
|
private int byteIpv6Count;
|
||||||
|
|
||||||
|
private int fileCount;
|
||||||
|
private int fileIpv4Count;
|
||||||
|
private int fileIpv6Count;
|
||||||
|
|
||||||
|
private int status1xxCount;
|
||||||
|
private int status2xxCount;
|
||||||
|
private int status3xxCount;
|
||||||
|
private int status4xxCount;
|
||||||
|
private int status5xxCount;
|
||||||
|
|
||||||
|
private int ipCount;
|
||||||
|
private int ipIpv4Count;
|
||||||
|
private int ipIpv6Count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new http acces log stat.
|
||||||
|
*/
|
||||||
|
public MinetestLogStat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020-2021 Christian Pierre MOMON <christian@momon.org>
|
||||||
|
*
|
||||||
|
* This file is part of StatoolInfos, simple service statistics tool.
|
||||||
|
*
|
||||||
|
* StatoolInfos is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* StatoolInfos is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with StatoolInfos. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package fr.devinsy.statoolinfos.metrics.minetest;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class MinetestProber.
|
||||||
|
*/
|
||||||
|
public class MinetestProber
|
||||||
|
{
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(MinetestProber.class);
|
||||||
|
|
||||||
|
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new minetest prober.
|
||||||
|
*/
|
||||||
|
public MinetestProber()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probe.
|
||||||
|
*
|
||||||
|
* @param logs
|
||||||
|
* the logs
|
||||||
|
* @param databaseConfig
|
||||||
|
* the database config
|
||||||
|
* @throws StatoolInfosException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static PathCounters probe(final String logs, final DatabaseConfig databaseConfig) throws IOException, StatoolInfosException
|
||||||
|
{
|
||||||
|
PathCounters result;
|
||||||
|
|
||||||
|
result = MinetestLogAnalyzer.probe(logs);
|
||||||
|
|
||||||
|
// metrics.metaverse.players
|
||||||
|
// accounts
|
||||||
|
// database size
|
||||||
|
// file size
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,15 +40,26 @@ public class IpUtils
|
||||||
/**
|
/**
|
||||||
* Checks if is ipv4.
|
* Checks if is ipv4.
|
||||||
*
|
*
|
||||||
* @param input
|
* @param value
|
||||||
* the input
|
* the value
|
||||||
* @return true, if is ipv4
|
* @return true, if is ipv4
|
||||||
*/
|
*/
|
||||||
public static boolean isIpv4(final String input)
|
public static boolean isIpv4(final String value)
|
||||||
{
|
{
|
||||||
boolean result;
|
boolean result;
|
||||||
|
|
||||||
result = IPV4_PATTERN.matcher(input).matches();
|
if (value == null)
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else if (value.startsWith("::ffff:"))
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = value.contains(".");
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
|
@ -70,4 +81,45 @@ public class IpUtils
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is ipv6.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return true, if is ipv6
|
||||||
|
*/
|
||||||
|
public static boolean isIPv6(final String value)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = value.contains(":");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is valid ipv4.
|
||||||
|
*
|
||||||
|
* @param input
|
||||||
|
* the input
|
||||||
|
* @return true, if is valid ipv4
|
||||||
|
*/
|
||||||
|
public static boolean isValidIpv4(final String input)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
result = IPV4_PATTERN.matcher(input).matches();
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue