'use strict'; exports = module.exports = { start, stop }; const LOG_FILENAME = 'app.log'; const assert = require('assert'), debug = require('debug')('syslog:server'), dgram = require('dgram'), fs = require('fs'), path = require('path'), parser = require('nsyslog-parser'), util = require('util'); let server = null; async function start(options) { assert.strictEqual(typeof options, 'object'); assert.strictEqual(typeof options.port, 'number'); assert.strictEqual(typeof options.logFolder, 'string'); debug('=========================================='); debug(' Cloudron Syslog Daemon '); debug('=========================================='); server = dgram.createSocket('udp4'); server.on('error', function (error) { console.error(`socket error: ${error}`); }); server.on('message', function (msg /*, rinfo */) { const info = parser(msg.toString()); if (!info || !info.appName) return debug('Ignore unknown app log:', msg.toString()); // remove line breaks to avoid holes in the log file // we do not ignore empty log lines, to allow gaps for potential ease of readability const message = info.message.replace(/\n/g, ''); const filePath = path.join(options.logFolder, info.appName); const fileName = path.join(filePath, LOG_FILENAME); try { fs.mkdirSync(filePath, { recursive: true }); fs.appendFileSync(fileName, info.ts.toISOString() + ' ' + message + '\n'); } catch (error) { console.error(error); } }); await util.promisify(server.bind.bind(server))(options.port); // intentional double "bind" debug(`Listening on port ${options.port}`); } async function stop() { if (!server) return; await util.promisify(server.close.bind(server))(); server = null; }