service-core/core/log.mjs

147 lines
3.3 KiB
JavaScript

// import nodewindows from 'node-windows'
import cluster from 'cluster'
import bunyan from 'bunyan-lite'
import { setTimeout } from 'timers/promises'
export function getDefaultStreams() {
if (process.env.NODE_ENV === 'production') {
return [{
path: 'log.log',
level: 'info',
}
]
} else {
return [{
"stream": process.stdout,
"level": "debug"
}
]
}
}
export default function getLog(name, streams = null, opts = {}) {
let settings
let ringbuffer = new bunyan.RingBuffer({ limit: 100 })
let ringbufferwarn = new bunyan.RingBuffer({ limit: 100 })
if (streams) {
streams.forEach(function(stream) {
if (stream.stream === 'process.stdout') {
stream.stream = process.stdout
}
})
}
settings = {
name: name,
streams: streams || getDefaultStreams()
}
let logger
settings.streams.push({
stream: ringbuffer,
type: 'raw',
level: 'info',
})
settings.streams.push({
stream: ringbufferwarn,
type: 'raw',
level: 'warn',
})
settings.streams.push({
stream: {
write: function(record) {
logger.emit('newlog', record)
if (cluster.isWorker) {
process.send({
apptarget: opts.name || name,
type: 'newlog',
payload: record,
})
}
},
end: function() {},
destroy: function() {},
destroySoon: function() {},
},
type: 'raw',
level: 'info',
})
let eventManager = null
let eventManagerLoading = false
async function safeLoadEvent(level, message, code) {
if (eventManager === false) {
return Promise.resolve()
}
if (!eventManager) {
if (eventManagerLoading) {
for (let i = 0; i < 10 && eventManagerLoading; i++) {
await setTimeout(50)
}
if (eventManagerLoading) {
eventManager = false
}
return safeLoadEvent(level, message, code)
}
eventManagerLoading = true
let prom
if (opts.import) {
prom = opts.import('node-windows')
} else {
prom = import('node-windows')
}
await prom.then(
function(res) { eventManager = new res.default.EventLogger(name) },
function() { eventManager = false },
)
eventManagerLoading = false
return safeLoadEvent(level, message, code)
}
return new Promise(function(res) {
try {
eventManager[level](message, code, function() { res() })
} catch {
res()
}
})
}
// Create our logger.
logger = bunyan.createLogger(settings)
if (process.env.NODE_ENV === 'production') {
logger.event = {
info: safeLoadEvent.bind(this, 'info'),
warn: safeLoadEvent.bind(this, 'warn'),
error: safeLoadEvent.bind(this, 'error'),
}
} else {
logger.event = {
info: function() { return Promise.resolve() },
warn: function() { return Promise.resolve() },
error: function() { return Promise.resolve() },
}
}
logger.on('error', function(err) {
if (process.env.NODE_ENV === 'production') {
logger.event.warn(`Error in logger ${name}: ${err.message}`)
} else {
console.log(`Error in logger ${name}: ${err.message}`)
}
})
logger.ringbuffer = ringbuffer
logger.ringbufferwarn = ringbufferwarn
return logger
}