syslog-portal
Version:
A portal for ingesting syslog data
126 lines • 5.19 kB
JavaScript
import { EventEmitter } from 'events';
const NIL = '-';
export class BaseServer extends EventEmitter {
_port;
_log;
_listeners = new Set();
_healthMonitor;
_entityId;
constructor(config, logger, watchDog) {
super();
this._port = config.serverPort;
this._log = logger;
this._healthMonitor = watchDog;
}
parseMessage(data, remoteInfo) {
const textData = data.toString('ascii');
try {
const parserState = {
position: 0,
};
const pri = this.extractPri(textData, parserState);
this._log.trace('Facility: %s, Severity: %s', pri.facility, pri.severity);
const version = this.extractVersion(textData, parserState);
this._log.trace('Version: %s', version);
const timestamp = this.extractTimestamp(textData, parserState);
this._log.trace('Timestamp: %s', timestamp);
const hostname = this.extractToken(textData, parserState);
this._log.trace('Hostname: %s', hostname);
const app = this.extractToken(textData, parserState);
this._log.trace('App: %s', app);
const procId = this.extractToken(textData, parserState);
this._log.trace('ProcID: %d', procId);
const msgId = this.extractToken(textData, parserState);
this._log.trace('MsgID: %s', msgId);
const sd = this.extractToken(textData, parserState);
this._log.trace('SD: %s', sd);
const msg = textData.slice(parserState.position).trim();
this._log.trace('Msg: %s', msg);
const msgDto = {
facility: pri.facility,
severity: pri.severity,
procId: procId !== NIL ? parseInt(procId) : undefined,
msgId: msgId !== NIL ? msgId : undefined,
app: app !== NIL ? app : undefined,
message: msg,
timestamp,
hostname,
modelVersion: 1,
};
this.emitLogMessage(msgDto).catch((err) => {
this._log.warn(`Error occurred during event handler chain for log messages: ${err}`);
});
}
catch (err) {
this._log.error(err, 'Encountered error while parsing message: %s, incoming message: %s', err.message, textData);
}
}
extractToken(data, parserState) {
const str = data.slice(parserState.position).trimStart();
const endPos = str.indexOf(' ');
if (endPos === -1)
throw new Error('Unable to tokenize value');
const token = str.slice(0, endPos);
parserState.position += endPos + 1;
return token.trim();
}
extractTimestamp(data, parserState) {
const token = this.extractToken(data, parserState);
const ts = Date.parse(token);
if (isNaN(ts))
throw new Error(`Failed to parse date from ${token}`);
return new Date(ts);
}
extractVersion(data, parserState) {
const version = data.slice(parserState.position, parserState.position + 1);
parserState.position++;
return version;
}
extractPri(data, parserState) {
if (data[0] !== '<') {
throw new Error(`Incoming message did not start with <, instead received ${data[0]}`);
}
const possiblePri = data.slice(0, 5);
const closingChar = possiblePri.indexOf('>');
if (closingChar === -1) {
throw new Error('Missing closing > in PRI, invalid header!');
}
const PRI = possiblePri.slice(1, closingChar);
const PRINumber = parseInt(PRI);
if (isNaN(PRINumber))
throw new Error(`PRI is not a parsable number: ${PRI}`);
const facility = Math.trunc(PRINumber / 8);
const severity = PRINumber % facility;
parserState.position = closingChar + 1;
return {
facility: facility,
severity: severity,
};
}
async emitLogMessage(message) {
this._log.debug('Emitting log message event to (%s) listeners', this._listeners.size);
for (const listener of this._listeners.values()) {
this._log.trace('Emitting log message to listener');
await listener.onLogMessage(message).catch((err) => {
this._log.error(err, 'Error occurred while emitting log message to listener: %s', err.message);
throw err;
});
this._log.trace('Finished emitting log message to listener');
}
this._log.debug('Finished Emitting log message event');
}
onLogMessage(listener) {
this._log.info('Adding log message listener');
this._listeners.add(listener);
this._log.info('Listeners: %s', this._listeners.size);
}
offLogMessage(listener) {
this._log.info('Removing log message listener');
this._listeners.delete(listener);
this._log.info('Listeners: %s', this._listeners.size);
}
pingMonitor() {
this._healthMonitor.kick(this._entityId);
}
}
//# sourceMappingURL=baseServer.js.map