@contrast/agentify 1.13.0 → 1.14.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.
- package/lib/heap-snapshots.js +63 -0
- package/lib/index.d.ts +23 -2
- package/lib/index.js +4 -1
- package/lib/rewrite-hooks.js +27 -17
- package/package.json +4 -2
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2023 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
'use strict';
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
const v8 = require('v8');
|
|
21
|
+
|
|
22
|
+
module.exports = function init(core) {
|
|
23
|
+
const {
|
|
24
|
+
config: {
|
|
25
|
+
agent: { heap_dump },
|
|
26
|
+
},
|
|
27
|
+
logger
|
|
28
|
+
} = core;
|
|
29
|
+
|
|
30
|
+
const dir = path.join(process.cwd(), heap_dump.path);
|
|
31
|
+
const ext = '.heapsnapshot';
|
|
32
|
+
|
|
33
|
+
const heapSnapshots = {
|
|
34
|
+
writeHeapSnapshot() {
|
|
35
|
+
const filename = path.format({ name: `${Date.now()}-contrast`, dir, ext });
|
|
36
|
+
logger.info('Writing heap snapshot at %s', filename);
|
|
37
|
+
v8.writeHeapSnapshot(filename);
|
|
38
|
+
},
|
|
39
|
+
async install() {
|
|
40
|
+
if (!heap_dump.enable) return;
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
44
|
+
} catch (err) {
|
|
45
|
+
logger.error({ err }, 'Unable to create snapshot directory. No heap snapshots will be taken.');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setTimeout(() => {
|
|
50
|
+
let count = 0;
|
|
51
|
+
const interval = setInterval(async () => {
|
|
52
|
+
await heapSnapshots.writeHeapSnapshot();
|
|
53
|
+
count++;
|
|
54
|
+
if (count === heap_dump.count) {
|
|
55
|
+
clearInterval(interval);
|
|
56
|
+
}
|
|
57
|
+
}, heap_dump.window_ms).unref();
|
|
58
|
+
}, heap_dump.delay_ms).unref();
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return core.heapSnapshots = heapSnapshots;
|
|
63
|
+
};
|
package/lib/index.d.ts
CHANGED
|
@@ -13,8 +13,27 @@
|
|
|
13
13
|
* way not consistent with the End User License Agreement.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import
|
|
16
|
+
import { Config } from '@contrast/config';
|
|
17
17
|
import { Logger } from '@contrast/logger';
|
|
18
|
+
import RequireHook from '@contrast/require-hook';
|
|
19
|
+
import { Rewriter } from '@contrast/rewriter';
|
|
20
|
+
|
|
21
|
+
declare module 'module' {
|
|
22
|
+
class Module {
|
|
23
|
+
/**
|
|
24
|
+
* @see https://github.com/nodejs/node/blob/main/lib/internal/modules/cjs/loader.js
|
|
25
|
+
* @param content The source code of the module
|
|
26
|
+
* @param filename The file path of the module
|
|
27
|
+
*/
|
|
28
|
+
_compile(content: string, filename: string);
|
|
29
|
+
}
|
|
30
|
+
export = Module;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare module 'node:module' {
|
|
34
|
+
import Module = require('module');
|
|
35
|
+
export = Module;
|
|
36
|
+
}
|
|
18
37
|
|
|
19
38
|
interface AgentifyOptions {
|
|
20
39
|
install: boolean;
|
|
@@ -41,9 +60,11 @@ export interface Agentify<T> {
|
|
|
41
60
|
(preRunMain: PreRunMain<T>, opts?: AgentifyOptions): Agent<T>;
|
|
42
61
|
}
|
|
43
62
|
|
|
44
|
-
interface Core<T> {
|
|
63
|
+
export interface Core<T> {
|
|
64
|
+
readonly config: Config;
|
|
45
65
|
readonly depHooks: RequireHook;
|
|
46
66
|
readonly logger: Logger;
|
|
67
|
+
readonly rewriter: Rewriter;
|
|
47
68
|
agentify: Agentify<T>;
|
|
48
69
|
}
|
|
49
70
|
|
package/lib/index.js
CHANGED
|
@@ -33,6 +33,7 @@ const defaultOpts = {
|
|
|
33
33
|
'depHooks',
|
|
34
34
|
'routeCoverage',
|
|
35
35
|
'libraryAnalysis',
|
|
36
|
+
'heapSnapshots',
|
|
36
37
|
'rewriteHooks',
|
|
37
38
|
'functionHooks'
|
|
38
39
|
]
|
|
@@ -40,10 +41,12 @@ const defaultOpts = {
|
|
|
40
41
|
|
|
41
42
|
module.exports = function (core) {
|
|
42
43
|
// compose add'l local services
|
|
44
|
+
require('./heap-snapshots')(core);
|
|
43
45
|
require('./sources')(core);
|
|
44
46
|
require('./function-hooks')(core);
|
|
45
47
|
require('./rewrite-hooks')(core);
|
|
46
48
|
|
|
49
|
+
|
|
47
50
|
/**
|
|
48
51
|
* The interface is a function, which when called, will hook runMain
|
|
49
52
|
* @param {function} preRunMain
|
|
@@ -95,7 +98,7 @@ class Agent {
|
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
logger.info('Starting the Contrast agent');
|
|
98
|
-
logger.
|
|
101
|
+
logger.info({ config }, 'Agent configuration');
|
|
99
102
|
|
|
100
103
|
const plugin = await opts.preRunMain(core);
|
|
101
104
|
|
package/lib/rewrite-hooks.js
CHANGED
|
@@ -12,22 +12,33 @@
|
|
|
12
12
|
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
13
|
* way not consistent with the End User License Agreement.
|
|
14
14
|
*/
|
|
15
|
+
// @ts-check
|
|
15
16
|
|
|
16
17
|
'use strict';
|
|
17
18
|
|
|
18
19
|
const Module = require('module');
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
/**
|
|
22
|
+
* @param {import('.').Core & {
|
|
23
|
+
* rewriteHooks?: import('@contrast/common').Installable;
|
|
24
|
+
* }} core;
|
|
25
|
+
* @returns {import('@contrast/common').Installable}
|
|
26
|
+
*/
|
|
27
|
+
module.exports = function init(core) {
|
|
28
|
+
const { _compile } = Module.prototype;
|
|
24
29
|
|
|
30
|
+
core.rewriteHooks = {
|
|
25
31
|
install() {
|
|
26
|
-
if (!
|
|
32
|
+
if (!core.config.agent.node.enable_rewrite) return;
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
/**
|
|
35
|
+
* @see https://github.com/nodejs/node/blob/main/lib/internal/modules/cjs/loader.js
|
|
36
|
+
* @param {string} content The source code of the module
|
|
37
|
+
* @param {string} filename The file path of the module
|
|
38
|
+
*/
|
|
39
|
+
Module.prototype._compile = function (content, filename) {
|
|
40
|
+
let result;
|
|
41
|
+
const { code } = core.rewriter.rewrite(content, {
|
|
31
42
|
filename,
|
|
32
43
|
isModule: false,
|
|
33
44
|
inject: true,
|
|
@@ -35,25 +46,24 @@ module.exports = function(deps) {
|
|
|
35
46
|
});
|
|
36
47
|
|
|
37
48
|
try {
|
|
38
|
-
|
|
49
|
+
result = _compile.call(this, code, filename);
|
|
39
50
|
} catch (err) {
|
|
40
|
-
|
|
51
|
+
core.logger.warn(
|
|
41
52
|
{ err },
|
|
42
|
-
'Failed to compile rewritten code for %s,
|
|
53
|
+
'Failed to compile rewritten code for %s, compiling original code.',
|
|
43
54
|
filename,
|
|
44
|
-
code
|
|
45
55
|
);
|
|
46
|
-
|
|
56
|
+
result = _compile.call(this, content, filename);
|
|
47
57
|
}
|
|
48
58
|
|
|
49
|
-
return
|
|
59
|
+
return result;
|
|
50
60
|
};
|
|
51
61
|
},
|
|
52
62
|
|
|
53
|
-
|
|
54
|
-
Module.prototype._compile =
|
|
63
|
+
uninstall() {
|
|
64
|
+
Module.prototype._compile = _compile;
|
|
55
65
|
}
|
|
56
66
|
};
|
|
57
67
|
|
|
58
|
-
return
|
|
68
|
+
return core.rewriteHooks;
|
|
59
69
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/agentify",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Configures Contrast agent services and instrumentation within an application",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
"test": "../scripts/test.sh"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@contrast/common": "1.15.
|
|
20
|
+
"@contrast/common": "1.15.1",
|
|
21
|
+
"@contrast/config": "1.19.0",
|
|
22
|
+
"@contrast/logger": "1.6.0"
|
|
21
23
|
}
|
|
22
24
|
}
|