dd-trace 2.4.2 → 2.7.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 (96) hide show
  1. package/LICENSE-3rdparty.csv +1 -2
  2. package/ci/init.js +6 -0
  3. package/ci/jest/env.js +16 -3
  4. package/ext/exporters.d.ts +2 -1
  5. package/ext/exporters.js +2 -1
  6. package/index.d.ts +17 -8
  7. package/package.json +20 -23
  8. package/packages/datadog-instrumentations/index.js +14 -0
  9. package/packages/datadog-instrumentations/src/connect.js +111 -0
  10. package/packages/datadog-instrumentations/src/cypress.js +8 -0
  11. package/packages/datadog-instrumentations/src/express.js +27 -0
  12. package/packages/datadog-instrumentations/src/fastify.js +187 -0
  13. package/packages/datadog-instrumentations/src/find-my-way.js +30 -0
  14. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +100 -0
  15. package/packages/datadog-instrumentations/src/http/server.js +1 -1
  16. package/packages/datadog-instrumentations/src/jest.js +175 -0
  17. package/packages/datadog-instrumentations/src/kafkajs.js +112 -0
  18. package/packages/datadog-instrumentations/src/knex.js +20 -0
  19. package/packages/datadog-instrumentations/src/koa.js +159 -0
  20. package/packages/datadog-instrumentations/src/limitd-client.js +21 -0
  21. package/packages/datadog-instrumentations/src/oracledb.js +128 -0
  22. package/packages/datadog-instrumentations/src/paperplane.js +77 -0
  23. package/packages/datadog-instrumentations/src/pg.js +2 -2
  24. package/packages/datadog-instrumentations/src/restify.js +58 -0
  25. package/packages/datadog-instrumentations/src/rhea.js +1 -1
  26. package/packages/datadog-instrumentations/src/router.js +177 -0
  27. package/packages/datadog-plugin-aws-sdk/src/helpers.js +4 -4
  28. package/packages/datadog-plugin-aws-sdk/src/index.js +1 -1
  29. package/packages/datadog-plugin-connect/src/index.js +10 -114
  30. package/packages/datadog-plugin-cucumber/src/index.js +16 -16
  31. package/packages/datadog-plugin-cypress/src/index.js +10 -5
  32. package/packages/datadog-plugin-cypress/src/plugin.js +18 -17
  33. package/packages/datadog-plugin-dns/src/index.js +12 -1
  34. package/packages/datadog-plugin-express/src/index.js +11 -25
  35. package/packages/datadog-plugin-fastify/src/index.js +17 -4
  36. package/packages/datadog-plugin-find-my-way/src/index.js +20 -0
  37. package/packages/datadog-plugin-fs/src/index.js +2 -0
  38. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +56 -111
  39. package/packages/datadog-plugin-http/src/server.js +2 -10
  40. package/packages/datadog-plugin-jest/src/index.js +101 -3
  41. package/packages/datadog-plugin-jest/src/util.js +1 -29
  42. package/packages/datadog-plugin-kafkajs/src/index.js +64 -90
  43. package/packages/datadog-plugin-koa/src/index.js +12 -164
  44. package/packages/datadog-plugin-mocha/src/index.js +14 -15
  45. package/packages/datadog-plugin-oracledb/src/index.js +34 -100
  46. package/packages/datadog-plugin-paperplane/src/index.js +14 -100
  47. package/packages/datadog-plugin-paperplane/src/logger.js +11 -0
  48. package/packages/datadog-plugin-paperplane/src/server.js +24 -0
  49. package/packages/datadog-plugin-restify/src/index.js +13 -75
  50. package/packages/datadog-plugin-router/src/index.js +67 -164
  51. package/packages/datadog-plugin-web/src/index.js +20 -0
  52. package/packages/dd-trace/lib/version.js +1 -1
  53. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +34 -12
  54. package/packages/dd-trace/src/appsec/index.js +7 -3
  55. package/packages/dd-trace/src/appsec/recommended.json +15 -5
  56. package/packages/dd-trace/src/appsec/reporter.js +33 -3
  57. package/packages/dd-trace/src/appsec/rule_manager.js +2 -2
  58. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +32 -0
  59. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +51 -0
  60. package/packages/dd-trace/src/config.js +33 -4
  61. package/packages/dd-trace/src/encode/0.4.js +0 -1
  62. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +193 -0
  63. package/packages/dd-trace/src/encode/tags-processors.js +116 -0
  64. package/packages/dd-trace/src/exporter.js +3 -0
  65. package/packages/dd-trace/src/exporters/agent/index.js +1 -1
  66. package/packages/dd-trace/src/exporters/agent/writer.js +7 -32
  67. package/packages/dd-trace/src/exporters/{agent → common}/docker.js +0 -0
  68. package/packages/dd-trace/src/exporters/common/request.js +83 -0
  69. package/packages/dd-trace/src/exporters/common/writer.js +36 -0
  70. package/packages/dd-trace/src/exporters/{agent/scheduler.js → scheduler.js} +0 -0
  71. package/packages/dd-trace/src/format.js +9 -5
  72. package/packages/dd-trace/src/instrumenter.js +3 -0
  73. package/packages/dd-trace/src/pkg.js +11 -6
  74. package/packages/dd-trace/src/plugin_manager.js +13 -7
  75. package/packages/dd-trace/src/plugins/index.js +1 -2
  76. package/packages/dd-trace/src/plugins/log_plugin.js +8 -4
  77. package/packages/dd-trace/src/plugins/plugin.js +8 -0
  78. package/packages/dd-trace/src/plugins/util/test.js +79 -1
  79. package/packages/dd-trace/src/plugins/util/web.js +41 -12
  80. package/packages/dd-trace/src/profiling/config.js +8 -8
  81. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  82. package/packages/dd-trace/src/profiling/index.js +4 -4
  83. package/packages/dd-trace/src/profiling/profilers/{heap.js → space.js} +2 -2
  84. package/packages/dd-trace/src/profiling/profilers/{cpu.js → wall.js} +3 -3
  85. package/packages/dd-trace/src/proxy.js +2 -0
  86. package/packages/dd-trace/src/span_processor.js +4 -1
  87. package/packages/dd-trace/src/telemetry.js +187 -0
  88. package/scripts/install_plugin_modules.js +1 -0
  89. package/packages/datadog-plugin-fastify/src/fastify.js +0 -198
  90. package/packages/datadog-plugin-fastify/src/find-my-way.js +0 -37
  91. package/packages/datadog-plugin-jest/src/jest-environment.js +0 -272
  92. package/packages/datadog-plugin-jest/src/jest-jasmine2.js +0 -185
  93. package/packages/datadog-plugin-knex/src/index.js +0 -23
  94. package/packages/datadog-plugin-limitd-client/src/index.js +0 -30
  95. package/packages/dd-trace/src/exporters/agent/request.js +0 -86
  96. package/scripts/postpublish.js +0 -24
