@google-cloud/debug-agent
Advanced tools
Comparing version 5.2.3 to 5.2.4
@@ -295,6 +295,6 @@ import { GoogleAuthOptions } from '@google-cloud/common'; | ||
/** | ||
* Number of times of the V8 breakpoint hits events before resetting the | ||
* breakpoints. This is to release the memory usage held by V8 engine for each | ||
* breakpoint hit to prevent the memory leak. The default value is specified | ||
* in defaultConfig. | ||
* Number of times the V8 pauses (could be breakpoint hits) before the | ||
* debugging session is reset. This is to release the memory usage held by V8 | ||
* engine for each breakpoint hit to prevent the memory leak. The default | ||
* value is specified in defaultConfig. | ||
*/ | ||
@@ -301,0 +301,0 @@ resetV8DebuggerThreshold: number; |
@@ -12,21 +12,2 @@ /// <reference types="node" /> | ||
import { V8Inspector } from './v8inspector'; | ||
/** | ||
* An interface that describes options that set behavior when interacting with | ||
* the V8 Inspector API. | ||
*/ | ||
interface InspectorOptions { | ||
/** | ||
* Whether to add a 'file://' prefix to a URL when setting breakpoints. | ||
*/ | ||
useWellFormattedUrl: boolean; | ||
} | ||
/** Data related to the v8 inspector. */ | ||
interface V8Data { | ||
session: inspector.Session; | ||
inspectorOptions: InspectorOptions; | ||
inspector: V8Inspector; | ||
setBreakpointsParams: { | ||
[v8BreakpointId: string]: inspector.Debugger.SetBreakpointByUrlParameterType; | ||
}; | ||
} | ||
export declare class BreakpointData { | ||
@@ -63,7 +44,6 @@ id: inspector.Debugger.BreakpointId; | ||
numBreakpoints: number; | ||
numBreakpointHitsBeforeReset: number; | ||
v8: V8Data; | ||
inspector: V8Inspector; | ||
constructor(logger: consoleLogLevel.Logger, config: ResolvedDebugAgentConfig, jsFiles: ScanStats, sourcemapper: SourceMapper); | ||
/** Creates a new V8 Debugging session and the related data. */ | ||
private createV8Data; | ||
/** Disconnects and marks the current V8 data as not connected. */ | ||
disconnect(): void; | ||
set(breakpoint: stackdriver.Breakpoint, cb: (err: Error | null) => void): void; | ||
@@ -73,3 +53,2 @@ clear(breakpoint: stackdriver.Breakpoint, cb: (err: Error | null) => void): void; | ||
log(breakpoint: stackdriver.Breakpoint, print: (format: string, exps: string[]) => void, shouldStop: () => boolean): void; | ||
disconnect(): void; | ||
numBreakpoints_(): number; | ||
@@ -93,8 +72,2 @@ numListeners_(): number; | ||
private handleDebugPausedEvent; | ||
/** | ||
* Periodically resets breakpoints to prevent memory leaks in V8 (for holding | ||
* contexts of previous breakpoint hits). | ||
*/ | ||
private tryResetV8Debugger; | ||
} | ||
export {}; |
@@ -18,4 +18,2 @@ "use strict"; | ||
const acorn = require("acorn"); | ||
// eslint-disable-next-line node/no-unsupported-features/node-builtins | ||
const inspector = require("inspector"); | ||
const path = require("path"); | ||
@@ -60,3 +58,2 @@ const status_message_1 = require("../../client/stackdriver/status-message"); | ||
this.numBreakpoints = 0; | ||
this.numBreakpointHitsBeforeReset = 0; | ||
this.logger = logger; | ||
@@ -66,17 +63,14 @@ this.config = config; | ||
this.sourcemapper = sourcemapper; | ||
this.scriptMapper = {}; | ||
this.v8 = this.createV8Data(); | ||
} | ||
/** Creates a new V8 Debugging session and the related data. */ | ||
createV8Data() { | ||
const session = new inspector.Session(); | ||
session.connect(); | ||
session.on('Debugger.scriptParsed', script => { | ||
this.scriptMapper[script.params.scriptId] = script.params; | ||
}); | ||
session.post('Debugger.enable'); | ||
session.post('Debugger.setBreakpointsActive', { active: true }); | ||
session.on('Debugger.paused', message => { | ||
this.inspector = new v8inspector_1.V8Inspector( | ||
/* logger=*/ logger, | ||
/*useWellFormattedUrl=*/ utils.satisfies(process.version, '>10.11.0'), | ||
/*resetV8DebuggerThreshold=*/ this.config.resetV8DebuggerThreshold, | ||
/*onScriptParsed=*/ | ||
scriptParams => { | ||
this.scriptMapper[scriptParams.scriptId] = scriptParams; | ||
}, | ||
/*onPaused=*/ | ||
messageParams => { | ||
try { | ||
this.handleDebugPausedEvent(message.params); | ||
this.handleDebugPausedEvent(messageParams); | ||
} | ||
@@ -87,12 +81,7 @@ catch (error) { | ||
}); | ||
return { | ||
session, | ||
inspectorOptions: { | ||
// Well-Formatted URL is required in Node 10.11.1+. | ||
useWellFormattedUrl: utils.satisfies(process.version, '>10.11.0'), | ||
}, | ||
inspector: new v8inspector_1.V8Inspector(session), | ||
setBreakpointsParams: {}, | ||
}; | ||
} | ||
/** Disconnects and marks the current V8 data as not connected. */ | ||
disconnect() { | ||
this.inspector.detach(); | ||
} | ||
set(breakpoint, cb) { | ||
@@ -167,4 +156,3 @@ if (!breakpoint || | ||
// id, we should remove this breakpoint from v8. | ||
result = this.v8.inspector.removeBreakpoint(breakpointData.id); | ||
delete this.v8.setBreakpointsParams[breakpointData.id]; | ||
result = this.inspector.removeBreakpoint(breakpointData.id); | ||
} | ||
@@ -229,5 +217,2 @@ delete this.breakpoints[breakpoint.id]; | ||
} | ||
disconnect() { | ||
this.v8.session.disconnect(); | ||
} | ||
numBreakpoints_() { | ||
@@ -350,3 +335,3 @@ // Tracks the number of stackdriver breakpoints. | ||
// The first time when a breakpoint was set to this location. | ||
const rawUrl = this.v8.inspectorOptions.useWellFormattedUrl | ||
const rawUrl = this.inspector.shouldUseWellFormattedUrl() | ||
? `file://${matchingScript}` | ||
@@ -359,3 +344,3 @@ : matchingScript; | ||
: rawUrl; | ||
const params = { | ||
const res = this.inspector.setBreakpointByUrl({ | ||
lineNumber: line - 1, | ||
@@ -365,4 +350,3 @@ url, | ||
condition: breakpoint.condition || undefined, | ||
}; | ||
const res = this.v8.inspector.setBreakpointByUrl(params); | ||
}); | ||
if (res.error || !res.response) { | ||
@@ -373,3 +357,2 @@ // Error case. | ||
v8BreakpointId = res.response.breakpointId; | ||
this.v8.setBreakpointsParams[v8BreakpointId] = params; | ||
this.locationMapper[locationStr] = []; | ||
@@ -439,3 +422,3 @@ this.breakpointMapper[v8BreakpointId] = []; | ||
// value will be returned to log. | ||
const result = state.evaluate(exp, frame, that.v8.inspector, true); | ||
const result = state.evaluate(exp, frame, that.inspector, true); | ||
if (result.error) { | ||
@@ -452,3 +435,3 @@ return result.error; | ||
else { | ||
const captured = state.capture(callFrames, breakpoint, this.config, this.scriptMapper, this.v8.inspector); | ||
const captured = state.capture(callFrames, breakpoint, this.config, this.scriptMapper, this.inspector); | ||
if (breakpoint.location && | ||
@@ -481,30 +464,5 @@ utils.isJavaScriptFile(breakpoint.location.path)) { | ||
} | ||
this.tryResetV8Debugger(); | ||
} | ||
/** | ||
* Periodically resets breakpoints to prevent memory leaks in V8 (for holding | ||
* contexts of previous breakpoint hits). | ||
*/ | ||
tryResetV8Debugger() { | ||
this.numBreakpointHitsBeforeReset += 1; | ||
if (this.numBreakpointHitsBeforeReset < this.config.resetV8DebuggerThreshold) { | ||
return; | ||
} | ||
this.numBreakpointHitsBeforeReset = 0; | ||
const storedParams = this.v8.setBreakpointsParams; | ||
// Re-connect the session to clean the memory usage. | ||
this.disconnect(); | ||
this.scriptMapper = {}; | ||
this.v8 = this.createV8Data(); | ||
this.v8.setBreakpointsParams = storedParams; | ||
// Setting the v8 breakpoints again according to the stored parameters. | ||
for (const params of Object.values(storedParams)) { | ||
const res = this.v8.inspector.setBreakpointByUrl(params); | ||
if (res.error || !res.response) { | ||
this.logger.error('Error upon re-setting breakpoint: ' + res); | ||
} | ||
} | ||
} | ||
} | ||
exports.InspectorDebugApi = InspectorDebugApi; | ||
//# sourceMappingURL=inspector-debugapi.js.map |
/// <reference types="node" /> | ||
import * as inspector from 'inspector'; | ||
import consoleLogLevel = require('console-log-level'); | ||
export declare class V8Inspector { | ||
private session; | ||
constructor(session: inspector.Session); | ||
setBreakpointByUrl(options: inspector.Debugger.SetBreakpointByUrlParameterType): { | ||
readonly logger: consoleLogLevel.Logger; | ||
readonly useWellFormattedUrl: boolean; | ||
readonly resetV8DebuggerThreshold: number; | ||
readonly onScriptParsed: (script: inspector.Debugger.ScriptParsedEventDataType) => void; | ||
readonly onPaused: (params: inspector.Debugger.PausedEventDataType) => void; | ||
session: inspector.Session | null; | ||
storeSetBreakpointParams: { | ||
[v8BreakpointId: string]: inspector.Debugger.SetBreakpointByUrlParameterType; | ||
}; | ||
numPausedBeforeReset: number; | ||
constructor(logger: consoleLogLevel.Logger, useWellFormattedUrl: boolean, resetV8DebuggerThreshold: number, onScriptParsed: (script: inspector.Debugger.ScriptParsedEventDataType) => void, onPaused: (params: inspector.Debugger.PausedEventDataType) => void); | ||
/** | ||
* Whether to add a 'file://' prefix to a URL when setting breakpoints. | ||
*/ | ||
shouldUseWellFormattedUrl(): boolean; | ||
setBreakpointByUrl(params: inspector.Debugger.SetBreakpointByUrlParameterType): { | ||
error?: Error | undefined; | ||
@@ -21,2 +35,15 @@ response?: inspector.Debugger.SetBreakpointByUrlReturnType | undefined; | ||
}; | ||
/** Attaches to the V8 debugger. */ | ||
private attach; | ||
/** | ||
* Detaches from the V8 debugger. This will purge all the existing V8 | ||
* breakpoints from the V8 debugger. | ||
*/ | ||
detach(): void; | ||
/** | ||
* Resets the debugging session when the number of paused events meets the | ||
* threshold. This is primarily for cleaning the memory usage hold by V8 | ||
* debugger when hitting the V8 breakpoints too many times. | ||
*/ | ||
private resetV8DebuggerIfThresholdMet; | ||
} |
@@ -17,11 +17,35 @@ "use strict"; | ||
exports.V8Inspector = void 0; | ||
// eslint-disable-next-line node/no-unsupported-features/node-builtins | ||
const inspector = require("inspector"); | ||
class V8Inspector { | ||
constructor(session) { | ||
this.session = session; | ||
constructor(logger, useWellFormattedUrl, resetV8DebuggerThreshold, onScriptParsed, onPaused) { | ||
this.logger = logger; | ||
this.useWellFormattedUrl = useWellFormattedUrl; | ||
this.resetV8DebuggerThreshold = resetV8DebuggerThreshold; | ||
this.onScriptParsed = onScriptParsed; | ||
this.onPaused = onPaused; | ||
// The V8 debugger session. | ||
this.session = null; | ||
// Store of the v8 setBreakpoint parameters for each v8 breakpoint so that | ||
// later the recorded parameters can be used to reset the breakpoints. | ||
this.storeSetBreakpointParams = {}; | ||
// Number of paused events before the next reset. | ||
this.numPausedBeforeReset = 0; | ||
} | ||
setBreakpointByUrl(options) { | ||
/** | ||
* Whether to add a 'file://' prefix to a URL when setting breakpoints. | ||
*/ | ||
shouldUseWellFormattedUrl() { | ||
return this.useWellFormattedUrl; | ||
} | ||
setBreakpointByUrl(params) { | ||
this.attach(); | ||
const result = {}; | ||
this.session.post('Debugger.setBreakpointByUrl', options, (error, response) => { | ||
if (error) | ||
this.session.post('Debugger.setBreakpointByUrl', params, (error, response) => { | ||
if (error) { | ||
result.error = error; | ||
} | ||
else { | ||
this.storeSetBreakpointParams[response.breakpointId] = params; | ||
} | ||
result.response = response; | ||
@@ -32,6 +56,15 @@ }); | ||
removeBreakpoint(breakpointId) { | ||
this.attach(); | ||
const result = {}; | ||
this.session.post('Debugger.removeBreakpoint', { breakpointId }, (error) => { | ||
if (error) | ||
if (error) { | ||
result.error = error; | ||
} | ||
else { | ||
delete this.storeSetBreakpointParams[breakpointId]; | ||
} | ||
// If there is no active V8 breakpoints, then detach the session. | ||
if (Object.keys(this.storeSetBreakpointParams).length === 0) { | ||
this.detach(); | ||
} | ||
}); | ||
@@ -41,2 +74,3 @@ return result; | ||
evaluateOnCallFrame(options) { | ||
this.attach(); | ||
const result = {}; | ||
@@ -52,2 +86,3 @@ this.session.post('Debugger.evaluateOnCallFrame', options, (error, response) => { | ||
const result = {}; | ||
this.attach(); | ||
this.session.post('Runtime.getProperties', options, (error, response) => { | ||
@@ -60,4 +95,57 @@ if (error) | ||
} | ||
/** Attaches to the V8 debugger. */ | ||
attach() { | ||
if (this.session) { | ||
return; | ||
} | ||
const session = new inspector.Session(); | ||
session.connect(); | ||
session.on('Debugger.scriptParsed', script => { | ||
this.onScriptParsed(script.params); | ||
}); | ||
session.post('Debugger.enable'); | ||
session.post('Debugger.setBreakpointsActive', { active: true }); | ||
session.on('Debugger.paused', message => { | ||
this.onPaused(message.params); | ||
this.resetV8DebuggerIfThresholdMet(); | ||
}); | ||
this.session = session; | ||
} | ||
/** | ||
* Detaches from the V8 debugger. This will purge all the existing V8 | ||
* breakpoints from the V8 debugger. | ||
*/ | ||
detach() { | ||
if (!this.session) { | ||
return; | ||
} | ||
this.session.disconnect(); | ||
this.session = null; | ||
this.storeSetBreakpointParams = {}; | ||
this.numPausedBeforeReset = 0; | ||
} | ||
/** | ||
* Resets the debugging session when the number of paused events meets the | ||
* threshold. This is primarily for cleaning the memory usage hold by V8 | ||
* debugger when hitting the V8 breakpoints too many times. | ||
*/ | ||
resetV8DebuggerIfThresholdMet() { | ||
this.numPausedBeforeReset += 1; | ||
if (this.numPausedBeforeReset < this.resetV8DebuggerThreshold) { | ||
return; | ||
} | ||
this.numPausedBeforeReset = 0; | ||
const previouslyStoredParams = this.storeSetBreakpointParams; | ||
this.detach(); | ||
this.attach(); | ||
// Setting the v8 breakpoints again according to the stored parameters. | ||
for (const params of Object.values(previouslyStoredParams)) { | ||
const res = this.setBreakpointByUrl(params); | ||
if (res.error || !res.response) { | ||
this.logger.error('Error upon re-setting breakpoint: ' + res); | ||
} | ||
} | ||
} | ||
} | ||
exports.V8Inspector = V8Inspector; | ||
//# sourceMappingURL=v8inspector.js.map |
{ | ||
"name": "@google-cloud/debug-agent", | ||
"version": "5.2.3", | ||
"version": "5.2.4", | ||
"author": "Google Inc.", | ||
@@ -5,0 +5,0 @@ "description": "Stackdriver Debug Agent for Node.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
452378
5819