mirror of
https://github.com/AsgardEternal/SquadJS.git
synced 2024-09-28 17:34:25 -05:00
49809169b8
pending connection destroyed: error path for clients that fail to connect, required to cleanup connection state in this error case. client-connected: Supersedes steamid connected, use base unreal engine client flow. Removes dependancy on EAC (broken as of squad 3.4). First step in resolving a new client connection. this gets us a connection id, steamid. client-login: 2nd step in player connected flow, this setups the steamid into eventstore.steamid-connected. playercontroller connected: gets us player controller. used in player connected flow. player-connected: update to use new eventStore layout, now all players should always have suffix,steamid,controller. These are now also cached within the logparser for lookup. last step in player connected flow. player-disconnected: uses new eventStore layout, marks players in eventStore.disconnected but doesn't remove cached players till map change; may be needed in cases with delayed logs, needs further testing. Broken as of Squad 3.4 due to EAC changes steamid-connected: Removed in favor of client-connected, no longer works as of squad 3.4 due to EAC changes.
117 lines
3.2 KiB
JavaScript
117 lines
3.2 KiB
JavaScript
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.eventStore = {
|
|
disconnected: {}, // holding area, cleared on map change.
|
|
players: {}, // persistent data, steamid, controller, suffix.
|
|
session: {}, // old eventstore, nonpersistent data
|
|
clients: {} // used in the connection chain before we resolve a player.
|
|
};
|
|
|
|
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++;
|
|
}
|
|
|
|
// manage cleanup disconnected players, session data.
|
|
clearEventStore() {
|
|
Logger.verbose('LogParser', 2, 'Cleaning Eventstore');
|
|
for (const player of Object.values(this.eventStore.players)) {
|
|
if (this.eventStore.disconnected[player.steamID] === true) {
|
|
Logger.verbose('LogParser', 2, `Removing ${player.steamID} from eventStore`);
|
|
delete this.eventStore.players[player.steamID];
|
|
delete this.eventStore.disconnected[player.steamID];
|
|
}
|
|
}
|
|
this.eventStore.session = {};
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|