azify-logger 1.0.44 → 1.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +84 -7
- package/init.js +21 -11
- package/middleware-express.js +46 -44
- package/middleware-pino.js +19 -10
- package/package.json +3 -1
- package/preload.js +15 -0
- package/register-http-client-early.js +816 -0
- package/register.js +1219 -366
- package/sampling.js +1 -1
- package/server.js +77 -10
- package/store.js +37 -11
- package/streams/httpQueue.js +24 -12
- package/streams/pino.js +45 -10
package/sampling.js
CHANGED
|
@@ -45,7 +45,7 @@ const sourceSampleRates = {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
const shouldSample = (level, source) => {
|
|
48
|
-
if (source === 'http-client') {
|
|
48
|
+
if (source === 'http-client' || source === 'pino-stdout') {
|
|
49
49
|
return true
|
|
50
50
|
}
|
|
51
51
|
const key = typeof level === 'string' ? level.toLowerCase() : 'info'
|
package/server.js
CHANGED
|
@@ -227,6 +227,7 @@ async function ensureIndexTemplate() {
|
|
|
227
227
|
userAgent: { type: 'text' },
|
|
228
228
|
environment: { type: 'keyword' },
|
|
229
229
|
hostname: { type: 'keyword' },
|
|
230
|
+
source: { type: 'keyword' },
|
|
230
231
|
responseBody: { type: 'text' },
|
|
231
232
|
error: {
|
|
232
233
|
properties: {
|
|
@@ -238,7 +239,7 @@ async function ensureIndexTemplate() {
|
|
|
238
239
|
}
|
|
239
240
|
}
|
|
240
241
|
},
|
|
241
|
-
priority:
|
|
242
|
+
priority: 1000
|
|
242
243
|
})
|
|
243
244
|
} catch (error) {
|
|
244
245
|
}
|
|
@@ -1836,21 +1837,55 @@ async function handleLog(req, res) {
|
|
|
1836
1837
|
))
|
|
1837
1838
|
)
|
|
1838
1839
|
|
|
1839
|
-
|
|
1840
|
+
const isRequestOrResponse = messageLower.includes('[request]') || messageLower.includes('[response]')
|
|
1841
|
+
const isAzifyHttpClientLog = (meta && meta.source === 'http-client') || isRequestOrResponse
|
|
1842
|
+
if (!isAzifyHttpClientLog && shouldFilterLog) {
|
|
1840
1843
|
return res.json({ success: true, message: 'Log filtrado' })
|
|
1841
1844
|
}
|
|
1845
|
+
if (isRequestOrResponse && process.env.AZIFY_LOGGER_DEBUG === '1') {
|
|
1846
|
+
console.log('[azify-logger][server] REQUEST/RESPONSE received:', (typeof message === 'string' ? message : '').slice(0, 80))
|
|
1847
|
+
}
|
|
1848
|
+
if (isRequestOrResponse && meta && typeof meta === 'object' && meta.source !== 'http-client') {
|
|
1849
|
+
meta = { ...meta, source: 'http-client' }
|
|
1850
|
+
}
|
|
1842
1851
|
|
|
1843
1852
|
const requestId = meta && meta.requestId
|
|
1844
1853
|
|
|
1854
|
+
function toTraceIdHex32(val) {
|
|
1855
|
+
if (val == null || typeof val !== 'string') return null
|
|
1856
|
+
const hex = String(val).replace(/[^0-9a-fA-F]/g, '').slice(0, 32)
|
|
1857
|
+
return hex ? hex.padStart(32, '0').slice(0, 32) : null
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1845
1860
|
let traceContext = null
|
|
1846
1861
|
|
|
1847
1862
|
if (meta && meta.traceId && meta.spanId) {
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1863
|
+
const tid = toTraceIdHex32(meta.traceId)
|
|
1864
|
+
if (tid) {
|
|
1865
|
+
traceContext = {
|
|
1866
|
+
traceId: tid,
|
|
1867
|
+
spanId: String(meta.spanId).slice(0, 16),
|
|
1868
|
+
parentSpanId: meta.parentSpanId != null && meta.parentSpanId !== '' ? String(meta.parentSpanId) : null
|
|
1869
|
+
}
|
|
1852
1870
|
}
|
|
1853
|
-
}
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
if (!traceContext && typeof message === 'string' && /traceId/i.test(message)) {
|
|
1874
|
+
const m = message.match(/"traceId"\s*:\s*"([^"]+)"/)
|
|
1875
|
+
const s = message.match(/"spanId"\s*:\s*"([^"]+)"/)
|
|
1876
|
+
if (m && m[1]) {
|
|
1877
|
+
const tid = toTraceIdHex32(m[1])
|
|
1878
|
+
if (tid) {
|
|
1879
|
+
traceContext = {
|
|
1880
|
+
traceId: tid,
|
|
1881
|
+
spanId: (s && s[1]) ? String(s[1]).slice(0, 16) : generateSpanId(),
|
|
1882
|
+
parentSpanId: null
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
if (!traceContext) {
|
|
1854
1889
|
try {
|
|
1855
1890
|
const extractedCtx = propagation.extract(context.active(), req.headers, {
|
|
1856
1891
|
get (carrier, key) {
|
|
@@ -1867,8 +1902,8 @@ async function handleLog(req, res) {
|
|
|
1867
1902
|
const spanContext = (span && span.spanContext && span.spanContext()) || null
|
|
1868
1903
|
if (spanContext && spanContext.traceId && spanContext.spanId) {
|
|
1869
1904
|
traceContext = {
|
|
1870
|
-
traceId: spanContext.traceId,
|
|
1871
|
-
spanId: spanContext.spanId,
|
|
1905
|
+
traceId: toTraceIdHex32(spanContext.traceId) || String(spanContext.traceId).replace(/-/g, '').padStart(32, '0').slice(0, 32),
|
|
1906
|
+
spanId: String(spanContext.spanId).slice(0, 16),
|
|
1872
1907
|
parentSpanId: null
|
|
1873
1908
|
}
|
|
1874
1909
|
}
|
|
@@ -1991,6 +2026,16 @@ async function handleLog(req, res) {
|
|
|
1991
2026
|
value = truncateBody(value, false)
|
|
1992
2027
|
}
|
|
1993
2028
|
logEntry[key] = value
|
|
2029
|
+
} else if (key === 'error') {
|
|
2030
|
+
if (value != null && typeof value === 'object' && !Array.isArray(value) && (value.message != null || value.stack != null || value.name != null)) {
|
|
2031
|
+
logEntry.error = {
|
|
2032
|
+
message: value.message != null ? String(value.message) : '',
|
|
2033
|
+
stack: value.stack != null ? String(value.stack) : undefined,
|
|
2034
|
+
name: value.name != null ? String(value.name) : undefined
|
|
2035
|
+
}
|
|
2036
|
+
} else if (value != null) {
|
|
2037
|
+
logEntry.error = { message: String(value) }
|
|
2038
|
+
}
|
|
1994
2039
|
} else {
|
|
1995
2040
|
logEntry[key] = value
|
|
1996
2041
|
}
|
|
@@ -1999,6 +2044,7 @@ async function handleLog(req, res) {
|
|
|
1999
2044
|
}
|
|
2000
2045
|
|
|
2001
2046
|
logEntry.message = message
|
|
2047
|
+
if (isRequestOrResponse) logEntry.source = 'http-client'
|
|
2002
2048
|
|
|
2003
2049
|
const osUrl = process.env.OPENSEARCH_URL || 'http://localhost:9200'
|
|
2004
2050
|
const appName = logEntry.appName || logEntry.service?.name || 'unknown'
|
|
@@ -2029,8 +2075,17 @@ const _logDedupeBucketMs = 80
|
|
|
2029
2075
|
|
|
2030
2076
|
function _logDedupeKey(serviceName, logEntry) {
|
|
2031
2077
|
const msg = typeof logEntry.message === 'string' ? logEntry.message.substring(0, 500) : String(logEntry.message || '')
|
|
2078
|
+
const msgLower = msg.toLowerCase()
|
|
2079
|
+
const isReqRes = msgLower.includes('[request]') || msgLower.includes('[response]')
|
|
2032
2080
|
const traceId = logEntry.traceId != null ? String(logEntry.traceId).trim() : ''
|
|
2033
2081
|
const spanId = logEntry.spanId != null ? String(logEntry.spanId).trim() : ''
|
|
2082
|
+
if (isReqRes) {
|
|
2083
|
+
const kind = msgLower.includes('[request]') ? 'REQUEST' : 'RESPONSE'
|
|
2084
|
+
if (traceId && spanId) return `r|${serviceName}|${traceId}|${spanId}|${kind}`
|
|
2085
|
+
const ts = logEntry['@timestamp'] != null ? Number(logEntry['@timestamp']) : Date.now()
|
|
2086
|
+
const bucket = Math.floor(ts / _logDedupeBucketMs) * _logDedupeBucketMs
|
|
2087
|
+
return `r|${serviceName}|${bucket}|${kind}`
|
|
2088
|
+
}
|
|
2034
2089
|
if (traceId && spanId) return `t|${serviceName}|${traceId}|${spanId}|${msg}`
|
|
2035
2090
|
const requestId = (logEntry.requestId != null ? String(logEntry.requestId).trim() : '') || ''
|
|
2036
2091
|
if (!requestId) return null
|
|
@@ -2059,6 +2114,12 @@ function _enqueueOpenSearchWrite(osUrl, indexName, logEntry, serviceName) {
|
|
|
2059
2114
|
if (expiry != null && expiry > now) return
|
|
2060
2115
|
_logDedupeSeen.set(key, now + _logDedupeWindowMs)
|
|
2061
2116
|
}
|
|
2117
|
+
if (process.env.AZIFY_LOGGER_DEBUG === '1') {
|
|
2118
|
+
const msg = typeof logEntry.message === 'string' ? logEntry.message : ''
|
|
2119
|
+
if (msg.toLowerCase().includes('[request]') || msg.toLowerCase().includes('[response]')) {
|
|
2120
|
+
console.log('[azify-logger][server] REQUEST/RESPONSE enqueued for OpenSearch:', msg.slice(0, 70))
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2062
2123
|
_openSearchWriteQueue.push({ osUrl, indexName, logEntry, serviceName })
|
|
2063
2124
|
_drainOpenSearchQueue()
|
|
2064
2125
|
}
|
|
@@ -2081,11 +2142,17 @@ function _drainOpenSearchQueue() {
|
|
|
2081
2142
|
})
|
|
2082
2143
|
.then(() => {
|
|
2083
2144
|
_openSearchFailuresInRow = 0
|
|
2145
|
+
if (process.env.AZIFY_LOGGER_DEBUG === '1') {
|
|
2146
|
+
const msg = typeof job.logEntry.message === 'string' ? job.logEntry.message : ''
|
|
2147
|
+
if (msg.toLowerCase().includes('[request]') || msg.toLowerCase().includes('[response]')) {
|
|
2148
|
+
console.log('[azify-logger][server] REQUEST/RESPONSE written to OpenSearch index=', job.indexName, 'msg=', msg.slice(0, 60))
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2084
2151
|
const SETUP_THROTTLE_MS = 10 * 60 * 1000
|
|
2085
2152
|
if (!handleLog._lastSetupTime) handleLog._lastSetupTime = new Map()
|
|
2086
2153
|
const last = handleLog._lastSetupTime.get(job.serviceName) || 0
|
|
2087
2154
|
const now = Date.now()
|
|
2088
|
-
const shouldRunSetup = job.serviceName !== 'unknown' && job.serviceName !== 'unknown-service' && (now - last >= SETUP_THROTTLE_MS)
|
|
2155
|
+
const shouldRunSetup = job.serviceName !== 'unknown' && job.serviceName !== 'unknown-service' && job.serviceName !== 'unknown-app' && (now - last >= SETUP_THROTTLE_MS)
|
|
2089
2156
|
if (shouldRunSetup) {
|
|
2090
2157
|
handleLog._lastSetupTime.set(job.serviceName, now)
|
|
2091
2158
|
setupGrafanaForApp(job.serviceName).then(() => {
|
package/store.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
const { AsyncLocalStorage } = require('async_hooks')
|
|
2
2
|
|
|
3
3
|
const als = new AsyncLocalStorage()
|
|
4
|
+
let lastJobContext = null
|
|
5
|
+
|
|
6
|
+
function setLastJobContext(ctx) {
|
|
7
|
+
lastJobContext = ctx || null
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function getLastJobContext() {
|
|
11
|
+
return lastJobContext
|
|
12
|
+
}
|
|
4
13
|
|
|
5
14
|
function fastGenerateId(length = 16) {
|
|
6
15
|
const chars = '0123456789abcdef'
|
|
@@ -12,21 +21,22 @@ function fastGenerateId(length = 16) {
|
|
|
12
21
|
return result
|
|
13
22
|
}
|
|
14
23
|
|
|
15
|
-
function
|
|
16
|
-
const
|
|
17
|
-
|
|
24
|
+
function toTraceIdHex(hex32) {
|
|
25
|
+
const raw = hex32 != null && typeof hex32 === 'string' ? String(hex32).replace(/[^0-9a-fA-F]/g, '').slice(0, 32) : ''
|
|
26
|
+
const hex = raw || fastGenerateId(16)
|
|
27
|
+
return hex.padStart(32, '0').slice(0, 32)
|
|
18
28
|
}
|
|
19
29
|
|
|
20
|
-
function startRequestContext(initial
|
|
30
|
+
function startRequestContext(initial) {
|
|
31
|
+
if (!initial || typeof initial !== 'object') initial = {}
|
|
21
32
|
const traceHex = initial.traceHex || fastGenerateId(16)
|
|
22
33
|
const spanHex = initial.spanHex || fastGenerateId(8)
|
|
23
|
-
|
|
24
|
-
traceId:
|
|
25
|
-
spanId: spanHex,
|
|
26
|
-
parentSpanId: initial.parentSpanId
|
|
27
|
-
requestId: initial.requestId
|
|
34
|
+
return {
|
|
35
|
+
traceId: toTraceIdHex(traceHex),
|
|
36
|
+
spanId: spanHex != null && spanHex !== '' ? String(spanHex).slice(0, 16) : fastGenerateId(8),
|
|
37
|
+
parentSpanId: initial.parentSpanId != null && initial.parentSpanId !== '' ? String(initial.parentSpanId) : null,
|
|
38
|
+
requestId: initial.requestId != null && initial.requestId !== '' ? String(initial.requestId) : null
|
|
28
39
|
}
|
|
29
|
-
return ctx
|
|
30
40
|
}
|
|
31
41
|
|
|
32
42
|
function runWithRequestContext(ctx, fn) {
|
|
@@ -37,11 +47,27 @@ function getRequestContext() {
|
|
|
37
47
|
return als.getStore() || null
|
|
38
48
|
}
|
|
39
49
|
|
|
50
|
+
function mergeTraceIntoJobPayload(data, traceContext) {
|
|
51
|
+
if (!traceContext || !traceContext.traceId) return data
|
|
52
|
+
const base = data && typeof data === 'object' && !Array.isArray(data) ? data : {}
|
|
53
|
+
return {
|
|
54
|
+
...base,
|
|
55
|
+
traceId: traceContext.traceId,
|
|
56
|
+
spanId: traceContext.spanId ?? null,
|
|
57
|
+
parentSpanId: traceContext.parentSpanId ?? null,
|
|
58
|
+
requestId: traceContext.requestId ?? null
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
40
62
|
module.exports = {
|
|
41
63
|
als,
|
|
42
64
|
startRequestContext,
|
|
43
65
|
runWithRequestContext,
|
|
44
|
-
getRequestContext
|
|
66
|
+
getRequestContext,
|
|
67
|
+
getLastJobContext,
|
|
68
|
+
setLastJobContext,
|
|
69
|
+
mergeTraceIntoJobPayload,
|
|
70
|
+
toTraceIdHex
|
|
45
71
|
}
|
|
46
72
|
|
|
47
73
|
|
package/streams/httpQueue.js
CHANGED
|
@@ -84,7 +84,7 @@ function resolveRedisConfig (overrides = {}) {
|
|
|
84
84
|
(overrides.redis && overrides.redis.url) ||
|
|
85
85
|
process.env.AZIFY_LOGGER_REDIS_URL ||
|
|
86
86
|
DEFAULT_REDIS_URL
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
if (!redisUrl) {
|
|
89
89
|
return null
|
|
90
90
|
}
|
|
@@ -108,11 +108,13 @@ function createHttpLoggerTransport (loggerUrl, overrides) {
|
|
|
108
108
|
if (!loggerUrl) {
|
|
109
109
|
return noopTransport
|
|
110
110
|
}
|
|
111
|
+
overrides = overrides || {}
|
|
111
112
|
|
|
112
113
|
const options = resolveOptions(overrides)
|
|
113
114
|
const redisConfig = resolveRedisConfig(overrides)
|
|
115
|
+
const hasRedisPassword = redisConfig && redisConfig.password != null && String(redisConfig.password).trim() !== ''
|
|
114
116
|
|
|
115
|
-
if (redisConfig) {
|
|
117
|
+
if (redisConfig && hasRedisPassword) {
|
|
116
118
|
try {
|
|
117
119
|
return createRedisStreamTransport(loggerUrl, options, redisConfig)
|
|
118
120
|
} catch (err) {
|
|
@@ -124,9 +126,7 @@ function createHttpLoggerTransport (loggerUrl, overrides) {
|
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
const redisUrl = overrides.redisUrl || (overrides.redis && overrides.redis.url) || process.env.AZIFY_LOGGER_REDIS_URL || DEFAULT_REDIS_URL
|
|
127
|
-
|
|
128
|
-
const pass = password != null && String(password).trim() !== '' ? String(password).trim() : undefined
|
|
129
|
-
if (redisUrl && !pass) {
|
|
129
|
+
if (redisUrl && !hasRedisPassword) {
|
|
130
130
|
if (typeof global.__azifyLoggerRedisPasswordWarned === 'undefined') {
|
|
131
131
|
global.__azifyLoggerRedisPasswordWarned = true
|
|
132
132
|
process.stderr.write('[azify-logger] ⚠️ Redis requires a password. No password set. Using direct HTTP (no Redis). Set AZIFY_LOGGER_REDIS_PASSWORD to use Redis.\n')
|
|
@@ -250,7 +250,7 @@ function buildInlineTransport (loggerUrl, options) {
|
|
|
250
250
|
|
|
251
251
|
flushTimer = setTimeout(() => {
|
|
252
252
|
flushTimer = null
|
|
253
|
-
|
|
253
|
+
flushQueue().catch(() => {})
|
|
254
254
|
}, delay)
|
|
255
255
|
|
|
256
256
|
if (typeof flushTimer.unref === 'function') {
|
|
@@ -278,9 +278,15 @@ function buildInlineTransport (loggerUrl, options) {
|
|
|
278
278
|
try {
|
|
279
279
|
for (let i = 0; i < batch.length; i += 1) {
|
|
280
280
|
const { payload, headers } = batch[i]
|
|
281
|
+
let body
|
|
282
|
+
try {
|
|
283
|
+
body = typeof payload === 'string' ? payload : JSON.stringify(payload)
|
|
284
|
+
} catch (_) {
|
|
285
|
+
continue
|
|
286
|
+
}
|
|
281
287
|
try {
|
|
282
|
-
await axios.post(loggerUrl,
|
|
283
|
-
headers,
|
|
288
|
+
await axios.post(loggerUrl, body, {
|
|
289
|
+
headers: { ...headers, 'Content-Type': 'application/json' },
|
|
284
290
|
timeout: options.timeout,
|
|
285
291
|
httpAgent,
|
|
286
292
|
httpsAgent,
|
|
@@ -298,11 +304,9 @@ function buildInlineTransport (loggerUrl, options) {
|
|
|
298
304
|
if (remaining.length) {
|
|
299
305
|
queue.unshift(...remaining)
|
|
300
306
|
}
|
|
301
|
-
|
|
302
|
-
throw error
|
|
303
307
|
}
|
|
304
308
|
}
|
|
305
|
-
} catch (
|
|
309
|
+
} catch (e) {
|
|
306
310
|
} finally {
|
|
307
311
|
flushing = false
|
|
308
312
|
if (queue.length) {
|
|
@@ -311,6 +315,12 @@ function buildInlineTransport (loggerUrl, options) {
|
|
|
311
315
|
}
|
|
312
316
|
}
|
|
313
317
|
|
|
318
|
+
const isRequestOrResponsePayload = (p) => {
|
|
319
|
+
if (!p || typeof p !== 'object') return false
|
|
320
|
+
const msg = typeof p.message === 'string' ? p.message : ''
|
|
321
|
+
return msg.includes('[REQUEST]') || msg.includes('[RESPONSE]')
|
|
322
|
+
}
|
|
323
|
+
|
|
314
324
|
const enqueue = (payload, headers = {}) => {
|
|
315
325
|
if (queue.length >= options.maxQueueSize) {
|
|
316
326
|
queue.shift()
|
|
@@ -319,7 +329,9 @@ function buildInlineTransport (loggerUrl, options) {
|
|
|
319
329
|
queue.push({ payload, headers })
|
|
320
330
|
|
|
321
331
|
if (queue.length >= options.batchSize) {
|
|
322
|
-
|
|
332
|
+
flushQueue().catch(() => {})
|
|
333
|
+
} else if (isRequestOrResponsePayload(payload)) {
|
|
334
|
+
scheduleFlush(0)
|
|
323
335
|
} else {
|
|
324
336
|
scheduleFlush()
|
|
325
337
|
}
|
package/streams/pino.js
CHANGED
|
@@ -36,26 +36,49 @@ function createPinoStream(options = {}) {
|
|
|
36
36
|
|
|
37
37
|
let traceId, spanId, parentSpanId
|
|
38
38
|
try {
|
|
39
|
-
const { getRequestContext } = require('../store')
|
|
39
|
+
const { getRequestContext, getLastJobContext, toTraceIdHex } = require('../store')
|
|
40
40
|
const ctx = getRequestContext()
|
|
41
41
|
if (ctx && ctx.traceId) {
|
|
42
42
|
traceId = ctx.traceId
|
|
43
43
|
spanId = ctx.spanId
|
|
44
44
|
parentSpanId = ctx.parentSpanId
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
if (!traceId
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
|
|
47
|
+
if (!traceId) {
|
|
48
|
+
const jobCtx = getLastJobContext()
|
|
49
|
+
if (jobCtx && jobCtx.traceId) {
|
|
50
|
+
traceId = jobCtx.traceId
|
|
51
|
+
spanId = jobCtx.spanId
|
|
52
|
+
parentSpanId = jobCtx.parentSpanId
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!traceId && (record.traceId || (record.data && record.data.traceId))) {
|
|
57
|
+
traceId = record.traceId || (record.data && record.data.traceId)
|
|
58
|
+
spanId = record.spanId != null ? record.spanId : (record.data && record.data.spanId)
|
|
59
|
+
parentSpanId = record.parentSpanId != null ? record.parentSpanId : (record.data && record.data.parentSpanId)
|
|
51
60
|
}
|
|
52
|
-
|
|
61
|
+
|
|
53
62
|
if (!traceId && record.req && record.req.traceId) {
|
|
54
63
|
traceId = record.req.traceId
|
|
55
64
|
spanId = record.req.spanId
|
|
56
65
|
parentSpanId = record.req.parentSpanId
|
|
57
66
|
}
|
|
58
|
-
|
|
67
|
+
|
|
68
|
+
if (!traceId) {
|
|
69
|
+
const msgStr = record.msg || record.message || ''
|
|
70
|
+
if (typeof msgStr === 'string' && /traceId/i.test(msgStr)) {
|
|
71
|
+
const m = msgStr.match(/"traceId"\s*:\s*"([^"]+)"/)
|
|
72
|
+
if (m) {
|
|
73
|
+
traceId = m[1]
|
|
74
|
+
const s = msgStr.match(/"spanId"\s*:\s*"([^"]+)"/)
|
|
75
|
+
spanId = s ? s[1] : null
|
|
76
|
+
const p = msgStr.match(/"parentSpanId"\s*:\s*"([^"]*)"/)
|
|
77
|
+
parentSpanId = (p && p[1]) ? p[1] : null
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
59
82
|
if (!traceId) {
|
|
60
83
|
const span = trace.getSpan(context.active())
|
|
61
84
|
const spanContext = span && span.spanContext()
|
|
@@ -65,6 +88,11 @@ function createPinoStream(options = {}) {
|
|
|
65
88
|
parentSpanId = spanContext.parentSpanId
|
|
66
89
|
}
|
|
67
90
|
}
|
|
91
|
+
|
|
92
|
+
if (traceId && typeof traceId === 'string') {
|
|
93
|
+
traceId = toTraceIdHex(traceId)
|
|
94
|
+
if (spanId != null) spanId = String(spanId).slice(0, 16)
|
|
95
|
+
}
|
|
68
96
|
} catch (_) {}
|
|
69
97
|
|
|
70
98
|
const headers = {}
|
|
@@ -90,12 +118,19 @@ function createPinoStream(options = {}) {
|
|
|
90
118
|
...(parentSpanId && { parentSpanId })
|
|
91
119
|
}
|
|
92
120
|
|
|
93
|
-
|
|
121
|
+
const isErrorOrWarn = level === 'error' || level === 'fatal' || level === 'warn'
|
|
122
|
+
if (!isErrorOrWarn && !shouldSample(level, 'logger')) {
|
|
94
123
|
return
|
|
95
124
|
}
|
|
96
125
|
|
|
97
126
|
const payload = { level, message: record.msg || record.message || 'log', meta }
|
|
98
|
-
|
|
127
|
+
try {
|
|
128
|
+
transport.enqueue(payload, headers)
|
|
129
|
+
} catch (err) {
|
|
130
|
+
if (process.env.AZIFY_LOGGER_DEBUG === '1') {
|
|
131
|
+
process.stderr.write(`[azify-logger] pino stream enqueue error: ${err && err.message}\n`)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
99
134
|
}
|
|
100
135
|
}
|
|
101
136
|
}
|