mirror of
https://github.com/AsgardEternal/SquadJS.git
synced 2024-09-28 08:24:23 -05:00
Refactor log parser
This commit is contained in:
parent
f434e94199
commit
baf07a79b6
98
core/log-parser/index.js
Normal file
98
core/log-parser/index.js
Normal file
@ -0,0 +1,98 @@
|
||||
import EventEmitter from 'events';
|
||||
|
||||
import async from 'async';
|
||||
import moment from 'moment';
|
||||
|
||||
import Logger from '../logger.js';
|
||||
|
||||
import TailLogReader from './log-readers/tail.js';
|
||||
import FTPLogReader from './log-readers/ftp.js';
|
||||
|
||||
export default class LogParser extends EventEmitter {
|
||||
constructor(filename = 'filename.log', options = {}) {
|
||||
super();
|
||||
|
||||
options.filename = filename;
|
||||
|
||||
this.eventStrore = {};
|
||||
|
||||
this.linesPerMinute = 0;
|
||||
this.matchingLinesPerMinute = 0;
|
||||
this.matchingLatency = 0;
|
||||
this.parsingStatsInterval = null;
|
||||
|
||||
this.processLine = this.processLine.bind(this);
|
||||
this.logStats = this.logStats.bind(this);
|
||||
|
||||
this.queue = async.queue(this.processLine);
|
||||
|
||||
switch (options.mode || 'tail') {
|
||||
case 'tail':
|
||||
this.logReader = new TailLogReader(this.queue.push, options);
|
||||
break;
|
||||
case 'ftp':
|
||||
this.logReader = new FTPLogReader(this.queue.push, options);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid mode.');
|
||||
}
|
||||
}
|
||||
|
||||
async processLine(line) {
|
||||
Logger.verbose('LogParser', 4, `Matching on line: ${line}`);
|
||||
|
||||
for (const rule of this.getRules()) {
|
||||
const match = line.match(rule.regex);
|
||||
if (!match) continue;
|
||||
|
||||
Logger.verbose('LogParser', 3, `Matched on line: ${match[0]}`);
|
||||
|
||||
match[1] = moment.utc(match[1], 'YYYY.MM.DD-hh.mm.ss:SSS').toDate();
|
||||
match[2] = parseInt(match[2]);
|
||||
|
||||
rule.onMatch(match, this);
|
||||
|
||||
this.matchingLinesPerMinute++;
|
||||
this.matchingLatency += Date.now() - match[1];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
this.linesPerMinute++;
|
||||
}
|
||||
|
||||
getRules() {
|
||||
return [];
|
||||
}
|
||||
|
||||
async watch() {
|
||||
Logger.verbose('LogParser', 1, 'Attempting to watch log file...');
|
||||
await this.logReader.watch();
|
||||
Logger.verbose('LogParser', 1, 'Watching log file...');
|
||||
|
||||
this.parsingStatsInterval = setInterval(this.logStats, 60 * 1000);
|
||||
}
|
||||
|
||||
logStats() {
|
||||
Logger.verbose(
|
||||
'LogParser',
|
||||
1,
|
||||
`Lines parsed per minute: ${
|
||||
this.linesPerMinute
|
||||
} lines per minute | Matching lines per minute: ${
|
||||
this.matchingLinesPerMinute
|
||||
} matching lines per minute | Average matching latency: ${
|
||||
this.matchingLatency / this.matchingLinesPerMinute
|
||||
}ms`
|
||||
);
|
||||
this.linesPerMinute = 0;
|
||||
this.matchingLinesPerMinute = 0;
|
||||
this.matchingLatency = 0;
|
||||
}
|
||||
|
||||
async unwatch() {
|
||||
await this.logReader.unwatch();
|
||||
|
||||
clearInterval(this.parsingStatsInterval);
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ export default class TailLogReader {
|
||||
encoding: 'utf8',
|
||||
verbose: options.verbose,
|
||||
|
||||
path: path.join(options.logDir, 'SquadGame.log'),
|
||||
path: path.join(options.logDir, options.filename),
|
||||
|
||||
fetchInterval: options.fetchInterval || 0,
|
||||
maxTempFileSize: options.maxTempFileSize || 5 * 1000 * 1000, // 5 MB
|
@ -1,16 +1,18 @@
|
||||
import path from 'path';
|
||||
|
||||
import TailModule from 'tail';
|
||||
|
||||
export default class TailLogReader {
|
||||
constructor(queueLine, options = {}) {
|
||||
if (!('logDir' in options)) throw new Error(`logDir must be specified.`);
|
||||
|
||||
this.reader = new TailModule.Tail(path.join(options.logDir, 'SquadGame.log'), {
|
||||
this.reader = new TailModule.Tail(path.join(options.logDir, options.filename), {
|
||||
useWatchFile: true
|
||||
});
|
||||
|
||||
if (typeof queueLine !== 'function')
|
||||
throw new Error('queueLine argument must be specified and be a function.');
|
||||
|
||||
this.reader.on('line', queueLine);
|
||||
}
|
||||
|
@ -3,11 +3,16 @@
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./log-parser": "./log-parser/index.js",
|
||||
"./constants": "./constants.js",
|
||||
"./logger": "./logger.js",
|
||||
"./rcon": "./rcon.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.0"
|
||||
"async": "^3.2.0",
|
||||
"chalk": "^4.1.0",
|
||||
"ftp-tail": "^1.1.1",
|
||||
"moment": "^2.29.1",
|
||||
"tail": "^2.0.4"
|
||||
}
|
||||
}
|
||||
|
@ -1,87 +0,0 @@
|
||||
import EventEmitter from 'events';
|
||||
|
||||
import async from 'async';
|
||||
import moment from 'moment';
|
||||
|
||||
import Logger from 'core/logger';
|
||||
|
||||
import TailLogReader from './log-readers/tail.js';
|
||||
import FTPLogReader from './log-readers/ftp.js';
|
||||
|
||||
import rules from './rules/index.js';
|
||||
|
||||
export default class LogParser extends EventEmitter {
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
|
||||
this.eventStore = {};
|
||||
|
||||
this.linesPerMinute = 0;
|
||||
this.matchingLinesPerMinute = 0;
|
||||
this.matchingLatency = 0;
|
||||
this.parsingStatsInterval = null;
|
||||
|
||||
this.queue = async.queue(async (line) => {
|
||||
Logger.verbose('LogParser', 4, `Matching on line: ${line}`);
|
||||
|
||||
for (const rule of rules) {
|
||||
const match = line.match(rule.regex);
|
||||
if (!match) continue;
|
||||
|
||||
Logger.verbose('LogParser', 3, `Matched on line: ${match[0]}`);
|
||||
|
||||
match[1] = moment.utc(match[1], 'YYYY.MM.DD-hh.mm.ss:SSS').toDate();
|
||||
match[2] = parseInt(match[2]);
|
||||
|
||||
rule.onMatch(match, this);
|
||||
|
||||
this.matchingLinesPerMinute++;
|
||||
this.matchingLatency += Date.now() - match[1];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
this.linesPerMinute++;
|
||||
});
|
||||
|
||||
switch (options.mode || 'tail') {
|
||||
case 'tail':
|
||||
this.logReader = new TailLogReader(this.queue.push, options);
|
||||
break;
|
||||
case 'ftp':
|
||||
this.logReader = new FTPLogReader(this.queue.push, options);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid mode.');
|
||||
}
|
||||
}
|
||||
|
||||
async watch() {
|
||||
Logger.verbose('LogParser', 1, 'Attempting to watch log file...');
|
||||
await this.logReader.watch();
|
||||
Logger.verbose('LogParser', 1, 'Watching log file...');
|
||||
|
||||
this.parsingStatsInterval = setInterval(() => {
|
||||
Logger.verbose(
|
||||
'LogParser',
|
||||
1,
|
||||
`Lines parsed per minute: ${
|
||||
this.linesPerMinute
|
||||
} lines per minute | Matching lines per minute: ${
|
||||
this.matchingLinesPerMinute
|
||||
} matching lines per minute | Average matching latency: ${
|
||||
this.matchingLatency / this.matchingLinesPerMinute
|
||||
}ms`
|
||||
);
|
||||
this.linesPerMinute = 0;
|
||||
this.matchingLinesPerMinute = 0;
|
||||
this.matchingLatency = 0;
|
||||
}, 60 * 1000);
|
||||
}
|
||||
|
||||
async unwatch() {
|
||||
await this.logReader.unwatch();
|
||||
|
||||
clearInterval(this.parsingStatsInterval);
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "log-parser",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^3.2.0",
|
||||
"ftp-tail": "^1.1.1",
|
||||
"moment": "^2.29.0",
|
||||
"tail": "^2.0.4"
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@
|
||||
"workspaces": [
|
||||
"assets",
|
||||
"core",
|
||||
"log-parser",
|
||||
"squad-server"
|
||||
],
|
||||
"scripts": {
|
||||
|
@ -116,14 +116,19 @@ export default class SquadServerFactory {
|
||||
if (type === 'sequelize') {
|
||||
let connector;
|
||||
|
||||
if(typeof connectorConfig === 'string') {
|
||||
connector = new Sequelize(connectorConfig, { logging: msg => Logger.verbose('Sequelize', 3, msg) })
|
||||
if (typeof connectorConfig === 'string') {
|
||||
connector = new Sequelize(connectorConfig, {
|
||||
logging: (msg) => Logger.verbose('Sequelize', 3, msg)
|
||||
});
|
||||
} else if (typeof connectorConfig === 'object') {
|
||||
connector = new Sequelize({ ...connectorConfig, logging: msg => Logger.verbose('Sequelize', 3, msg) });
|
||||
connector = new Sequelize({
|
||||
...connectorConfig,
|
||||
logging: (msg) => Logger.verbose('Sequelize', 3, msg)
|
||||
});
|
||||
} else {
|
||||
throw new Error('Unknown sequelize connector config type.');
|
||||
}
|
||||
|
||||
|
||||
await connector.authenticate();
|
||||
return connector;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import Gamedig from 'gamedig';
|
||||
import Logger from 'core/logger';
|
||||
import { SQUADJS_API_DOMAIN } from 'core/constants';
|
||||
|
||||
import LogParser from 'log-parser';
|
||||
import LogParser from './log-parser/index.js';
|
||||
import Rcon from './rcon.js';
|
||||
|
||||
import { SQUADJS_VERSION } from './utils/constants.js';
|
||||
|
@ -1,3 +1,5 @@
|
||||
import LogParser from 'core/log-parser';
|
||||
|
||||
import AdminBroadcast from './admin-broadcast.js';
|
||||
import NewGame from './new-game.js';
|
||||
import PlayerConnected from './player-connected.js';
|
||||
@ -11,17 +13,25 @@ import RoundWinner from './round-winner.js';
|
||||
import ServerTickRate from './server-tick-rate.js';
|
||||
import SteamIDConnected from './steamid-connected.js';
|
||||
|
||||
export default [
|
||||
AdminBroadcast,
|
||||
NewGame,
|
||||
PlayerConnected,
|
||||
PlayerDamaged,
|
||||
PlayerDied,
|
||||
PlayerPossess,
|
||||
PlayerRevived,
|
||||
PlayerUnPossess,
|
||||
PlayerWounded,
|
||||
RoundWinner,
|
||||
ServerTickRate,
|
||||
SteamIDConnected
|
||||
];
|
||||
export default class SquadLogParser extends LogParser {
|
||||
constructor(options) {
|
||||
super('SquadGame.log', options);
|
||||
}
|
||||
|
||||
getRules() {
|
||||
return [
|
||||
AdminBroadcast,
|
||||
NewGame,
|
||||
PlayerConnected,
|
||||
PlayerDamaged,
|
||||
PlayerDied,
|
||||
PlayerPossess,
|
||||
PlayerRevived,
|
||||
PlayerUnPossess,
|
||||
PlayerWounded,
|
||||
RoundWinner,
|
||||
ServerTickRate,
|
||||
SteamIDConnected
|
||||
];
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@
|
||||
"didyoumean": "^1.2.1",
|
||||
"discord.js": "^12.3.1",
|
||||
"gamedig": "^2.0.20",
|
||||
"log-parser": "1.0.0",
|
||||
"mariadb": "^2.5.1",
|
||||
"mysql2": "^2.2.5",
|
||||
"pg": "^8.5.1",
|
||||
|
Loading…
Reference in New Issue
Block a user