@@ -1,111 +1,25 @@
1
1
  'use strict'
2
2
 
3
- const web = require('../../dd-trace/src/plugins/util/web')
3
+ const Plugin = require('../../dd-trace/src/plugins/plugin')
4
+ const PaperplaneLoggerPlugin = require('./logger')
5
+ const PaperplaneServerPlugin = require('./server')
4
6
 
5
- const traceRoute = handler => req => {
6
- const { original, route } = req
7
-
8
- if (web.active(original)) {
9
- web.enterRoute(original, route)
7
+ class PaperplanePlugin extends Plugin {
8
+ static get name () {
9
+ return 'paperplane'
10
10
  }
11
11
 
12
- return handler(req)
13
- }
14
-
15
- const wrapLogger = tracer => logger => record => {
16
- const span = tracer.scope().active()
12
+ constructor (...args) {
13
+ super(...args)
17
14
 
18
- if (!span) return logger(record)
19
-
20
- const correlation = {
21
- dd: {
22
- trace_id: span.context().toTraceId(),
23
- span_id: span.context().toSpanId()
24
- }
15
+ this.server = new PaperplaneServerPlugin(...args)
16
+ this.logger = new PaperplaneLoggerPlugin(...args)
25
17
  }
26
18
 
27
- record = record instanceof Error
28
- ? Object.assign(record, correlation)
29
- : Object.assign({}, record, correlation)
30
-
31
- return logger(record)
32
- }
33
-
34
- const wrapMount = (tracer, config) => mount => opts => {
35
- const handler = mount(opts)
36
-
37
- const traced = (req, res) =>
38
- web.instrument(
39
- tracer, config, req, res, 'paperplane.request',
40
- () => handler(req, res)
41
- )
42
-
43
- return traced
44
- }
45
-
46
- const wrapRoutes = tracer => routes => handlers => {
47
- const traced = {}
48
-
49
- for (const route in handlers) {
50
- traced[route] = traceRoute(handlers[route])
19
+ configure (config) {
20
+ this.server.configure(config)
21
+ this.logger.configure(config)
51
22
  }
52
-
53
- return routes(traced)
54
23
  }
55
24
 
56
- const nodeMajor = Number(process.versions.node.split('.')[0])
57
- const mainVersionRange = nodeMajor <= 12 ? ['>=2.3.2'] : nodeMajor <= 14 ? ['>=3.1.1'] : []
58
-
59
- module.exports = [
60
- {
61
- name: 'paperplane',
62
- versions: mainVersionRange,
63
- file: 'lib/logger.js',
64
- patch (exports, tracer) {
65
- if (tracer._logInjection) {
66
- this.wrap(exports, 'logger', wrapLogger(tracer))
67
- }
68
- },
69
- unpatch (exports) {
70
- this.unwrap(exports, 'logger')
71
- }
72
- },
73
- {
74
- name: 'paperplane',
75
- versions: mainVersionRange,
76
- file: 'lib/mount.js',
77
- patch (exports, tracer, config) {
78
- config = web.normalizeConfig(config)
79
- this.wrap(exports, 'mount', wrapMount(tracer, config))
80
- },
81
- unpatch (exports) {
82
- this.unwrap(exports, 'mount')
83
- }
84
- },
85
- {
86
- name: 'paperplane',
87
- versions: mainVersionRange,
88
- file: 'lib/routes.js',
89
- patch (exports, tracer) {
90
- this.wrap(exports, 'routes', wrapRoutes(tracer))
91
- },
92
- unpatch (exports) {
93
- this.unwrap(exports, 'routes')
94
- }
95
- }
96
- ]
97
-
98
- if (nodeMajor <= 12) {
99
- module.exports.push({
100
- name: 'paperplane',
101
- versions: ['2.3.0 - 2.3.1'],
102
- patch (paperplane, tracer, config) {
103
- config = web.normalizeConfig(config)
104
- this.wrap(paperplane, 'mount', wrapMount(tracer, config))
105
- this.wrap(paperplane, 'routes', wrapRoutes(tracer))
106
- },
107
- unpatch (paperplane) {
108
- this.unwrap(paperplane, ['mount', 'routes'])
109
- }
110
- })
111
- }
25
+ module.exports = PaperplanePlugin
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ const LogPlugin = require('../../dd-trace/src/plugins/log_plugin')
4
+
5
+ class PaperplaneLoggerPlugin extends LogPlugin {
6
+ static get name () {
7
+ return 'paperplane'
8
+ }
9
+ }
10
+
11
+ module.exports = PaperplaneLoggerPlugin
@@ -0,0 +1,24 @@
1
+ 'use strict'
2
+
3
+ const RouterPlugin = require('../../datadog-plugin-router/src')
4
+ const web = require('../../dd-trace/src/plugins/util/web')
5
+
6
+ class PaperplaneServerPlugin extends RouterPlugin {
7
+ static get name () {
8
+ return 'paperplane'
9
+ }
10
+
11
+ constructor (...args) {
12
+ super(...args)
13
+
14
+ this.addSub('apm:paperplane:request:handle', req => {
15
+ this.setFramework(req, 'paperplane', this.config)
16
+ })
17
+
18
+ this.addSub('apm:paperplane:request:route', ({ req, route }) => {
19
+ web.setRoute(req, route)
20
+ })
21
+ }
22
+ }
23
+
24
+ module.exports = PaperplaneServerPlugin
@@ -1,86 +1,24 @@
1
1
  'use strict'
2
2
 
3
+ const RouterPlugin = require('../../datadog-plugin-router/src')
3
4
  const web = require('../../dd-trace/src/plugins/util/web')
4
- const handlers = ['use', 'pre']
5
- const methods = ['del', 'get', 'head', 'opts', 'post', 'put', 'patch']
6
5
 
7
- function createWrapSetupRequest (tracer, config, withRoute) {
8
- config = web.normalizeConfig(config)
9
-
10
- return function wrapSetupRequest (setupRequest) {
11
- return function setupRequestWithTrace (req, res) {
12
- return web.instrument(tracer, config, req, res, 'restify.request', () => {
13
- web.beforeEnd(req, () => {
14
- if (req.route && withRoute) {
15
- web.enterRoute(req, req.route.path)
16
- }
17
- })
18
-
19
- return setupRequest.apply(this, arguments)
20
- })
21
- }
22
- }
23
- }
24
-
25
- function createWrapMethod (tracer, config) {
26
- return function wrapMethod (method) {
27
- return function methodWithTrace (path) {
28
- const middleware = wrapMiddleware(Array.prototype.slice.call(arguments, 1))
29
-
30
- return method.apply(this, [path].concat(middleware))
31
- }
6
+ class RestifyPlugin extends RouterPlugin {
7
+ static get name () {
8
+ return 'restify'
32
9
  }
33
- }
34
-
35
- function createWrapHandler (tracer, config) {
36
- return function wrapMethod (method) {
37
- return function methodWithTrace () {
38
- return method.apply(this, wrapMiddleware(arguments))
39
- }
40
- }
41
- }
42
10
 
43
- function wrapMiddleware (middleware) {
44
- return Array.prototype.map.call(middleware, wrapFn)
45
- }
11
+ constructor (...args) {
12
+ super(...args)
46
13
 
47
- function wrapFn (fn) {
48
- if (Array.isArray(fn)) return wrapMiddleware(fn)
14
+ this.addSub('apm:restify:request:handle', ({ req }) => {
15
+ this.setFramework(req, 'restify', this.config)
16
+ })
49
17
 
50
- return function (req, res, next) {
51
- return web.reactivate(req, () => fn.apply(this, arguments))
18
+ this.addSub('apm:restify:request:route', ({ req, route }) => {
19
+ web.setRoute(req, route)
20
+ })
52
21
  }
53
22
  }
54
23
 
55
- module.exports = [
56
- {
57
- name: 'restify',
58
- versions: ['>=7'],
59
- file: 'lib/server.js',
60
- patch (Server, tracer, config) {
61
- this.wrap(Server.prototype, '_setupRequest', createWrapSetupRequest(tracer, config))
62
- this.wrap(Server.prototype, handlers, createWrapHandler(tracer, config))
63
- this.wrap(Server.prototype, methods, createWrapMethod(tracer, config))
64
- },
65
- unpatch (Server) {
66
- this.unwrap(Server.prototype, '_setupRequest')
67
- this.unwrap(Server.prototype, handlers)
68
- this.unwrap(Server.prototype, methods)
69
- }
70
- },
71
- {
72
- name: 'restify',
73
- versions: ['3 - 6'],
74
- file: 'lib/server.js',
75
- patch (Server, tracer, config) {
76
- this.wrap(Server.prototype, '_setupRequest', createWrapSetupRequest(tracer, config, true))
77
- this.wrap(Server.prototype, handlers, createWrapHandler(tracer, config))
78
- this.wrap(Server.prototype, methods, createWrapMethod(tracer, config))
79
- },
80
- unpatch (Server) {
81
- this.unwrap(Server.prototype, '_setupRequest')
82
- this.unwrap(Server.prototype, handlers)
83
- this.unwrap(Server.prototype, methods)
84
- }
85
- }
86
- ]
24
+ module.exports = RestifyPlugin
@@ -1,204 +1,107 @@
1
1
  'use strict'
2
2
 
3
- const METHODS = require('methods').concat('all')
4
- const pathToRegExp = require('path-to-regexp')
5
- const shimmer = require('../../datadog-shimmer')
6
3
  const web = require('../../dd-trace/src/plugins/util/web')
4
+ const WebPlugin = require('../../datadog-plugin-web/src')
5
+ const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
6
+ const { storage } = require('../../datadog-core')
7
7
 
8
- // TODO: stop checking for fast star and fast slash
9
-
10
- const contexts = new WeakMap()
11
- const layerMatchers = new WeakMap()
12
- const regexpCache = Object.create(null)
13
-
14
- function createWrapHandle (tracer, config) {
15
- return function wrapHandle (handle) {
16
- return function handleWithTrace (req, res, done) {
17
- web.patch(req)
18
-
19
- if (!contexts.has(req)) {
20
- const context = {
21
- route: '',
22
- stack: []
23
- }
24
-
25
- web.beforeEnd(req, () => {
26
- web.enterRoute(req, context.route)
27
- })
28
-
29
- contexts.set(req, context)
30
- }
31
-
32
- return handle.apply(this, arguments)
33
- }
8
+ class RouterPlugin extends WebPlugin {
9
+ static get name () {
10
+ return 'router'
34
11
  }
35
- }
36
12
 
37
- function wrapRouterMethod (original) {
38
- return function methodWithTrace (fn) {
39
- const offset = this.stack ? [].concat(this.stack).length : 0
40
- const router = original.apply(this, arguments)
13
+ constructor (...args) {
14
+ super(...args)
41
15
 
42
- if (typeof this.stack === 'function') {
43
- this.stack = [{ handle: this.stack }]
44
- }
16
+ this._contexts = new WeakMap()
45
17
 
46
- wrapStack(this.stack, offset, extractMatchers(fn))
47
-
48
- return router
49
- }
50
- }
18
+ this.addSub(`apm:${this.constructor.name}:middleware:enter`, ({ req, name, route }) => {
19
+ const store = storage.getStore()
20
+ const context = this._createContext(req, route)
21
+ const span = this._getMiddlewareSpan(context, store, name)
51
22
 
52
- function wrapLayerHandle (layer, handle) {
53
- handle._name = handle._name || layer.name
23
+ this.enter(span, store)
54
24
 
55
- let wrapCallHandle
56
-
57
- if (handle.length === 4) {
58
- wrapCallHandle = shimmer.wrap(handle, function (error, req, res, next) {
59
- return callHandle(layer, handle, req, [error, req, res, wrapNext(layer, req, next)])
60
- })
61
- } else {
62
- wrapCallHandle = shimmer.wrap(handle, function (req, res, next) {
63
- return callHandle(layer, handle, req, [req, res, wrapNext(layer, req, next)])
25
+ web.patch(req)
26
+ web.setRoute(req, context.route)
64
27
  })
65
- }
66
28
 
67
- // This is a workaround for the `loopback` library so that it can find the correct express layer
68
- // that contains the real handle function
69
- wrapCallHandle._datadog_orig = handle
29
+ this.addSub(`apm:${this.constructor.name}:middleware:exit`, ({ req }) => {
30
+ const context = this._contexts.get(req)
70
31
 
71
- return wrapCallHandle
72
- }
32
+ if (!context) return
73
33
 
74
- function wrapStack (stack, offset, matchers) {
75
- [].concat(stack).slice(offset).forEach(layer => {
76
- if (layer.__handle) { // express-async-errors
77
- layer.__handle = wrapLayerHandle(layer, layer.__handle)
78
- } else {
79
- layer.handle = wrapLayerHandle(layer, layer.handle)
80
- }
81
-
82
- layerMatchers.set(layer, matchers)
83
-
84
- if (layer.route) {
85
- METHODS.forEach(method => {
86
- if (typeof layer.route.stack === 'function') {
87
- layer.route.stack = [{ handle: layer.route.stack }]
88
- }
34
+ context.stack.pop()
89
35
 
90
- layer.route[method] = wrapRouterMethod(layer.route[method])
91
- })
92
- }
93
- })
94
- }
36
+ if (context.middleware.length > 0) {
37
+ context.middleware.pop().finish()
38
+ }
39
+ })
95
40
 
96
- function wrapNext (layer, req, next) {
97
- if (!next || !web.active(req)) return next
41
+ this.addSub(`apm:${this.constructor.name}:middleware:error`, this.addError)
98
42
 
99
- const originalNext = next
100
- const context = contexts.get(req)
101
- const matchers = layerMatchers.get(layer)
43
+ this.addSub(`apm:http:server:request:finish`, ({ req }) => {
44
+ const context = this._contexts.get(req)
102
45
 
103
- return function (error) {
104
- if (layer.path && !isFastStar(layer, matchers) && !isFastSlash(layer, matchers)) {
105
- context.stack.pop()
106
- }
46
+ if (!context) return
107
47
 
108
- web.finish(req, error)
48
+ let span
109
49
 
110
- originalNext.apply(null, arguments)
50
+ while ((span = context.middleware.pop())) {
51
+ span.finish()
52
+ }
53
+ })
111
54
  }
112
- }
113
-
114
- function callHandle (layer, handle, req, args) {
115
- const matchers = layerMatchers.get(layer)
116
55
 
117
- if (web.active(req) && matchers) {
118
- // Try to guess which path actually matched
119
- for (let i = 0; i < matchers.length; i++) {
120
- if (matchers[i].test(layer)) {
121
- const context = contexts.get(req)
56
+ _getMiddlewareSpan (context, store, name) {
57
+ const childOf = store && store.span
122
58
 
123
- context.stack.push(matchers[i].path)
124
-
125
- const route = context.stack.join('')
126
-
127
- // Longer route is more likely to be the actual route handler route.
128
- if (route.length > context.route.length) {
129
- context.route = route
130
- }
59
+ if (this.config.middleware === false) {
60
+ return childOf
61
+ }
131
62
 
132
- break
63
+ const span = this.tracer.startSpan(`${this.constructor.name}.middleware`, {
64
+ childOf,
65
+ tags: {
66
+ 'resource.name': name || '<anonymous>'
133
67
  }
134
- }
135
- }
68
+ })
136
69
 
137
- return web.wrapMiddleware(req, handle, 'express.middleware', () => {
138
- return handle.apply(layer, args)
139
- })
140
- }
70
+ context.middleware.push(span)
141
71
 
142
- function extractMatchers (fn) {
143
- const arg = flatten([].concat(fn))
72
+ analyticsSampler.sample(span, this.config.measured)
144
73
 
145
- if (typeof arg[0] === 'function') {
146
- return []
74
+ return span
147
75
  }
148
76
 
149
- return arg.map(pattern => ({
150
- path: pattern instanceof RegExp ? `(${pattern})` : pattern,
151
- test: layer => {
152
- const matchers = layerMatchers.get(layer)
77
+ _createContext (req, route) {
78
+ let context = this._contexts.get(req)
153
79
 
154
- return !isFastStar(layer, matchers) &&
155
- !isFastSlash(layer, matchers) &&
156
- cachedPathToRegExp(pattern).test(layer.path)
80
+ if (!route || route === '/' || route === '*') {
81
+ route = ''
157
82
  }
158
- }))
159
- }
160
83
 
161
- function isFastStar (layer, matchers) {
162
- if (layer.regexp.fast_star !== undefined) {
163
- return layer.regexp.fast_star
164
- }
84
+ if (context) {
85
+ context.stack.push(route)
165
86
 
166
- return matchers.some(matcher => matcher.path === '*')
167
- }
87
+ route = context.stack.join('')
168
88
 
169
- function isFastSlash (layer, matchers) {
170
- if (layer.regexp.fast_slash !== undefined) {
171
- return layer.regexp.fast_slash
172
- }
173
-
174
- return matchers.some(matcher => matcher.path === '/')
175
- }
89
+ // Longer route is more likely to be the actual route handler route.
90
+ if (route.length > context.route.length) {
91
+ context.route = route
92
+ }
93
+ } else {
94
+ context = {
95
+ stack: [route],
96
+ route,
97
+ middleware: []
98
+ }
176
99
 
177
- function flatten (arr) {
178
- return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), [])
179
- }
100
+ this._contexts.set(req, context)
101
+ }
180
102
 
181
- function cachedPathToRegExp (pattern) {
182
- const maybeCached = regexpCache[pattern]
183
- if (maybeCached) {
184
- return maybeCached
103
+ return context
185
104
  }
186
- const regexp = pathToRegExp(pattern)
187
- regexpCache[pattern] = regexp
188
- return regexp
189
105
  }
190
106
 
191
- module.exports = {
192
- name: 'router',
193
- versions: ['>=1'],
194
- patch (Router, tracer, config) {
195
- this.wrap(Router.prototype, 'handle', createWrapHandle(tracer, config))
196
- this.wrap(Router.prototype, 'use', wrapRouterMethod)
197
- this.wrap(Router.prototype, 'route', wrapRouterMethod)
198
- },
199
- unpatch (Router) {
200
- this.unwrap(Router.prototype, 'handle')
201
- this.unwrap(Router.prototype, 'use')
202
- this.unwrap(Router.prototype, 'route')
203
- }
204
- }
107
+ module.exports = RouterPlugin
@@ -0,0 +1,20 @@
1
+ 'use strict'
2
+
3
+ const Plugin = require('../../dd-trace/src/plugins/plugin')
4
+ const web = require('../../dd-trace/src/plugins/util/web')
5
+
6
+ class WebPlugin extends Plugin {
7
+ static get name () {
8
+ return 'web'
9
+ }
10
+
11
+ configure (config) {
12
+ return super.configure(web.normalizeConfig(config))
13
+ }
14
+
15
+ setFramework (req, name, config) {
16
+ web.setFramework(req, name, config)
17
+ }
18
+ }
19
+
20
+ module.exports = WebPlugin
@@ -1 +1 @@
1
- module.exports = '2.4.2'
1
+ module.exports = '2.7.0'
@@ -7,16 +7,14 @@ const Reporter = require('../reporter')
7
7
 
8
8
  const validAddressSet = new Set(Object.values(addresses))
9
9
 
10
- const DEFAULT_MAX_BUDGET = 5e3 // µs
11
-
12
10
  // TODO: put reusable code in a base class
13
11
  class WAFCallback {
14
- static loadDDWAF (rules) {
12
+ static loadDDWAF (rules, config) {
15
13
  try {
16
14
  // require in `try/catch` because this can throw at require time
17
15
  const { DDWAF } = require('@datadog/native-appsec')
18
16
 
19
- return new DDWAF(rules)
17
+ return new DDWAF(rules, config)
20
18
  } catch (err) {
21
19
  log.error('AppSec could not load native package. In-app WAF features will not be available.')
22
20
 
@@ -24,8 +22,24 @@ class WAFCallback {
24
22
  }
25
23
  }
26
24
 
27
- constructor (rules) {
28
- this.ddwaf = WAFCallback.loadDDWAF(rules)
25
+ constructor (rules, config) {
26
+ const { wafTimeout, obfuscatorKeyRegex, obfuscatorValueRegex } = config
27
+
28
+ this.ddwaf = WAFCallback.loadDDWAF(rules, { obfuscatorKeyRegex, obfuscatorValueRegex })
29
+
30
+ this.wafTimeout = wafTimeout
31
+
32
+ const version = this.ddwaf.constructor.version()
33
+
34
+ Reporter.metricsQueue.set('_dd.appsec.waf.version', `${version.major}.${version.minor}.${version.patch}`)
35
+
36
+ const { loaded, failed } = this.ddwaf.rulesInfo
37
+
38
+ Reporter.metricsQueue.set('_dd.appsec.event_rules.loaded', loaded)
39
+ Reporter.metricsQueue.set('_dd.appsec.event_rules.error_count', failed)
40
+
41
+ Reporter.metricsQueue.set('manual.keep', true)
42
+
29
43
  this.wafContextCache = new WeakMap()
30
44
 
31
45
  // closures are faster than binds
@@ -70,7 +84,7 @@ class WAFCallback {
70
84
  }
71
85
  }
72
86
 
73
- if (!wafContext) {
87
+ if (!wafContext || wafContext.disposed) {
74
88
  wafContext = this.ddwaf.createContext()
75
89
  }
76
90
 
@@ -81,23 +95,31 @@ class WAFCallback {
81
95
 
82
96
  try {
83
97
  // TODO: possible optimizaion: only send params that haven't already been sent to this wafContext
84
- const result = wafContext.run(params, DEFAULT_MAX_BUDGET)
98
+ const start = process.hrtime.bigint()
99
+
100
+ const result = wafContext.run(params, this.wafTimeout)
101
+
102
+ result.durationExt = parseInt(process.hrtime.bigint() - start)
85
103
 
86
104
  return this.applyResult(result, store)
87
105
  } catch (err) {
88
106
  log.error('Error while running the AppSec WAF')
89
107
  log.error(err)
108
+ } finally {
109
+ wafContext.dispose()
90
110
  }
91
111
  }
92
112
 
93
113
  applyResult (result, store) {
114
+ Reporter.reportMetrics({
115
+ duration: result.totalRuntime / 1e3,
116
+ durationExt: result.durationExt / 1e3,
117
+ rulesVersion: this.ddwaf.rulesInfo.version
118
+ }, store)
119
+
94
120
  if (result.data && result.data !== '[]') {
95
121
  Reporter.reportAttack(result.data, store)
96
122
  }
97
-
98
- // TODO: use these values later for budget management
99
- // result.perfData
100
- // result.perfTotalRuntime
101
123
  }
102
124
 
103
125
  clear () {
@@ -16,7 +16,7 @@ function enable (config) {
16
16
  let rules = fs.readFileSync(config.appsec.rules)
17
17
  rules = JSON.parse(rules)
18
18
 
19
- RuleManager.applyRules(rules)
19
+ RuleManager.applyRules(rules, config.appsec)
20
20
  } catch (err) {
21
21
  log.error('Unable to start AppSec')
22
22
  log.error(err)
@@ -94,12 +94,16 @@ function incomingHttpEndTranslator (data) {
94
94
  }
95
95
 
96
96
  if (data.req.cookies && typeof data.req.cookies === 'object') {
97
- payload[addresses.HTTP_INCOMING_COOKIES] = data.req.cookies
97
+ payload[addresses.HTTP_INCOMING_COOKIES] = {}
98
+
99
+ for (const k of Object.keys(data.req.cookies)) {
100
+ payload[addresses.HTTP_INCOMING_COOKIES][k] = [ data.req.cookies[k] ]
101
+ }
98
102
  }
99
103
 
100
104
  Gateway.propagate(payload, context)
101
105
 
102
- Reporter.finishAttacks(data.req, context)
106
+ Reporter.finishRequest(data.req, context)
103
107
  }
104
108
 
105
109
  function disable () {