make kestrel a tak server, so that it can send and receive pois as cots data
Some checks failed
ci/woodpecker/pr/pr Pipeline failed
Some checks failed
ci/woodpecker/pr/pr Pipeline failed
This commit is contained in:
84
server/utils/logger.js
Normal file
84
server/utils/logger.js
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Structured logger with request context support.
|
||||
* Uses AsyncLocalStorage to provide request-scoped context that's automatically isolated per async context.
|
||||
*/
|
||||
|
||||
import { AsyncLocalStorage } from 'node:async_hooks'
|
||||
|
||||
const asyncLocalStorage = new AsyncLocalStorage()
|
||||
|
||||
/**
|
||||
* Run a function with logger context. Context is automatically isolated per async execution.
|
||||
* @param {string} reqId - Request ID
|
||||
* @param {string|null} uId - User ID (optional)
|
||||
* @param {Function} fn - Function to run with context
|
||||
* @returns {Promise<any>} Result of the function
|
||||
*/
|
||||
export function runWithContext(reqId, uId, fn) {
|
||||
return asyncLocalStorage.run({ requestId: reqId, userId: uId }, fn)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set context for the current async context. Use runWithContext() instead for proper isolation.
|
||||
* @deprecated Use runWithContext() instead for proper async context isolation
|
||||
* @param {string} reqId - Request ID
|
||||
* @param {string|null} uId - User ID (optional)
|
||||
*/
|
||||
export function setContext(reqId, uId = null) {
|
||||
const store = asyncLocalStorage.getStore()
|
||||
if (store) {
|
||||
store.requestId = reqId
|
||||
store.userId = uId
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear context for the current async context.
|
||||
* @deprecated Context is automatically cleared when async context ends. Use runWithContext() instead.
|
||||
*/
|
||||
export function clearContext() {
|
||||
const store = asyncLocalStorage.getStore()
|
||||
if (store) {
|
||||
store.requestId = null
|
||||
store.userId = null
|
||||
}
|
||||
}
|
||||
|
||||
function getContext() {
|
||||
return asyncLocalStorage.getStore() || { requestId: null, userId: null }
|
||||
}
|
||||
|
||||
function formatMessage(level, message, context = {}) {
|
||||
const { requestId, userId } = getContext()
|
||||
const timestamp = new Date().toISOString()
|
||||
const ctx = {
|
||||
timestamp,
|
||||
level,
|
||||
requestId,
|
||||
...(userId && { userId }),
|
||||
...context,
|
||||
}
|
||||
return `[${level.toUpperCase()}] ${JSON.stringify({ message, ...ctx })}`
|
||||
}
|
||||
|
||||
export function info(message, context = {}) {
|
||||
console.log(formatMessage('info', message, context))
|
||||
}
|
||||
|
||||
export function error(message, context = {}) {
|
||||
const ctx = { ...context }
|
||||
if (context.error && context.error.stack) {
|
||||
ctx.stack = context.error.stack
|
||||
}
|
||||
console.error(formatMessage('error', message, ctx))
|
||||
}
|
||||
|
||||
export function warn(message, context = {}) {
|
||||
console.warn(formatMessage('warn', message, context))
|
||||
}
|
||||
|
||||
export function debug(message, context = {}) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.debug(formatMessage('debug', message, context))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user