mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-19 05:37:53 +00:00
Add an endpoint and module for reading journald logs
Change-type: minor Closes: #1003 Signed-off-by: Cameron Diver <cameron@balena.io>
This commit is contained in:
parent
fa26988ca6
commit
43cbf7dbba
35
docs/API.md
35
docs/API.md
@ -1149,6 +1149,7 @@ Response:
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### V2 Utilities
|
||||
|
||||
#### Cleanup volumes with no references
|
||||
@ -1179,3 +1180,37 @@ Unsuccessful response:
|
||||
}
|
||||
```
|
||||
|
||||
#### Journald logs
|
||||
|
||||
Added in supervisor version v10.1.0
|
||||
|
||||
Retrieve a stream to the journald logs on device. This is
|
||||
equivalent to running `journalctl -o export`. Options
|
||||
supported are:
|
||||
|
||||
##### all: boolean
|
||||
Show all fields in full, equivalent to `journalctl --all`.
|
||||
|
||||
##### follow: boolean
|
||||
Continuously stream logs as they are generated, equivalent
|
||||
to `journalctl --follow`.
|
||||
|
||||
##### count: integer
|
||||
Show the most recent `count` events, equivalent to
|
||||
`journalctl --line=<count>`.
|
||||
|
||||
##### unit
|
||||
Show journal logs from `unit` only, equivalent to
|
||||
`journalctl --unit=<unit>`.
|
||||
|
||||
Fields should be provided via POST body in JSON format.
|
||||
|
||||
From an application container (with systemd installed):
|
||||
```
|
||||
$ curl -X POST --data '{"follow":true,"all":true}' "$BALENA_SUPERVISOR_ADDRESS/v2/journal-logs?apikey=$BALENA_SUPERVISOR_API_KEY" | systemd-journal-remote - -o log.journal
|
||||
```
|
||||
|
||||
The `log.journal` file can then be viewed with
|
||||
```
|
||||
journalctl --file log.journal -f
|
||||
```
|
||||
|
@ -13,8 +13,11 @@ import {
|
||||
import { doPurge, doRestart, serviceAction } from './common';
|
||||
|
||||
import Volume from '../compose/volume';
|
||||
import { spawnJournalctl } from '../lib/journald';
|
||||
|
||||
import log from '../lib/supervisor-console';
|
||||
import supervisorVersion = require('../lib/supervisor-version');
|
||||
import { checkInt, checkTruthy } from '../lib/validation';
|
||||
|
||||
export function createV2Api(router: Router, applications: ApplicationManager) {
|
||||
const { _lockingIfNecessary, deviceState } = applications;
|
||||
@ -533,4 +536,32 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/v2/journal-logs', (req, res) => {
|
||||
try {
|
||||
const all = checkTruthy(req.body.all) || false;
|
||||
const follow = checkTruthy(req.body.follow) || false;
|
||||
const count = checkInt(req.body.count, { positive: true }) || undefined;
|
||||
const unit = req.body.unit;
|
||||
|
||||
const journald = spawnJournalctl({ all, follow, count, unit });
|
||||
res.status(200);
|
||||
journald.stdout.pipe(res);
|
||||
res.on('close', () => {
|
||||
journald.kill('SIGKILL');
|
||||
});
|
||||
journald.on('exit', () => {
|
||||
res.end();
|
||||
});
|
||||
} catch (e) {
|
||||
log.error('There was an error reading the journalctl process', e);
|
||||
if (res.headersSent) {
|
||||
return;
|
||||
}
|
||||
res.json({
|
||||
status: 'failed',
|
||||
message: messageFromError(e),
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
41
src/lib/journald.ts
Normal file
41
src/lib/journald.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { ChildProcess, spawn } from 'child_process';
|
||||
|
||||
import constants = require('./constants');
|
||||
import log from './supervisor-console';
|
||||
|
||||
export function spawnJournalctl(opts: {
|
||||
all: boolean;
|
||||
follow: boolean;
|
||||
count?: number;
|
||||
unit?: string;
|
||||
}): ChildProcess {
|
||||
const args = [
|
||||
// The directory we want to run the chroot from
|
||||
constants.rootMountPoint,
|
||||
'journalctl',
|
||||
'-o',
|
||||
'export',
|
||||
];
|
||||
if (opts.all) {
|
||||
args.push('-a');
|
||||
}
|
||||
if (opts.follow) {
|
||||
args.push('--follow');
|
||||
}
|
||||
if (opts.unit != null) {
|
||||
args.push('-u');
|
||||
args.push(opts.unit);
|
||||
}
|
||||
if (opts.count != null) {
|
||||
args.push('-n');
|
||||
args.push(opts.count.toString());
|
||||
}
|
||||
|
||||
log.debug('Spawning journald with: chroot ', args.join(' '));
|
||||
|
||||
const journald = spawn('chroot', args, {
|
||||
stdio: 'pipe',
|
||||
});
|
||||
|
||||
return journald;
|
||||
}
|
Loading…
Reference in New Issue
Block a user