UNPKG

dd-trace

Version:

Datadog APM tracing client for JavaScript

139 lines (120 loc) 3.54 kB
'use strict' const { EOL } = require('node:os') // Load binding first to not import other modules if it throws const libdatadog = require('@datadog/libdatadog') const binding = libdatadog.load('crashtracker') const log = require('../log') const { getAgentUrl } = require('../agent/url') const pkg = require('../../../../package.json') const processTags = require('../process-tags') class Crashtracker { #started = false configure (config) { if (!this.#started) return try { binding.updateConfig(this.#getConfig(config)) binding.updateMetadata(this.#getMetadata(config)) } catch (e) { log.error('Error configuring crashtracker', e) } } /** * @param {import('../config/config-base')} config - Tracer configuration */ start (config) { if (this.#started) return this.configure(config) try { binding.init( this.#getConfig(config), this.#getReceiverConfig(), this.#getMetadata(config) ) this.#started = true this.#trackUnhandledExceptions() } catch (e) { log.error('Error initializing crashtracker', e) } } #trackUnhandledExceptions () { process.once('uncaughtExceptionMonitor', (error, origin) => { try { binding.reportUncaughtExceptionMonitor(error, origin) } catch (e) { process.stderr.write(`Error reporting uncaught exception to crashtracker: ${e.toString()}${EOL}`) } }) } withProfilerSerializing (f) { binding.beginProfilerSerializing() try { return f() } finally { binding.endProfilerSerializing() } } // TODO: Send only configured values when defaults are fixed. /** * @param {import('../config/config-base')} config - Tracer configuration */ #getConfig (config) { const url = getAgentUrl(config) // Out-of-process symbolication currently works on // Linux only, does not work on Mac. const resolveMode = require('os').platform === 'linux' ? 'EnabledWithSymbolsInReceiver' : 'EnabledWithInprocessSymbols' return { additional_files: [], create_alt_stack: true, use_alt_stack: true, endpoint: { // TODO: Use the string directly when deserialization is fixed. url: { scheme: url.protocol.slice(0, -1), authority: url.protocol === 'unix:' ? Buffer.from(url.pathname).toString('hex') : url.host, path_and_query: '', }, timeout_ms: 3000, }, timeout: { secs: 5, nanos: 0 }, demangle_names: true, signals: [], resolve_frames: resolveMode, } } #getMetadata (config) { const tags = Object.keys(config.tags).map(key => `${key}:${config.tags[key]}`) // Add process tags to the tags array for (const [key, value] of processTags.tags) { if (value !== undefined) { tags.push(`${key}:${value}`) } } return { library_name: pkg.name, library_version: pkg.version, family: 'nodejs', tags: [ ...tags, 'is_crash:true', 'language:javascript', `library_version:${pkg.version}`, 'runtime:nodejs', `runtime_version:${process.versions.node}`, 'severity:crash', ], } } #getReceiverConfig () { return { args: [], env: [], path_to_receiver_binary: libdatadog.find('crashtracker-receiver', true), stderr_filename: null, stdout_filename: null, } } } module.exports = new Crashtracker()