console.log()에서 컨텍스트를 유지하는 간단한 방법
This post explains a simple way to enhance the use of console.log() in a nodejs http server, with an example for SvelteKit. Of course one may use dedicated logger tools too.
Nodejs http/tcp 서버는 여러 요청을 동시에 처리합니다. 로깅과 관련하여 현재 요청의 식별자(requestId, userId 또는 요청과 관련된 모든 데이터)를 각 로그 메시지 앞에 추가하는 것이 유용합니다.
이 정보의 이름을 지정하겠습니다
contextualData
.명확하고 쉬운 방법은 컨텍스트 데이터를 함수에서 함수로 전달하여 코드의 모든 파일에서
console.log(contextualData, xxx)
를 호출할 수 있도록 하는 것입니다.처음에는 간단하고 쉬웠지만 앱이 성장함에 따라 덜 단순하고 거대한 코드베이스로 끔찍합니다.
다른 방법이 있습니까?
실제로 AsyncLocalStorage은 요청 컨텍스트에 있는 스토리지(브라우저의 localStorage와 유사)를 정확하게 제공하는 상대적으로 새롭고 알려지지 않은 Nodejs API입니다.
1단계: AsyncLocalStorage 사용
이 API를 사용하는 것은 매우 간단합니다. 내 의견을 포함하여 정확히 동일한 문서 예제를 살펴보겠습니다.
import http from 'node:http';
// import AsyncLocalStorage API
import { AsyncLocalStorage } from 'node:async_hooks';
// new instance
const asyncLocalStorage = new AsyncLocalStorage();
// this function shows how to retrieve the context
// and preprend it to console.log() messages
function logWithId(msg) {
const id = asyncLocalStorage.getStore();
console.log(`${id !== undefined ? id : '-'}:`, msg);
}
let idSeq = 0; // the contextual data of this example
http.createServer((req, res) => {
// .run(context, callback) runs the callback and makes 'context'
// available when calling .getStore() from inside the callback
// for this example, idSeq is incremented on each request
asyncLocalStorage.run(idSeq++, () => {
// starting from here, contextualData is defined
logWithId('start');
// Imagine any chain of async operations here
setImmediate(() => {
logWithId('finish');
res.end();
});
// until here
});
}).listen(8080);
http.get('http://localhost:8080');
http.get('http://localhost:8080');
// Prints:
// 0: start
// 1: start
// 0: finish
// 1: finish
다음 단계는 console.log()를 다시 작성하여 사용 가능한 경우 컨텍스트가 있는 메시지를 자동으로 미리 추가하도록 합니다.
2단계: console.log() 재작성
정적 접두사가 있는 예를 들어 보겠습니다.
let _log = null // pointer to console.log base function
const setConsolePrefix = (prefix) => {
// singleton
if (_log)
return
// keep a pointer to the system console.log function
_log = console.log
// rewrite console.log function with prefix
console.log = () => {
let args = Array.from(arguments)
if (prefix)
// insert prefix as the first argument
args.unshift(prefix)
// call system console.log function with updated arguments
_log.apply(console, log, args)
}
// anywhere in the code
setConsolePrefix("Pulp Fiction:")
// later in the code
console.log("It's Zed's")
console.log("Who's Zed ?")
// prints :
// Pulp Fiction: It's Zed's
// Pulp Fiction: Who's Zed ?
너무 간단합니다.
물건 모으기
이제 모든 것을 모아서 이 기능을
Context.js
파일에 캡슐화해 보겠습니다.import { AsyncLocalStorage } from "async_hooks"
export const context = new AsyncLocalStorage()
var __log = null
export function setContextualConsole(){
// singleton
if (__log)
return
__log = console.log
console.log = function(){
let args = Array.from(arguments)
// retrieve a contextual prefix instead of a static prefix
const contextualPrefix = context.getStore()
if (contextualPrefix)
args.unshift(contextualPrefix )
__log.apply(console, args)
}
}
Sveltekit에서 사용
Sveltekit에서 이를 사용하는 올바른 위치는
hooks.ts
에 정의된 handle() 함수입니다. 이 예제에서 컨텍스트 데이터는 Nodejs AsyncLocalStorage 문서 예제에서와 매우 동일한 seqId입니다.import {context, setContextualConsole} from 'Context'
// our contextual data
let seqId = 0
export async function handle({ event, resolve }) {
seqId++
// use our new 'context-ready' console.log
setContextualConsole()
return await context.run(seqId, async()=>{
// starting from here, console.log(xxx) prints 'seqId xxx'
const response = await resolve(event)
// until here
return response
})
}
노드 js Http 서버에서 사용
베어 nodejs httpServer와 동일:
import http from 'node:http'
import {context, setContextualConsole} from './Context.js'
// our contextual data
let seqId = 0
http.createServer((req, res) => {
seqId++
// use our 'context-ready' console
setContextualConsole()
context.run(seqId, ()=>{
// context available from here...
console.log('start')
// the timeout simulates request processing time
// so that we get simultaneous requests for this example
setTimeout(()=>{
console.log('end')
// ... to here
res.end()
}, 10)
})
}).listen(80)
http.get('http://localhost')
http.get('http://localhost')
// prints :
// 1 start
// 2 start
// 1 end
// 2 end
그게 다야!
컨텍스트 데이터는 개체, 배열 또는 요청 처리 중에 저장해야 하는 데이터일 수 있습니다.
SvelteKit에서 내 조언은 로깅 목적으로만 이 트릭을 사용하는 것입니다. event.locals를 대체해서는 안 됩니다.
Reference
이 문제에 관하여(console.log()에서 컨텍스트를 유지하는 간단한 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/air16/a-simple-way-to-keep-context-in-consolelog-4e88텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)