Repository URL to install this package:
|
Version:
0.0.7 ▾
|
import { EMPTY_OBJ, isObj } from 'exotic'
import { TRACING_HEADERS } from './toTracing'
import { LoggingMetaType, LoggingMetaTracingType, LoggingMetaMetaType } from './typings'
import { Timer } from './Timer'
// import { fetchDynamic } from './fetch'
// here just because this is for dev only...
// @todo if tracing is disabled, export nothing...
// @todo ^ same for timer
export const TRACE_URL = process.env.TRACE_URL || 'http://localhost:7777/trace'
export const SHOULD_CALL_TRACING_ENDPOINT = process.env.SHOULD_CALL_TRACING_ENDPOINT || 'true'
export type TracingHeadersType = Record<string, string | number | boolean>
/**
* @todo use `raf` and batch requests
*/
export interface TraceArgsType {
appName: string
spanName?: string
url: string
// | number | boolean
headers: TracingHeadersType
timer: Timer
tracing?: LoggingMetaTracingType
meta?: LoggingMetaType
}
// x-session-id => sessionId
export function fromHeadersToTracing(headers: TracingHeadersType) {
return {
// ...headers,
openTraceId: headers[TRACING_HEADERS.openTraceId] as string,
openTraceSpanId: headers[TRACING_HEADERS.openTraceSpanId] as number,
requestId: headers[TRACING_HEADERS.requestId] as string,
sessionId: headers[TRACING_HEADERS.sessionId] as string,
}
}
// here, we are using meta > req
export function ensureTracingHeaders(headers: LoggingMetaTracingType, tracing: LoggingMetaTracingType) {
return {
openTraceId: tracing.openTraceId || headers.openTraceId,
openTraceSpanId: tracing.openTraceSpanId || headers.openTraceSpanId,
sessionId: tracing.sessionId || headers.sessionId,
requestId: tracing.requestId || headers.requestId,
}
}
export const DEFAULT_EMPTY_META = Object.freeze({
tracing: {},
})
function toOptions(options: TraceArgsType = EMPTY_OBJ as any): TraceArgsType {
const { tracing, meta, ...remainingProps } = options
// @@perf @todo
const metaOrMergedMeta = meta || { tracing: tracing || EMPTY_OBJ, meta: EMPTY_OBJ } as LoggingMetaType
return { ...remainingProps, meta: metaOrMergedMeta, tracing: tracing || metaOrMergedMeta.tracing }
}
export function trace(options: TraceArgsType) {
if (SHOULD_CALL_TRACING_ENDPOINT === 'false') {
console.trace('[tracing] not calling tracing endpoint due to env')
return undefined
}
const coerced = toOptions(options)
const { url, headers, timer, appName, spanName, tracing, meta } = coerced
// console.log('___trace___', coerced)
if (isObj(timer.endWallTime) === false) {
timer.end()
}
const tracingUnsafe = fromHeadersToTracing(headers)
const tracingFinal = ensureTracingHeaders(tracingUnsafe, tracing)
const sizing = meta.meta
const body: LoggingMetaType = {
meta: {
bytesReceived: sizing.bytesReceived,
bytesSent: sizing.bytesSent,
spanName,
appName,
url,
},
tracing: tracingFinal,
cache: {
isCached: false,
},
timing: timer.toJSON(),
}
// console.debug(`[tracing] trace: ${url}`)
return fetch(TRACE_URL, {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
redirect: 'follow',
referrer: 'no-referrer',
body: JSON.stringify(body),
})
.catch(rejectionException => {
console.error('[tracing] likely the tracing endpoint is not up')
})
.finally(() => {
console.debug(`traced ${url}`)
// console.log(body)
})
}