Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

32 logging #1870

Merged
merged 5 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ module.exports = (grunt) => {
const fork2 = function () {
grunt.log.writeln('backend: forking...')
child = fork(backendIndex, process.argv, {
env: process.env,
env: { NODE_ENV, ...process.env },
execArgv: ['--require', '@babel/register']
})
child.on('error', (err) => {
Expand Down
2 changes: 1 addition & 1 deletion backend/database-sqlite.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export async function initStorage (options: Object = {}): Promise<void> {
})
})
await run('CREATE TABLE IF NOT EXISTS Data(key TEXT NOT NULL PRIMARY KEY, value TEXT NOT NULL)')
console.log('Connected to the %s SQLite database.', filename)
console.info(`Connected to the ${filename} SQLite database.`)
readStatement = db.prepare('SELECT value FROM Data WHERE key = ?')
writeStatement = db.prepare('REPLACE INTO Data(key, value) VALUES(?, ?)')
}
Expand Down
12 changes: 6 additions & 6 deletions backend/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ sbp('sbp/selectors/register', {
this.push(null)
}
} catch (e) {
console.error(`read(): ${e.message}:`, e)
console.error(e, `read(): ${e.message}`)
this.push(']')
this.push(null)
}
Expand Down Expand Up @@ -94,7 +94,7 @@ sbp('sbp/selectors/register', {
}
} catch (e) {
// TODO: properly return an error to caller, see https://nodejs.org/api/stream.html#errors-while-reading
console.error(`read(): ${e.message}:`, e)
console.error(e, `read(): ${e.message}:`)
this.push(']')
this.push(null)
}
Expand Down Expand Up @@ -132,7 +132,7 @@ sbp('sbp/selectors/register', {
}
} catch (e) {
// TODO: properly return an error to caller, see https://nodejs.org/api/stream.html#errors-while-reading
console.error(`read(): ${e.message}:`, e)
console.error(e, `read(): ${e.message}:`)
this.push(']')
this.push(null)
}
Expand Down Expand Up @@ -227,7 +227,7 @@ export default async () => {
let numVisitedKeys = 0
let numNewKeys = 0

console.log('[chelonia.db] Preloading...')
console.info('[chelonia.db] Preloading...')
for (const key of keys) {
// Skip keys which are already in the DB.
if (!persistence || !await sbp('chelonia/db/get', key)) {
Expand All @@ -240,10 +240,10 @@ export default async () => {
}
numVisitedKeys++
if (numVisitedKeys % Math.floor(numKeys / 10) === 0) {
console.log(`[chelonia.db] Preloading... ${numVisitedKeys / Math.floor(numKeys / 10)}0% done`)
console.info(`[chelonia.db] Preloading... ${numVisitedKeys / Math.floor(numKeys / 10)}0% done`)
}
}
numNewKeys && console.log(`[chelonia.db] Preloaded ${numNewKeys} new entries`)
numNewKeys && console.info(`[chelonia.db] Preloaded ${numNewKeys} new entries`)
}
await initZkpp()
}
68 changes: 55 additions & 13 deletions backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,69 @@ import '@sbp/okturtles.events'
import { SERVER_RUNNING } from './events.js'
import { PUBSUB_INSTANCE } from './instance-keys.js'
import chalk from 'chalk'
import pino from 'pino'

