|
| 1 | +'use strict' |
| 2 | + |
| 3 | +const path = require('node:path') |
| 4 | +const pkg = require('../pkg') |
| 5 | + |
| 6 | +const CURRENT_WORKING_DIRECTORY = process.cwd() |
| 7 | +const ENTRYPOINT_PATH = require.main?.filename || '' |
| 8 | + |
| 9 | +const TRACING_FIELD_NAME = '_dd.tags.process' |
| 10 | +const DSM_FIELD_NAME = 'ProcessTags' |
| 11 | +const PROFILING_FIELD_NAME = 'process_tags' |
| 12 | + |
| 13 | +module.exports.TRACING_FIELD_NAME = TRACING_FIELD_NAME |
| 14 | +module.exports.DSM_FIELD_NAME = DSM_FIELD_NAME |
| 15 | +module.exports.PROFILING_FIELD_NAME = PROFILING_FIELD_NAME |
| 16 | + |
| 17 | +// TODO CRASH_TRACKING_FIELD_NAME /process_tags /application/process_tags |
| 18 | +// TODO: TELEMETRY_FIELD_NAME /application/process_tags |
| 19 | +// TODO: DYNAMIC_INSTRUMENTATION_FIELD_NAME process_tags |
| 20 | +// TODO: CLIENT_TRACE_STATISTICS_FIELD_NAME process_tags |
| 21 | +// TODO: REMOTE_CONFIG_FIELD_NAME process_tags |
| 22 | + |
| 23 | +// $ cd /foo/bar && node baz/banana.js |
| 24 | +// entrypoint.workdir = bar |
| 25 | +// entrypoint.name = banana |
| 26 | +// entrypoint.type = script |
| 27 | +// entrypoint.basedir = baz |
| 28 | +// package.json.name = <from package.json> |
| 29 | + |
| 30 | +module.exports = function getProcessTags () { |
| 31 | + // this list is sorted alphabetically for consistent serialization |
| 32 | + const tags = [ |
| 33 | + // the parent directory name of the entrypoint script, e.g. /foo/bar/baz/banana.js -> baz |
| 34 | + ['entrypoint.basedir', ENTRYPOINT_PATH === '' ? undefined : path.basename(path.dirname(ENTRYPOINT_PATH))], |
| 35 | + |
| 36 | + // the entrypoint script filename without the extension, e.g. /foo/bar/baz/banana.js -> banana |
| 37 | + ['entrypoint.name', path.basename(ENTRYPOINT_PATH, path.extname(ENTRYPOINT_PATH)) || undefined], |
| 38 | + |
| 39 | + // always script for JavaScript applications |
| 40 | + ['entrypoint.type', 'script'], |
| 41 | + |
| 42 | + // last segment of the current working directory, e.g. /foo/bar/baz/ -> baz |
| 43 | + ['entrypoint.workdir', path.basename(CURRENT_WORKING_DIRECTORY) || undefined], |
| 44 | + |
| 45 | + // the .name field from the application's package.json |
| 46 | + ['package.json.name', pkg.name || undefined] |
| 47 | + ] |
| 48 | + |
| 49 | + const serialized = serialize(tags) |
| 50 | + |
| 51 | + return { |
| 52 | + tags, |
| 53 | + serialized |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +function serialize (tags) { |
| 58 | + const intermediary = [] |
| 59 | + for (const [name, value] of tags) { |
| 60 | + // if we don't have a value we should send nothing at all |
| 61 | + if (value === undefined) continue |
| 62 | + intermediary.push(`${name}:${sanitize(value)}`) |
| 63 | + } |
| 64 | + return intermediary.join(',') |
| 65 | +} |
| 66 | + |
| 67 | +module.exports.serialize = serialize |
| 68 | + |
| 69 | +/** |
| 70 | + * Sanitize a process tag value |
| 71 | + * |
| 72 | + * @param {string} value |
| 73 | + * @returns {string} |
| 74 | + */ |
| 75 | +function sanitize (value) { |
| 76 | + return String(value) |
| 77 | + .toLowerCase() |
| 78 | + .replaceAll(/[^a-zA-Z0-9/_.-]+/g, '_') |
| 79 | +} |
| 80 | + |
| 81 | +module.exports.sanitize = sanitize |
0 commit comments