dd-trace
Version:
Datadog APM tracing client for JavaScript
142 lines (115 loc) • 3.77 kB
JavaScript
const { storage } = require('../../../datadog-core')
const { LogChannel } = require('./channels')
const { Log } = require('./log')
const defaultLogger = {
debug: msg => console.debug(msg), /* eslint-disable-line no-console */
info: msg => console.info(msg), /* eslint-disable-line no-console */
warn: msg => console.warn(msg), /* eslint-disable-line no-console */
error: msg => console.error(msg) /* eslint-disable-line no-console */
}
let enabled = false
let logger = defaultLogger
let logChannel = new LogChannel()
let stackTraceLimitFunction = onError
function withNoop (fn) {
const store = storage('legacy').getStore()
storage('legacy').enterWith({ noop: true })
fn()
storage('legacy').enterWith(store)
}
function unsubscribeAll () {
logChannel.unsubscribe({ trace: onTrace, debug: onDebug, info: onInfo, warn: onWarn, error: onError })
}
function toggleSubscription (enable, level) {
unsubscribeAll()
if (enable) {
logChannel = new LogChannel(level)
logChannel.subscribe({ trace: onTrace, debug: onDebug, info: onInfo, warn: onWarn, error: onError })
}
}
function toggle (enable, level) {
enabled = enable
toggleSubscription(enabled, level)
}
function use (newLogger) {
if (typeof newLogger?.debug === 'function' && typeof newLogger.error === 'function') {
logger = newLogger
}
}
function reset () {
logger = defaultLogger
enabled = false
toggleSubscription(false)
}
function getErrorLog (err) {
if (typeof err?.delegate === 'function') {
const result = err.delegate()
return Array.isArray(result) ? Log.parse(...result) : Log.parse(result)
}
return err
}
function setStackTraceLimitFunction (fn) {
if (typeof fn !== 'function') {
throw new TypeError('stackTraceLimitFunction must be a function')
}
stackTraceLimitFunction = fn
}
function onError (err) {
const { formatted, cause } = getErrorLog(err)
// calling twice logger.error() because Error cause is only available in nodejs v16.9.0
// TODO: replace it with Error(message, { cause }) when cause has broad support
if (formatted) {
withNoop(() => {
const l = Error.stackTraceLimit
Error.stackTraceLimit = 0
const e = new Error(formatted)
Error.stackTraceLimit = l
Error.captureStackTrace(e, stackTraceLimitFunction)
logger.error(e)
})
}
if (cause) withNoop(() => logger.error(cause))
}
function onWarn (log) {
const { formatted, cause } = getErrorLog(log)
if (formatted) withNoop(() => logger.warn(formatted))
if (cause) withNoop(() => logger.warn(cause))
}
function onInfo (log) {
const { formatted, cause } = getErrorLog(log)
if (formatted) withNoop(() => logger.info(formatted))
if (cause) withNoop(() => logger.info(cause))
}
function onDebug (log) {
const { formatted, cause } = getErrorLog(log)
if (formatted) withNoop(() => logger.debug(formatted))
if (cause) withNoop(() => logger.debug(cause))
}
function onTrace (log) {
const { formatted, cause } = getErrorLog(log)
// Using logger.debug() because not all loggers have trace level,
// and console.trace() has a completely different meaning.
if (formatted) withNoop(() => logger.debug(formatted))
if (cause) withNoop(() => logger.debug(cause))
}
function error (...args) {
onError(Log.parse(...args))
}
function warn (...args) {
const log = Log.parse(...args)
if (!logger.warn) return onDebug(log)
onWarn(log)
}
function info (...args) {
const log = Log.parse(...args)
if (!logger.info) return onDebug(log)
onInfo(log)
}
function debug (...args) {
onDebug(Log.parse(...args))
}
function trace (...args) {
onTrace(Log.parse(...args))
}
module.exports = { use, toggle, reset, error, warn, info, debug, trace, setStackTraceLimitFunction }