global.logger = function (err) {
console.error(err)
err.stack && console.error(err.stack)
return err // routes.js is written in a way that depends on this returning the error
// NOTE: enabling pretty print does add a slight bit of overhead to logging and therefore is not recommended in production
// Learn more about the Pino API here: https://github.com/pinojs/pino/blob/master/docs/api.md
const prettyPrint = process.env.NODE_ENV === 'development' || process.env.CI || process.env.CYPRESS_RECORD_KEY || process.env.PRETTY
// support regular console.log('asdf', 'adsf', 'adsf') style logging that might be used by libraries
// https://github.com/pinojs/pino/blob/master/docs/api.md#interpolationvalues-any
function logMethod (args, method) {
const stringIdx = typeof args[0] === 'string' ? 0 : 1
if (args.length > 1) {
for (let i = stringIdx + 1; i < args.length; ++i) {
args[stringIdx] += typeof args[i] === 'string' ? ' %s' : ' %o'
}
}
method.apply(this, args)
}
const logger = pino(prettyPrint
? {
hooks: { logMethod },
transport: {
target: 'pino-pretty',
options: {
colorize: true
}
}
}
: { hooks: { logMethod } })

const logLevel = process.env.LOG_LEVEL || (prettyPrint ? 'debug' : 'info')
if (Object.keys(logger.levels.values).includes(logLevel)) {
logger.level = logLevel
} else {
logger.warn(`Unknown log level: ${logLevel}`)
}

global.logger = logger // $FlowExpectedError
console.debug = logger.debug.bind(logger) // $FlowExpectedError
console.info = logger.info.bind(logger) // $FlowExpectedError
console.log = logger.info.bind(logger) // $FlowExpectedError
console.warn = logger.warn.bind(logger) // $FlowExpectedError
console.error = logger.error.bind(logger)

console.info('NODE_ENV =', process.env.NODE_ENV)

const dontLog = { 'backend/server/broadcastEntry': true }

function logSBP (domain, selector, data) {
function logSBP (domain, selector, data: Array<*>) {
if (!dontLog[selector]) {
console.log(chalk.bold(`[sbp] ${selector}`), data)
if (selector === 'backend/server/handleEntry') {
console.debug(chalk.bold(`[sbp] ${selector}`), data[0].description())
} else {
console.debug(chalk.bold(`[sbp] ${selector}`), data)
}
}
}

;['backend'].forEach(domain => sbp('sbp/filters/domain/add', domain, logSBP))
// any specific selectors outside of backend namespace to log
;[].forEach(sel => sbp('sbp/filters/selector/add', sel, logSBP))

module.exports = (new Promise((resolve, reject) => {
sbp('okTurtles.events/on', SERVER_RUNNING, function () {
console.log(chalk.bold('backend startup sequence complete.'))
console.info(chalk.bold('backend startup sequence complete.'))
resolve()
})
// call this after we've registered listener for SERVER_RUNNING
Expand All @@ -35,17 +77,17 @@ module.exports = (new Promise((resolve, reject) => {

const shutdownFn = function (message) {
sbp('okTurtles.data/apply', PUBSUB_INSTANCE, function (pubsub) {
console.log('message received in child, shutting down...', message)
console.info('message received in child, shutting down...', message)
pubsub.on('close', async function () {
try {
await sbp('backend/server/stop')
console.log('Hapi server down')
console.info('Hapi server down')
// await db.stop()
// console.log('database stopped')
// console.info('database stopped')
process.send({}) // tell grunt we've successfully shutdown the server
process.nextTick(() => process.exit(0)) // triple-check we quit :P
} catch (err) {
console.error('Error during shutdown:', err)
console.error(err, 'Error during shutdown')
process.exit(1)
}
})
Expand All @@ -63,12 +105,12 @@ process.on('SIGUSR2', shutdownFn)
process.on('message', shutdownFn)

process.on('uncaughtException', (err) => {
console.error('[server] Unhandled exception:', err, err.stack)
console.error(err, '[server] Unhandled exception')
process.exit(1)
})

process.on('unhandledRejection', (reason, p) => {
console.error('[server] Unhandled promise rejection:', p, 'reason:', reason)
console.error(reason, '[server] Unhandled promise rejection:', reason)
process.exit(1)
})

Expand Down
23 changes: 11 additions & 12 deletions backend/pubsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ const generateSocketID = (() => {
return (debugID) => String(counter++) + (debugID ? '-' + debugID : '')
})()

const log = console.log.bind(console, tag)
log.bold = (...args) => console.log(bold(tag, ...args))
log.debug = console.debug.bind(console, tag)
log.error = (...args) => console.error(bold.red(tag, ...args))
const log = logger.info.bind(logger, tag)
log.bold = (...args) => logger.debug(bold(tag, ...args))
log.debug = logger.debug.bind(logger, tag)
log.error = (error, ...args) => logger.error(error, bold.red(tag, ...args))

// ====== API ====== //

Expand Down Expand Up @@ -175,21 +175,20 @@ const defaultServerHandlers = {
socket.on(eventName, (...args) => {
// Logging of 'message' events is handled in the default 'message' event handler.
if (eventName !== 'message') {
log(`Event '${eventName}' on socket ${socket.id}`, ...args.map(arg => String(arg)))
log.debug(`Event '${eventName}' on socket ${socket.id}`, ...args.map(arg => String(arg)))
}
try {
(defaultSocketEventHandlers: Object)[eventName]?.call(socket, ...args)
socket.server.customSocketEventHandlers[eventName]?.call(socket, ...args)
} catch (error) {
socket.server.emit('error', error)
socket.server.emit(error, 'error in socket connection')
socket.terminate()
}
})
})
},
error (error: Error) {
log.error('Server error:', error)
logger(error)
log.error(error, 'Server error')
},
headers () {
},
Expand Down Expand Up @@ -221,13 +220,13 @@ const defaultSocketEventHandlers = {
try {
msg = messageParser(text)
} catch (error) {
log.error(`Malformed message: ${error.message}`)
log.error(error, `Malformed message: ${error.message}`)
server.rejectMessageAndTerminateSocket(msg, socket)
return
}
// Now that we have successfully parsed the message, we can log it.
if (msg.type !== 'pong' || server.options.logPongMessages) {
log(`Received '${msg.type}' on socket ${socket.id}`, text)
log.debug(`Received '${msg.type}' on socket ${socket.id}`, text)
}
// The socket can be marked as active since it just received a message.
socket.activeSinceLastPing = true
Expand All @@ -238,7 +237,7 @@ const defaultSocketEventHandlers = {
handler.call(socket, msg)
} catch (error) {
// Log the error message and stack trace but do not send it to the client.
logger(error)
log.error(error, 'onMesage')
server.rejectMessageAndTerminateSocket(msg, socket)
}
} else {
Expand Down Expand Up @@ -282,7 +281,7 @@ const defaultMessageHandlers = {
// Add this socket to the channel subscribers.
server.subscribersByChannelID[channelID].add(socket)
} else {
log('Already subscribed to', channelID)
log.debug('Already subscribed to', channelID)
}
socket.send(createOkResponse({ type: SUB, channelID }))
},
Expand Down
Loading
Loading