syslog: restructure code

This commit is contained in:
Girish Ramakrishnan
2023-04-14 19:31:45 +02:00
parent 158ba4ea0b
commit 4c475818bc
11 changed files with 65 additions and 1754 deletions

6
package-lock.json generated
View File

@@ -39,6 +39,7 @@
"multiparty": "^4.2.3",
"mysql": "^2.18.1",
"nodemailer": "^6.9.1",
"nsyslog-parser": "^0.10.1",
"oidc-provider": "^7.14.3",
"qrcode": "^1.5.1",
"readdirp": "^3.6.0",
@@ -4132,6 +4133,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/nsyslog-parser": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/nsyslog-parser/-/nsyslog-parser-0.10.1.tgz",
"integrity": "sha512-38XUyNf4j1nDXCpPIcGLxNxGceBUpSv06wQgcY3niZ7bydIDvyWr779Cx3RMjWpgib02hjueDUp84S15C9s5lQ=="
},
"node_modules/nwsapi": {
"version": "2.2.2",
"license": "MIT"

View File

@@ -3,7 +3,10 @@
"description": "Main code for a cloudron",
"version": "1.0.0",
"private": true,
"contributors": [ "Girish", "Johannes" ],
"contributors": [
"Girish",
"Johannes"
],
"repository": {
"type": "git",
"url": "https://git.cloudron.io/cloudron/box.git"
@@ -44,6 +47,7 @@
"multiparty": "^4.2.3",
"mysql": "^2.18.1",
"nodemailer": "^6.9.1",
"nsyslog-parser": "^0.10.1",
"oidc-provider": "^7.14.3",
"qrcode": "^1.5.1",
"readdirp": "^3.6.0",

View File

@@ -4,7 +4,7 @@ set -eu
readonly source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly DATA_DIR="${HOME}/.cloudron_test"
readonly DEFAULT_TESTS="./src/test/*-test.js ./src/routes/test/*-test.js"
readonly DEFAULT_TESTS="./syslog/*-test.js ./src/test/*-test.js ./src/routes/test/*-test.js"
! "${source_dir}/src/test/check-install" && exit 1
@@ -67,7 +67,7 @@ echo "=> Create iptables blocklist"
sudo ipset create cloudron_blocklist hash:net || true
echo "=> Starting cloudron-syslog"
cloudron-syslog --logdir "${DATA_DIR}/platformdata/logs/" &
syslog/syslog-service.js "${DATA_DIR}/platformdata/logs/" &
echo "=> Ensure database"
mysql -h"${MYSQL_IP}" -uroot -ppassword -e 'CREATE DATABASE IF NOT EXISTS box'

View File

@@ -127,6 +127,9 @@ if ! which node 2>/dev/null || [[ "$(node --version)" != "v${node_version}" ]];
rm -rf /usr/local/node-16.14.2
fi
# obsolete module
rm -rf /usr/local/cloudron-syslog
# note that rebuild requires the above node
for try in `seq 1 10`; do
# for reasons unknown, the dtrace package will fail. but rebuilding second time will work
@@ -166,19 +169,6 @@ for image in ${images}; do
done
done
log "update cloudron-syslog"
CLOUDRON_SYSLOG_DIR=/usr/local/cloudron-syslog
CLOUDRON_SYSLOG="${CLOUDRON_SYSLOG_DIR}/bin/cloudron-syslog"
CLOUDRON_SYSLOG_VERSION="1.1.0"
while [[ ! -f "${CLOUDRON_SYSLOG}" || "$(${CLOUDRON_SYSLOG} --version)" != ${CLOUDRON_SYSLOG_VERSION} ]]; do
rm -rf "${CLOUDRON_SYSLOG_DIR}"
mkdir -p "${CLOUDRON_SYSLOG_DIR}"
# verbatim is not needed in node 18 since that is the default there. in node 16, ipv4 is preferred and this breaks on ipv6 only servers
if NODE_OPTIONS="--dns-result-order=verbatim" npm install --unsafe-perm -g --prefix "${CLOUDRON_SYSLOG_DIR}" cloudron-syslog@${CLOUDRON_SYSLOG_VERSION}; then break; fi
log "Failed to install cloudron-syslog, trying again"
sleep 5
done
log "creating cloudron-support user"
if ! id cloudron-support 2>/dev/null; then
useradd --system --comment "Cloudron Support (support@cloudron.io)" --create-home --no-user-group --shell /bin/bash cloudron-support

View File

@@ -3,9 +3,9 @@ Description=Cloudron Syslog
After=network.target
[Service]
ExecStart=/usr/local/cloudron-syslog/bin/cloudron-syslog --port 2514 --logdir /home/yellowtent/platformdata/logs
WorkingDirectory=/usr/local/cloudron-syslog
Environment="NODE_ENV=production"
ExecStart=/home/yellowtent/box/syslog/service.js
WorkingDirectory=/home/yellowtent/box
Environment="NODE_ENV=production" "DEBUG=syslog:*"
Restart=always
User=yellowtent
Group=yellowtent

View File

@@ -1,36 +0,0 @@
#!/usr/bin/env node
'use strict';
const server = require('./server.js');
const argv = require('yargs')
.default('port', 2514, 'The port to listen on') // syslog is 514 so we prefix with 2
.default('logdir', '/tmp/logs', 'The root log directory')
.argv;
const options = {
logFolder: argv.logdir,
port: argv.port
};
if (argv.version) {
console.log('1.0.1');
process.exit(0);
}
console.log();
console.log('==========================================');
console.log(' Cloudron Syslog Daemon ');
console.log('==========================================');
console.log();
console.log(' Log Folder: ', options.logFolder);
console.log(' UDP Port: ', options.port);
console.log();
console.log('==========================================');
console.log();
server.start(options, function (error) {
if (error) return console.error(error);
console.log('Listening...');
});

1642
syslog/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +0,0 @@
{
"name": "cloudron-syslog",
"version": "1.1.0",
"description": "Cloudron Syslog Daemon listening on port 2514",
"main": "index.js",
"scripts": {
"test": "./node_modules/.bin/mocha ./test.js"
},
"bin": {
"cloudron-syslog": "./index.js"
},
"repository": {
"type": "git",
"url": "https://git.cloudron.io/cloudron/cloudron-syslog.git"
},
"author": "Cloudron Developers",
"license": "MIT",
"dependencies": {
"nsyslog-parser": "^0.9.6",
"yargs": "^17.3.1"
},
"devDependencies": {
"expect.js": "^0.3.1",
"grepit": "^1.0.0",
"mocha": "^9.1.3"
}
}

View File

@@ -8,29 +8,34 @@ exports = module.exports = {
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');
parser = require('nsyslog-parser'),
util = require('util');
let server = null;
function start(options, callback) {
async function start(options) {
assert.strictEqual(typeof options, 'object');
assert.strictEqual(typeof options.port, 'number');
assert.strictEqual(typeof options.logFolder, 'string');
assert.strictEqual(typeof callback, 'function');
debug('==========================================');
debug(' Cloudron Syslog Daemon ');
debug('==========================================');
server = dgram.createSocket('udp4');
server.on('error', function (error) {
callback(error);
}).on('listening', function () {
callback();
}).on('message', function (msg /*, rinfo */) {
console.error(`socket error: ${error}`);
});
server.on('message', function (msg /*, rinfo */) {
const info = parser(msg.toString());
if (!info || !info.appName) return console.log('Ignore unknown app log:', 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
@@ -45,17 +50,15 @@ function start(options, callback) {
} catch (error) {
console.error(error);
}
}).bind(options.port);
});
await util.promisify(server.bind.bind(server))(options.port); // intentional double "bind"
debug(`Listening on port ${options.port}`);
}
function stop(callback) {
assert.strictEqual(typeof callback, 'function');
if (!server) return callback();
server.close();
async function stop() {
if (!server) return;
await util.promisify(server.close.bind(server))();
server = null;
callback();
}
}

16
syslog/service.js Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env node
'use strict';
const server = require('./server.js');
const options = {
logFolder: process.argv[2] || '/home/yellowtent/platformdata/logs',
port: 2514
};
async function main() {
await server.start(options);
}
main();

View File

@@ -9,7 +9,6 @@
const dgram = require('dgram'),
expect = require('expect.js'),
fs = require('fs'),
grepit = require('grepit'),
path = require('path'),
os = require('os'),
server = require('./server.js');
@@ -19,6 +18,7 @@ const LOG_FOLDER = path.join(os.tmpdir(), '/cloudron-syslog-test/');
function sendMessage(message, callback) {
const client = dgram.createSocket('udp4');
client.send(message, PORT, 'localhost', function (error) {
if (error) return callback(error);
@@ -31,25 +31,22 @@ function sendMessage(message, callback) {
function verifyMessage(pattern, fileName, callback) {
// give the server some time to write to disk
setTimeout(function () {
const found = grepit(pattern, path.join(LOG_FOLDER, fileName));
if (found.length === 0) return callback('not found');
callback();
const data = fs.readFileSync(path.join(LOG_FOLDER, fileName), { encoding: 'utf8' });
const found = data.match(new RegExp(pattern));
return callback(found === null ? new Error('not found') : null);
}, 250);
}
describe('Daemon', function () {
this.timeout(5000);
after(function (done) {
after(async function () {
fs.rmSync(LOG_FOLDER, { recursive: true, force: true });
server.stop(done);
await server.stop();
});
it('can start', function (done) {
server.start({ port: PORT, logFolder: LOG_FOLDER }, function (error) {
expect(error).to.not.be.ok();
done();
});
it('can start', async function () {
await server.start({ port: PORT, logFolder: LOG_FOLDER });
});
it('handle good message', function (done) {