dd-trace 5.2.0 → 5.3.0

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.
Files changed (68) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/README.md +1 -32
  3. package/ci/init.js +1 -4
  4. package/index.d.ts +21 -0
  5. package/package.json +6 -5
  6. package/packages/datadog-instrumentations/src/amqplib.js +1 -1
  7. package/packages/datadog-instrumentations/src/child_process.js +150 -0
  8. package/packages/datadog-instrumentations/src/cucumber.js +12 -12
  9. package/packages/datadog-instrumentations/src/express.js +20 -0
  10. package/packages/datadog-instrumentations/src/grpc/client.js +56 -36
  11. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -2
  12. package/packages/datadog-instrumentations/src/jest.js +147 -10
  13. package/packages/datadog-instrumentations/src/mocha.js +3 -3
  14. package/packages/datadog-instrumentations/src/mongoose.js +23 -10
  15. package/packages/datadog-instrumentations/src/next.js +17 -3
  16. package/packages/datadog-instrumentations/src/playwright.js +41 -9
  17. package/packages/datadog-plugin-amqplib/src/consumer.js +10 -1
  18. package/packages/datadog-plugin-amqplib/src/producer.js +14 -1
  19. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +107 -1
  20. package/packages/datadog-plugin-child_process/src/index.js +91 -0
  21. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +125 -0
  22. package/packages/datadog-plugin-cucumber/src/index.js +16 -11
  23. package/packages/datadog-plugin-cypress/src/plugin.js +25 -12
  24. package/packages/datadog-plugin-grpc/src/client.js +16 -2
  25. package/packages/datadog-plugin-http/src/client.js +1 -1
  26. package/packages/datadog-plugin-jest/src/index.js +47 -6
  27. package/packages/datadog-plugin-mocha/src/index.js +14 -5
  28. package/packages/datadog-plugin-playwright/src/index.js +19 -5
  29. package/packages/datadog-plugin-rhea/src/consumer.js +11 -1
  30. package/packages/datadog-plugin-rhea/src/producer.js +11 -0
  31. package/packages/dd-trace/src/appsec/addresses.js +2 -0
  32. package/packages/dd-trace/src/appsec/api_security_sampler.js +16 -3
  33. package/packages/dd-trace/src/appsec/channels.js +2 -1
  34. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +1 -1
  35. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +7 -28
  36. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +10 -6
  37. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +4 -1
  38. package/packages/dd-trace/src/appsec/index.js +17 -2
  39. package/packages/dd-trace/src/appsec/rule_manager.js +2 -2
  40. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +83 -0
  41. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +25 -6
  42. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +2 -0
  43. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +83 -41
  44. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +30 -8
  45. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +7 -1
  46. package/packages/dd-trace/src/ci-visibility/{intelligent-test-runner/get-itr-configuration.js → requests/get-library-configuration.js} +18 -6
  47. package/packages/dd-trace/src/config.js +22 -9
  48. package/packages/dd-trace/src/datastreams/processor.js +6 -0
  49. package/packages/dd-trace/src/datastreams/writer.js +2 -5
  50. package/packages/dd-trace/src/dogstatsd.js +3 -5
  51. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +5 -3
  52. package/packages/dd-trace/src/exporters/common/request.js +21 -3
  53. package/packages/dd-trace/src/format.js +25 -1
  54. package/packages/dd-trace/src/noop/span.js +1 -0
  55. package/packages/dd-trace/src/opentelemetry/span.js +9 -2
  56. package/packages/dd-trace/src/opentracing/span.js +38 -0
  57. package/packages/dd-trace/src/opentracing/span_context.js +12 -6
  58. package/packages/dd-trace/src/opentracing/tracer.js +2 -1
  59. package/packages/dd-trace/src/plugins/ci_plugin.js +24 -8
  60. package/packages/dd-trace/src/plugins/index.js +1 -0
  61. package/packages/dd-trace/src/plugins/util/git.js +6 -0
  62. package/packages/dd-trace/src/plugins/util/test.js +36 -7
  63. package/packages/dd-trace/src/profiling/config.js +22 -22
  64. package/packages/dd-trace/src/proxy.js +31 -23
  65. package/packages/dd-trace/src/span_processor.js +5 -1
  66. package/packages/dd-trace/src/telemetry/index.js +3 -0
  67. package/packages/datadog-instrumentations/src/child-process.js +0 -29
  68. package/packages/dd-trace/src/plugins/util/exec.js +0 -34
