標記全鏈路日誌有助於更好的解決 bug 和分析接口性能,本篇文章使用 node
來做爲示例javascript
使用 requestId
惟一標識每一個請求,有時它又被稱爲 sessionId
或者 transactionId
。java
requestId
標記每次請求全鏈路日誌,所要標記的日誌種類如上所示X-Request-Id
(X-Session-Id) 標記在請求頭中,在整個鏈路進行傳遞async function context (ctx: KoaContext, next: any) {
const requestId = ctx.header['x-request-id'] || uuid()
ctx.res.setHeader('requestId', requestId)
ctx.requestId = requestId
await next()
}
app.use('/todos/:id', (ctx) => {
User.findByPk(ctx.body.id, {
logging () {
// log ctx.requestId
}
})
})
複製代碼
如上,在每次數據庫查詢時手動對 requestId
進行標記過於繁瑣。能夠統一設計 logger
函數進行標記node
具體代碼可見我一個腳手架中的 logger.tsgit
這裏使用了流行的日誌庫 winston (13582 Star)github
import winston, { format } from 'winston'
const requestId = format((info) => {
info.requestId = session.get('requestId')
return info
})
const logger = winston.createLogger({
format: format.combine(
format.timestamp(),
requestId(),
format.json()
)
})
複製代碼
或者說如何在 logger.ts
如何得到整個請求響應生命週期中的 requestId
redis
具體代碼可見 session.tssql
import { createNamespace } from 'cls-hooked'
const session = createNamespace('hello, world')
export { session }
複製代碼
sentry
(警報系統) 中收到一條異常警報時,經過 requestId
能夠在 elk
(日誌系統) 中獲取到關於該異常的全部關鍵日誌 (sql, redis, 關鍵函數的輸入輸出)requestId
能夠在 elk
中分析該請求的全部數據庫查詢時間,請求響應時間,緩存是否命中等指標另外能夠經過 zipkin 來追蹤全鏈路耗時。typescript
歡迎關注個人公衆號山月行,在這裏記錄着個人技術成長,歡迎交流數據庫