-
Notifications
You must be signed in to change notification settings - Fork 30
Description
This s6-log config doesn't properly handle multi-line logs, which breaks any form of structured log collector (datadog, signoz, etc):
Line 7 in 104aabe
| exec > >(exec s6-log -b p"api[$$]:" 1 || true) 2>&1 |
So, we end up with logs like this:
api[523]: No webresource handler loaded.
api[523]: (node:531) NOTE: The AWS SDK for JavaScript (v2) is in maintenance mode.
api[523]: SDK releases are limited to address critical bug fixes and security issues only.
api[523]:
api[523]: Please migrate your code to use AWS SDK for JavaScript (v3).
api[523]: For more information, check the blog post at https://a.co/cUPnyil
api[523]: Successfully executed standard models.
api[523]: Successfully executed migrations model.
api[523]: Successfully executed tasks model.
api[523]: Successfully executed webresource model.
api[523]: Loading application config
api[523]: Successfully executed balena model.
api[523]: Successfully executed v7 model.
api[523]: Successfully executed v6 model.
api[523]: Async migration execution is enabled
api[523]: Creating superuser account...
api[523]: Superuser already exists!
api[523]: Server listening in development mode on port 80
api[523]: node:internal/process/promises:394
api[523]: triggerUncaughtException(err, true /* fromPromise */);
api[523]: ^
api[523]:
api[523]: Error [XMLParserError]: Non-whitespace before first tag.
api[523]: Line: 0
api[523]: Column: 1
api[523]: Char: u
api[523]: at error (/usr/src/app/node_modules/sax/lib/sax.js:667:10)
api[523]: at strictFail (/usr/src/app/node_modules/sax/lib/sax.js:693:7)
api[523]: at beginWhiteSpace (/usr/src/app/node_modules/sax/lib/sax.js:967:7)
api[523]: at SAXParser.write (/usr/src/app/node_modules/sax/lib/sax.js:1019:11)
api[523]: at exports.Parser.Parser.parseString (/usr/src/app/node_modules/xml2js/lib/parser.js:337:31)
api[523]: at Parser.parseString (/usr/src/app/node_modules/xml2js/lib/parser.js:5:59)
api[523]: at NodeXmlParser.parse (/usr/src/app/node_modules/aws-sdk/lib/xml/node_parser.js:31:10)
api[523]: at Request.extractError (/usr/src/app/node_modules/aws-sdk/lib/services/s3.js:743:39)
api[523]: at Request.callListeners (/usr/src/app/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
api[523]: at Request.emit (/usr/src/app/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
api[523]: at Request.emit (/usr/src/app/node_modules/aws-sdk/lib/request.js:686:14)
api[523]: at Request.transition (/usr/src/app/node_modules/aws-sdk/lib/request.js:22:10)
api[523]: at AcceptorStateMachine.runTo (/usr/src/app/node_modules/aws-sdk/lib/state_machine.js:14:12)
api[523]: at /usr/src/app/node_modules/aws-sdk/lib/state_machine.js:26:10
api[523]: at Request.<anonymous> (/usr/src/app/node_modules/aws-sdk/lib/request.js:38:9)
api[523]: at Request.<anonymous> (/usr/src/app/node_modules/aws-sdk/lib/request.js:688:12) {
api[523]: code: 'XMLParserError',
api[523]: retryable: true,
api[523]: time: 2025-09-10T17:57:17.788Z,
api[523]: statusCode: 503
api[523]: }
api[523]:
api[523]: Node.js v24.7.0
api[523]: Program node --enable-source-maps --loader @swc-node/register/esm-register index.js exited with code 1
api[523]:
s6-rc: info: service legacy-services: stopping
where everything in that middle code block was actually a single line of log output.
Unfortunately s6-log is line oriented, so the exec pipe has to feed something else like jq or awk first:
jq# stdout -> jq-> s6-log -> stdout exec > >(jq -R -c --arg app "api" --arg pid "$$" \ '{ts:(now|todateiso8601), app:$app, pid:($pid|tonumber), stream:"stdout", msg:.}' \ | s6-log -b -l 0 1) \ 2> >(jq -R -c --arg app "api" --arg pid "$$" \ '{ts:(now|todateiso8601), app:$app, pid:($pid|tonumber), stream:"stderr", msg:.}' \ | s6-log -b -l 0 1)
awkjson_filter() { awk -v app="$1" -v pid="$$" -v stream="$2" ' function esc(s){ gsub(/\\/,"\\\\",s); gsub(/"/,"\\\"",s); gsub(/\r/,"",s); gsub(/\t/,"\\t",s); gsub(/\n/,"\\n",s); return s } { line=$0; printf("{\"app\":\"%s\",\"pid\":%d,\"stream\":\"%s\",\"msg\":\"%s\"}\n", app, pid, stream, esc(line)); fflush() }' } exec > >(json_filter api stdout | s6-log -b -l 0 1) \ 2> >(json_filter api stderr | s6-log -b -l 0 1)
The other alternative is to use something like Pino in open-balena-api, but that would require all the various console.log and other logging calls to be reworked into a pino logger ... great long term, but the above is an easier fix. Additionally, the above works for the -s3 and -vpn projects as well that can't move to something line Pino.
(cc @klutchell )