@@ -27,7 +27,7 @@ const {
27
27
  TELEMETRY_EVENT_CREATED,
28
28
  TELEMETRY_ITR_SKIPPED
29
29
  } = require('../ci-visibility/telemetry')
30
- const { CI_PROVIDER_NAME, GIT_REPOSITORY_URL, GIT_COMMIT_SHA, GIT_BRANCH } = require('./util/tags')
30
+ const { CI_PROVIDER_NAME, GIT_REPOSITORY_URL, GIT_COMMIT_SHA, GIT_BRANCH, CI_WORKSPACE_PATH } = require('./util/tags')
31
31
  const { OS_VERSION, OS_PLATFORM, OS_ARCHITECTURE, RUNTIME_NAME, RUNTIME_VERSION } = require('./util/env')
32
32
 
33
33
  module.exports = class CiPlugin extends Plugin {
@@ -36,17 +36,17 @@ module.exports = class CiPlugin extends Plugin {
36
36
 
37
37
  this.rootDir = process.cwd() // fallback in case :session:start events are not emitted
38
38
 
39
- this.addSub(`ci:${this.constructor.id}:itr-configuration`, ({ onDone }) => {
40
- if (!this.tracer._exporter || !this.tracer._exporter.getItrConfiguration) {
39
+ this.addSub(`ci:${this.constructor.id}:library-configuration`, ({ onDone }) => {
40
+ if (!this.tracer._exporter || !this.tracer._exporter.getLibraryConfiguration) {
41
41
  return onDone({ err: new Error('CI Visibility was not initialized correctly') })
42
42
  }
43
- this.tracer._exporter.getItrConfiguration(this.testConfiguration, (err, itrConfig) => {
43
+ this.tracer._exporter.getLibraryConfiguration(this.testConfiguration, (err, libraryConfig) => {
44
44
  if (err) {
45
45
  log.error(`Intelligent Test Runner configuration could not be fetched. ${err.message}`)
46
46
  } else {
47
- this.itrConfig = itrConfig
47
+ this.libraryConfig = libraryConfig
48
48
  }
49
- onDone({ err, itrConfig })
49
+ onDone({ err, libraryConfig })
50
50
  })
51
51
  })
52
52
 
@@ -115,6 +115,18 @@ module.exports = class CiPlugin extends Plugin {
115
115
  })
116
116
  this.telemetry.count(TELEMETRY_ITR_SKIPPED, { testLevel: 'suite' }, skippedSuites.length)
117
117
  })
118
+
119
+ this.addSub(`ci:${this.constructor.id}:known-tests`, ({ onDone }) => {
120
+ if (!this.tracer._exporter?.getKnownTests) {
121
+ return onDone({ err: new Error('CI Visibility was not initialized correctly') })
122
+ }
123
+ this.tracer._exporter.getKnownTests(this.testConfiguration, (err, knownTests) => {
124
+ if (err) {
125
+ log.error(`Known tests could not be fetched. ${err.message}`)
126
+ }
127
+ onDone({ err, knownTests })
128
+ })
129
+ })
118
130
  }
119
131
 
120
132
  get telemetry () {
@@ -140,7 +152,6 @@ module.exports = class CiPlugin extends Plugin {
140
152
  configure (config) {
141
153
  super.configure(config)
142
154
  this.testEnvironmentMetadata = getTestEnvironmentMetadata(this.constructor.id, this.config)
143
- this.codeOwnersEntries = getCodeOwnersFileEntries()
144
155
 
145
156
  const {
146
157
  [GIT_REPOSITORY_URL]: repositoryUrl,
@@ -151,9 +162,14 @@ module.exports = class CiPlugin extends Plugin {
151
162
  [RUNTIME_NAME]: runtimeName,
152
163
  [RUNTIME_VERSION]: runtimeVersion,
153
164
  [GIT_BRANCH]: branch,
154
- [CI_PROVIDER_NAME]: ciProviderName
165
+ [CI_PROVIDER_NAME]: ciProviderName,
166
+ [CI_WORKSPACE_PATH]: repositoryRoot
155
167
  } = this.testEnvironmentMetadata
156
168
 
169
+ this.repositoryRoot = repositoryRoot || process.cwd()
170
+
171
+ this.codeOwnersEntries = getCodeOwnersFileEntries(repositoryRoot)
172
+
157
173
  this.isUnsupportedCIProvider = !ciProviderName
158
174
 
159
175
  this.testConfiguration = {
@@ -23,6 +23,7 @@ module.exports = {
23
23
  get 'aws-sdk' () { return require('../../../datadog-plugin-aws-sdk/src') },
24
24
  get 'bunyan' () { return require('../../../datadog-plugin-bunyan/src') },
25
25
  get 'cassandra-driver' () { return require('../../../datadog-plugin-cassandra-driver/src') },
26
+ get 'child_process' () { return require('../../../datadog-plugin-child_process/src') },
26
27
  get 'connect' () { return require('../../../datadog-plugin-connect/src') },
27
28
  get 'couchbase' () { return require('../../../datadog-plugin-couchbase/src') },
28
29
  get 'cypress' () { return require('../../../datadog-plugin-cypress/src') },
@@ -26,6 +26,7 @@ const {
26
26
  TELEMETRY_GIT_COMMAND_ERRORS
27
27
  } = require('../../ci-visibility/telemetry')
28
28
  const { filterSensitiveInfoFromRepository } = require('./url')
29
+ const { storage } = require('../../../../datadog-core')
29
30
 
30
31
  const GIT_REV_LIST_MAX_BUFFER = 8 * 1024 * 1024 // 8MB
31
32
 
@@ -36,6 +37,9 @@ function sanitizedExec (
36
37
  durationMetric,
37
38
  errorMetric
38
39
  ) {
40
+ const store = storage.getStore()
41
+ storage.enterWith({ noop: true })
42
+
39
43
  let startTime
40
44
  if (operationMetric) {
41
45
  incrementCountMetric(operationMetric.name, operationMetric.tags)
@@ -55,6 +59,8 @@ function sanitizedExec (
55
59
  }
56
60
  log.error(e)
57
61
  return ''
62
+ } finally {
63
+ storage.enterWith(store)
58
64
  }
59
65
  }
60
66
 
@@ -48,6 +48,12 @@ const TEST_MODULE_ID = 'test_module_id'
48
48
  const TEST_SUITE_ID = 'test_suite_id'
49
49
  const TEST_TOOLCHAIN = 'test.toolchain'
50
50
  const TEST_SKIPPED_BY_ITR = 'test.skipped_by_itr'
51
+ // Browser used in browser test. Namespaced by test.configuration because it affects the fingerprint
52
+ const TEST_CONFIGURATION_BROWSER_NAME = 'test.configuration.browser_name'
53
+ // Early flake detection
54
+ const TEST_IS_NEW = 'test.is_new'
55
+ const TEST_EARLY_FLAKE_IS_RETRY = 'test.early_flake.is_retry'
56
+ const TEST_EARLY_FLAKE_IS_ENABLED = 'test.early_flake.is_enabled'
51
57
 
52
58
  const CI_APP_ORIGIN = 'ciapp-test'
53
59
 
@@ -87,6 +93,10 @@ module.exports = {
87
93
  JEST_WORKER_COVERAGE_PAYLOAD_CODE,
88
94
  TEST_SOURCE_START,
89
95
  TEST_SKIPPED_BY_ITR,
96
+ TEST_CONFIGURATION_BROWSER_NAME,
97
+ TEST_IS_NEW,
98
+ TEST_EARLY_FLAKE_IS_RETRY,
99
+ TEST_EARLY_FLAKE_IS_ENABLED,
90
100
  getTestEnvironmentMetadata,
91
101
  getTestParametersString,
92
102
  finishAllTraceSpans,
@@ -253,7 +263,6 @@ function getTestCommonTags (name, suite, version, testFramework) {
253
263
  [SAMPLING_PRIORITY]: AUTO_KEEP,
254
264
  [TEST_NAME]: name,
255
265
  [TEST_SUITE]: suite,
256
- [TEST_SOURCE_FILE]: suite,
257
266
  [RESOURCE_NAME]: `${suite}.${name}`,
258
267
  [TEST_FRAMEWORK_VERSION]: version,
259
268
  [LIBRARY_VERSION]: ddTraceVersion
@@ -281,16 +290,36 @@ const POSSIBLE_CODEOWNERS_LOCATIONS = [
281
290
  '.gitlab/CODEOWNERS'
282
291
  ]
283
292
 
284
- function getCodeOwnersFileEntries (rootDir = process.cwd()) {
285
- let codeOwnersContent
286
-
287
- POSSIBLE_CODEOWNERS_LOCATIONS.forEach(location => {
293
+ function readCodeOwners (rootDir) {
294
+ for (const location of POSSIBLE_CODEOWNERS_LOCATIONS) {
288
295
  try {
289
- codeOwnersContent = fs.readFileSync(`${rootDir}/${location}`).toString()
296
+ return fs.readFileSync(path.join(rootDir, location)).toString()
290
297
  } catch (e) {
291
298
  // retry with next path
292
299
  }
293
- })
300
+ }
301
+ return ''
302
+ }
303
+
304
+ function getCodeOwnersFileEntries (rootDir) {
305
+ let codeOwnersContent
306
+ let usedRootDir = rootDir
307
+ let isTriedCwd = false
308
+
309
+ const processCwd = process.cwd()
310
+
311
+ if (!usedRootDir || usedRootDir === processCwd) {
312
+ usedRootDir = processCwd
313
+ isTriedCwd = true
314
+ }
315
+
316
+ codeOwnersContent = readCodeOwners(usedRootDir)
317
+
318
+ // If we haven't found CODEOWNERS in the provided root dir, we try with process.cwd()
319
+ if (!codeOwnersContent && !isTriedCwd) {
320
+ codeOwnersContent = readCodeOwners(processCwd)
321
+ }
322
+
294
323
  if (!codeOwnersContent) {
295
324
  return null
296
325
  }
@@ -18,34 +18,34 @@ const { isFalse, isTrue } = require('../util')
18
18
  class Config {
19
19
  constructor (options = {}) {
20
20
  const {
21
- DD_PROFILING_ENABLED,
22
- DD_PROFILING_PROFILERS,
23
- DD_ENV,
24
- DD_TAGS,
25
- DD_SERVICE,
26
- DD_VERSION,
27
- DD_TRACE_AGENT_URL,
28
21
  DD_AGENT_HOST,
29
- DD_TRACE_AGENT_PORT,
22
+ DD_ENV,
23
+ DD_PROFILING_CODEHOTSPOTS_ENABLED,
30
24
  DD_PROFILING_DEBUG_SOURCE_MAPS,
31
- DD_PROFILING_UPLOAD_TIMEOUT,
32
- DD_PROFILING_SOURCE_MAP,
33
- DD_PROFILING_UPLOAD_PERIOD,
34
- DD_PROFILING_PPROF_PREFIX,
35
- DD_PROFILING_HEAP_ENABLED,
36
- DD_PROFILING_V8_PROFILER_BUG_WORKAROUND,
37
- DD_PROFILING_WALLTIME_ENABLED,
25
+ DD_PROFILING_ENABLED,
26
+ DD_PROFILING_ENDPOINT_COLLECTION_ENABLED,
27
+ DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED,
38
28
  DD_PROFILING_EXPERIMENTAL_CPU_ENABLED,
39
- DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED,
29
+ DD_PROFILING_EXPERIMENTAL_ENDPOINT_COLLECTION_ENABLED,
30
+ DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES,
40
31
  DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE,
41
32
  DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT,
42
- DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES,
43
- DD_PROFILING_TIMELINE_ENABLED,
33
+ DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED,
44
34
  DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED,
45
- DD_PROFILING_CODEHOTSPOTS_ENABLED,
46
- DD_PROFILING_ENDPOINT_COLLECTION_ENABLED,
47
- DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED,
48
- DD_PROFILING_EXPERIMENTAL_ENDPOINT_COLLECTION_ENABLED
35
+ DD_PROFILING_HEAP_ENABLED,
36
+ DD_PROFILING_PPROF_PREFIX,
37
+ DD_PROFILING_PROFILERS,
38
+ DD_PROFILING_SOURCE_MAP,
39
+ DD_PROFILING_TIMELINE_ENABLED,
40
+ DD_PROFILING_UPLOAD_PERIOD,
41
+ DD_PROFILING_UPLOAD_TIMEOUT,
42
+ DD_PROFILING_V8_PROFILER_BUG_WORKAROUND,
43
+ DD_PROFILING_WALLTIME_ENABLED,
44
+ DD_SERVICE,
45
+ DD_TAGS,
46
+ DD_TRACE_AGENT_PORT,
47
+ DD_TRACE_AGENT_URL,
48
+ DD_VERSION
49
49
  } = process.env
50
50
 
51
51
  const enabled = isTrue(coalesce(options.enabled, DD_PROFILING_ENABLED, true))
@@ -19,6 +19,7 @@ class Tracer extends NoopProxy {
19
19
  this._initialized = false
20
20
  this._pluginManager = new PluginManager(this)
21
21
  this.dogstatsd = new dogstatsd.NoopDogStatsDClient()
22
+ this._tracingInitialized = false
22
23
  }
23
24
 
24
25
  init (options) {
@@ -28,6 +29,7 @@ class Tracer extends NoopProxy {
28
29
 
29
30
  try {
30
31
  const config = new Config(options) // TODO: support dynamic code config
32
+ telemetry.start(config, this._pluginManager)
31
33
 
32
34
  if (config.dogstatsd) {
33
35
  // Custom Metrics
@@ -60,11 +62,7 @@ class Tracer extends NoopProxy {
60
62
  } else {
61
63
  config.configure(conf.lib_config, true)
62
64
  }
63
-
64
- if (config.tracing) {
65
- this._tracer.configure(config)
66
- this._pluginManager.configure(config)
67
- }
65
+ this._enableOrDisableTracing(config)
68
66
  })
69
67
  }
70
68
 
@@ -89,25 +87,9 @@ class Tracer extends NoopProxy {
89
87
  runtimeMetrics.start(config)
90
88
  }
91
89
 
92
- if (config.tracing) {
93
- // TODO: This should probably not require tracing to be enabled.
94
- telemetry.start(config, this._pluginManager)
95
-
96
- // dirty require for now so zero appsec code is executed unless explicitly enabled
97
- if (config.appsec.enabled) {
98
- require('./appsec').enable(config)
99
- }
100
-
101
- this._tracer = new DatadogTracer(config)
102
- this.appsec = new AppsecSdk(this._tracer, config)
103
-
104
- if (config.iast.enabled) {
105
- require('./appsec/iast').enable(config, this._tracer)
106
- }
107
-
108
- this._pluginManager.configure(config)
109
- setStartupLogPluginManager(this._pluginManager)
90
+ this._enableOrDisableTracing(config)
110
91
 
92
+ if (config.tracing) {
111
93
  if (config.isManualApiEnabled) {
112
94
  const TestApiManualPlugin = require('./ci-visibility/test-api-manual/test-api-manual-plugin')
113
95
  this._testApiManualPlugin = new TestApiManualPlugin(this)
@@ -121,6 +103,32 @@ class Tracer extends NoopProxy {
121
103
  return this
122
104
  }
123
105
 
106
+ _enableOrDisableTracing (config) {
107
+ if (config.tracing !== false) {
108
+ // dirty require for now so zero appsec code is executed unless explicitly enabled
109
+ if (config.appsec.enabled) {
110
+ require('./appsec').enable(config)
111
+ }
112
+ if (!this._tracingInitialized) {
113
+ this._tracer = new DatadogTracer(config)
114
+ this.appsec = new AppsecSdk(this._tracer, config)
115
+ this._tracingInitialized = true
116
+ }
117
+ if (config.iast.enabled) {
118
+ require('./appsec/iast').enable(config, this._tracer)
119
+ }
120
+ } else if (this._tracingInitialized) {
121
+ require('./appsec').disable()
122
+ require('./appsec/iast').disable()
123
+ }
124
+
125
+ if (this._tracingInitialized) {
126
+ this._tracer.configure(config)
127
+ this._pluginManager.configure(config)
128
+ setStartupLogPluginManager(this._pluginManager)
129
+ }
130
+ }
131
+
124
132
  profilerStarted () {
125
133
  if (!this._profilerStarted) {
126
134
  throw new Error('profilerStarted() must be called after init()')
@@ -27,10 +27,14 @@ class SpanProcessor {
27
27
  const active = []
28
28
  const formatted = []
29
29
  const trace = spanContext._trace
30
- const { flushMinSpans } = this._config
30
+ const { flushMinSpans, tracing } = this._config
31
31
  const { started, finished } = trace
32
32
 
33
33
  if (trace.record === false) return
34
+ if (tracing === false) {
35
+ this._erase(trace, active)
36
+ return
37
+ }
34
38
  if (started.length === finished.length || finished.length >= flushMinSpans) {
35
39
  this._prioritySampler.sample(spanContext)
36
40
  this._spanSampler.sample(spanContext)
@@ -141,6 +141,9 @@ function appStarted (config) {
141
141
  }
142
142
 
143
143
  function appClosing () {
144
+ if (!config?.telemetry?.enabled) {
145
+ return
146
+ }
144
147
  const { reqType, payload } = createPayload('app-closing')
145
148
  sendData(config, application, host, reqType, payload)
146
149
  // we flush before shutting down. Only in CI Visibility
@@ -1,29 +0,0 @@
1
- 'use strict'
2
-
3
- const {
4
- channel,
5
- addHook
6
- } = require('./helpers/instrument')
7
- const shimmer = require('../../datadog-shimmer')
8
-
9
- const childProcessChannel = channel('datadog:child_process:execution:start')
10
- const execMethods = ['exec', 'execFile', 'fork', 'spawn', 'execFileSync', 'execSync', 'spawnSync']
11
- const names = ['child_process', 'node:child_process']
12
-
13
- addHook({ name: names }, childProcess => {
14
- shimmer.massWrap(childProcess, execMethods, wrapChildProcessMethod())
15
- return childProcess
16
- })
17
-
18
- function wrapChildProcessMethod () {
19
- function wrapMethod (childProcessMethod) {
20
- return function () {
21
- if (childProcessChannel.hasSubscribers && arguments.length > 0) {
22
- const command = arguments[0]
23
- childProcessChannel.publish({ command })
24
- }
25
- return childProcessMethod.apply(this, arguments)
26
- }
27
- }
28
- return wrapMethod
29
- }
@@ -1,34 +0,0 @@
1
- const cp = require('child_process')
2
- const log = require('../../log')
3
- const { distributionMetric, incrementCountMetric } = require('../../ci-visibility/telemetry')
4
-
5
- const sanitizedExec = (
6
- cmd,
7
- flags,
8
- operationMetric,
9
- durationMetric,
10
- errorMetric
11
- ) => {
12
- let startTime
13
- if (operationMetric) {
14
- incrementCountMetric(operationMetric.name, operationMetric.tags)
15
- }
16
- if (durationMetric) {
17
- startTime = Date.now()
18
- }
19
- try {
20
- const result = cp.execFileSync(cmd, flags, { stdio: 'pipe' }).toString().replace(/(\r\n|\n|\r)/gm, '')
21
- if (durationMetric) {
22
- distributionMetric(durationMetric.name, durationMetric.tags, Date.now() - startTime)
23
- }
24
- return result
25
- } catch (e) {
26
- if (errorMetric) {
27
- incrementCountMetric(errorMetric.name, { ...errorMetric.tags, exitCode: e.status })
28
- }
29
- log.error(e)
30
- return ''
31
- }
32
- }
33
-
34
- module.exports = { sanitizedExec }