@google-cloud/profiler
Advanced tools
Comparing version 0.2.3 to 1.0.0
@@ -40,2 +40,4 @@ /** | ||
localTimeDurationMillis?: number; | ||
sourceMapSearchPath?: string[]; | ||
disableSourceMaps?: boolean; | ||
} | ||
@@ -65,2 +67,4 @@ export interface ProfilerConfig extends GoogleAuthOptions { | ||
localTimeDurationMillis: number; | ||
sourceMapSearchPath: string[]; | ||
disableSourceMaps: boolean; | ||
} | ||
@@ -84,2 +88,4 @@ export declare const defaultConfig: { | ||
localTimeDurationMillis: number; | ||
sourceMapSearchPath: string[]; | ||
disableSourceMaps: boolean; | ||
}; |
@@ -39,4 +39,6 @@ "use strict"; | ||
localLogPeriodMillis: 10000, | ||
localTimeDurationMillis: 1000 | ||
localTimeDurationMillis: 1000, | ||
sourceMapSearchPath: [process.cwd()], | ||
disableSourceMaps: false, | ||
}; | ||
//# sourceMappingURL=config.js.map |
@@ -87,3 +87,10 @@ "use strict"; | ||
} | ||
const mergedConfig = extend(true, {}, config_1.defaultConfig, envSetConfig, envConfig, config); | ||
const mergedUserConfigs = extend(true, {}, envSetConfig, envConfig, config); | ||
if (Array.isArray(mergedUserConfigs.sourceMapSearchPath) && | ||
mergedUserConfigs.sourceMapSearchPath.length === 0 && | ||
!mergedUserConfigs.disableSourceMaps) { | ||
throw new Error('serviceMapSearchPath is an empty array. Use disableSourceMaps to' + | ||
' disable source map support instead.'); | ||
} | ||
const mergedConfig = extend(true, {}, config_1.defaultConfig, mergedUserConfigs); | ||
if (!hasService(mergedConfig)) { | ||
@@ -90,0 +97,0 @@ throw new Error('Service must be specified in the configuration'); |
@@ -86,2 +86,3 @@ /** | ||
private retryer; | ||
private sourceMapper; | ||
timeProfiler: TimeProfiler | undefined; | ||
@@ -100,3 +101,3 @@ config: ProfilerConfig; | ||
*/ | ||
start(): void; | ||
start(): Promise<void>; | ||
/** | ||
@@ -103,0 +104,0 @@ * Endlessly polls the profiler server for instructions, and collects and |
@@ -35,2 +35,3 @@ "use strict"; | ||
const time_profiler_1 = require("./profilers/time-profiler"); | ||
const sourcemapper_1 = require("./sourcemapper/sourcemapper"); | ||
const parseDuration = require('parse-duration'); | ||
@@ -261,3 +262,15 @@ const pjson = require('../../package.json'); | ||
start() { | ||
this.runLoop(); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!this.config.disableSourceMaps) { | ||
try { | ||
this.sourceMapper = | ||
yield sourcemapper_1.create(this.config.sourceMapSearchPath); | ||
} | ||
catch (err) { | ||
this.logger.error(`Failed to initialize source maps and start profiler: ${err}`); | ||
return; | ||
} | ||
} | ||
this.runLoop(); | ||
}); | ||
} | ||
@@ -430,3 +443,3 @@ /** | ||
} | ||
const p = yield this.timeProfiler.profile(durationMillis); | ||
const p = yield this.timeProfiler.profile(durationMillis, this.sourceMapper); | ||
prof.profileBytes = yield profileBytes(p); | ||
@@ -447,3 +460,3 @@ return prof; | ||
} | ||
const p = heapProfiler.profile(); | ||
const p = heapProfiler.profile(this.config.ignoreHeapSamplesPath, this.sourceMapper); | ||
prof.profileBytes = yield profileBytes(p); | ||
@@ -450,0 +463,0 @@ return prof; |
@@ -17,3 +17,4 @@ /** | ||
import { perftools } from '../../../proto/profile'; | ||
export declare function profile(ignoreSamplePath?: string): perftools.profiles.IProfile; | ||
import { SourceMapper } from '../sourcemapper/sourcemapper'; | ||
export declare function profile(ignoreSamplePath?: string, sourceMapper?: SourceMapper): perftools.profiles.IProfile; | ||
/** | ||
@@ -20,0 +21,0 @@ * Starts heap profiling. If heap profiling has already been started with |
@@ -18,4 +18,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const heap_profiler_bindings_1 = require("./heap-profiler-bindings"); | ||
const profile_serializer_1 = require("./profile-serializer"); | ||
const profiler = require('bindings')('sampling_heap_profiler'); | ||
let enabled = false; | ||
@@ -28,3 +28,3 @@ let heapIntervalBytes = 0; | ||
*/ | ||
function profile(ignoreSamplePath) { | ||
function profile(ignoreSamplePath, sourceMapper) { | ||
if (!enabled) { | ||
@@ -34,3 +34,3 @@ throw new Error('Heap profiler is not enabled.'); | ||
const startTimeNanos = Date.now() * 1000 * 1000; | ||
const result = profiler.getAllocationProfile(); | ||
const result = heap_profiler_bindings_1.getAllocationProfile(); | ||
// Add node for external memory usage. | ||
@@ -50,3 +50,3 @@ // Current type definitions do not have external. | ||
} | ||
return profile_serializer_1.serializeHeapProfile(result, startTimeNanos, heapIntervalBytes, ignoreSamplePath); | ||
return profile_serializer_1.serializeHeapProfile(result, startTimeNanos, heapIntervalBytes, ignoreSamplePath, sourceMapper); | ||
} | ||
@@ -68,3 +68,3 @@ exports.profile = profile; | ||
heapStackDepth = stackDepth; | ||
profiler.startSamplingHeapProfiler(heapIntervalBytes, heapStackDepth); | ||
heap_profiler_bindings_1.startSamplingHeapProfiler(heapIntervalBytes, heapStackDepth); | ||
enabled = true; | ||
@@ -77,3 +77,3 @@ } | ||
enabled = false; | ||
profiler.stopSamplingHeapProfiler(); | ||
heap_profiler_bindings_1.stopSamplingHeapProfiler(); | ||
} | ||
@@ -80,0 +80,0 @@ } |
@@ -17,2 +17,3 @@ /** | ||
import { perftools } from '../../../proto/profile'; | ||
import { SourceMapper } from '../sourcemapper/sourcemapper'; | ||
import { AllocationProfileNode, TimeProfile } from '../v8-types'; | ||
@@ -26,3 +27,3 @@ /** | ||
*/ | ||
export declare function serializeTimeProfile(prof: TimeProfile, intervalMicros: number): perftools.profiles.IProfile; | ||
export declare function serializeTimeProfile(prof: TimeProfile, intervalMicros: number, sourceMapper?: SourceMapper): perftools.profiles.IProfile; | ||
/** | ||
@@ -38,2 +39,2 @@ * Converts v8 heap profile into into a profile proto. | ||
*/ | ||
export declare function serializeHeapProfile(prof: AllocationProfileNode, startTimeNanos: number, intervalBytes: number, ignoreSamplesPath?: string): perftools.profiles.IProfile; | ||
export declare function serializeHeapProfile(prof: AllocationProfileNode, startTimeNanos: number, intervalBytes: number, ignoreSamplesPath?: string, sourceMapper?: SourceMapper): perftools.profiles.IProfile; |
@@ -19,2 +19,6 @@ "use strict"; | ||
const profile_1 = require("../../../proto/profile"); | ||
function isGeneratedLocation(location) { | ||
return location.column !== undefined && location.line !== undefined && | ||
location.line > 0; | ||
} | ||
/** | ||
@@ -56,3 +60,3 @@ * Used to build string table and access strings and their ids within the table | ||
*/ | ||
function serialize(profile, root, appendToSamples, stringTable, ignoreSamplesPath) { | ||
function serialize(profile, root, appendToSamples, stringTable, ignoreSamplesPath, sourceMapper) { | ||
const samples = []; | ||
@@ -73,3 +77,3 @@ const locations = []; | ||
const stack = entry.stack; | ||
const location = getLocation(node); | ||
const location = getLocation(node, sourceMapper); | ||
stack.unshift(location.id); | ||
@@ -85,4 +89,15 @@ appendToSamples(entry, samples); | ||
profile.stringTable = stringTable.strings; | ||
function getLocation(node) { | ||
const keyStr = `${node.scriptId}:${node.lineNumber}:${node.columnNumber}:${node.name}`; | ||
function getLocation(node, sourceMapper) { | ||
let profLoc = { | ||
file: node.scriptName || '', | ||
line: node.lineNumber, | ||
column: node.columnNumber, | ||
name: node.name | ||
}; | ||
if (profLoc.line) { | ||
if (sourceMapper && isGeneratedLocation(profLoc)) { | ||
profLoc = sourceMapper.mappingInfo(profLoc); | ||
} | ||
} | ||
const keyStr = `${node.scriptId}:${profLoc.line}:${profLoc.column}:${profLoc.name}`; | ||
let id = locationIdMap.get(keyStr); | ||
@@ -95,14 +110,15 @@ if (id !== undefined) { | ||
locationIdMap.set(keyStr, id); | ||
const location = new profile_1.perftools.profiles.Location({ id, line: [getLine(node)] }); | ||
const line = getLine(node.scriptId, profLoc.file, profLoc.name, profLoc.line); | ||
const location = new profile_1.perftools.profiles.Location({ id, line: [line] }); | ||
locations.push(location); | ||
return location; | ||
} | ||
function getLine(node) { | ||
function getLine(scriptId, scriptName, name, line) { | ||
return new profile_1.perftools.profiles.Line({ | ||
functionId: getFunction(node).id, | ||
line: node.lineNumber, | ||
functionId: getFunction(scriptId, scriptName, name).id, | ||
line, | ||
}); | ||
} | ||
function getFunction(node) { | ||
const keyStr = `${node.scriptId}:${node.name}`; | ||
function getFunction(scriptId, scriptName, name) { | ||
const keyStr = `${scriptId}:${name}`; | ||
let id = functionIdMap.get(keyStr); | ||
@@ -115,3 +131,3 @@ if (id !== undefined) { | ||
functionIdMap.set(keyStr, id); | ||
const nameId = stringTable.getIndexOrAdd(node.name || '(anonymous)'); | ||
const nameId = stringTable.getIndexOrAdd(name || '(anonymous)'); | ||
const f = new profile_1.perftools.profiles.Function({ | ||
@@ -121,3 +137,3 @@ id, | ||
systemName: nameId, | ||
filename: stringTable.getIndexOrAdd(node.scriptName) | ||
filename: stringTable.getIndexOrAdd(scriptName || '') | ||
}); | ||
@@ -172,3 +188,3 @@ functions.push(f); | ||
*/ | ||
function serializeTimeProfile(prof, intervalMicros) { | ||
function serializeTimeProfile(prof, intervalMicros, sourceMapper) { | ||
const appendTimeEntryToSamples = (entry, samples) => { | ||
@@ -193,3 +209,3 @@ if (entry.node.hitCount > 0) { | ||
}; | ||
serialize(profile, prof.topDownRoot, appendTimeEntryToSamples, stringTable); | ||
serialize(profile, prof.topDownRoot, appendTimeEntryToSamples, stringTable, undefined, sourceMapper); | ||
return profile; | ||
@@ -208,3 +224,3 @@ } | ||
*/ | ||
function serializeHeapProfile(prof, startTimeNanos, intervalBytes, ignoreSamplesPath) { | ||
function serializeHeapProfile(prof, startTimeNanos, intervalBytes, ignoreSamplesPath, sourceMapper) { | ||
const appendHeapEntryToSamples = (entry, samples) => { | ||
@@ -231,3 +247,3 @@ if (entry.node.allocations.length > 0) { | ||
}; | ||
serialize(profile, prof, appendHeapEntryToSamples, stringTable, ignoreSamplesPath); | ||
serialize(profile, prof, appendHeapEntryToSamples, stringTable, ignoreSamplesPath, sourceMapper); | ||
return profile; | ||
@@ -234,0 +250,0 @@ } |
@@ -17,2 +17,3 @@ /** | ||
import { perftools } from '../../../proto/profile'; | ||
import { SourceMapper } from '../sourcemapper/sourcemapper'; | ||
export declare class TimeProfiler { | ||
@@ -29,3 +30,3 @@ private intervalMicros; | ||
*/ | ||
profile(durationMillis: number): Promise<perftools.profiles.IProfile>; | ||
profile(durationMillis: number, sourceMapper?: SourceMapper): Promise<perftools.profiles.IProfile>; | ||
} |
@@ -28,3 +28,3 @@ "use strict"; | ||
const profile_serializer_1 = require("./profile-serializer"); | ||
const profiler = require('bindings')('time_profiler'); | ||
const time_profiler_bindings_1 = require("./time-profiler-bindings"); | ||
class TimeProfiler { | ||
@@ -36,3 +36,3 @@ /** | ||
this.intervalMicros = intervalMicros; | ||
profiler.setSamplingInterval(this.intervalMicros); | ||
time_profiler_bindings_1.setSamplingInterval(this.intervalMicros); | ||
} | ||
@@ -44,3 +44,3 @@ /** | ||
*/ | ||
profile(durationMillis) { | ||
profile(durationMillis, sourceMapper) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -55,8 +55,8 @@ // Node.js contains an undocumented API for reporting idle status to V8. | ||
const runName = 'stackdriver-profiler-' + Date.now() + '-' + Math.random(); | ||
profiler.startProfiling(runName); | ||
time_profiler_bindings_1.startProfiling(runName); | ||
yield delay_1.default(durationMillis); | ||
const result = profiler.stopProfiling(runName); | ||
const result = time_profiler_bindings_1.stopProfiling(runName); | ||
// tslint:disable-next-line no-any | ||
process._stopProfilerIdleNotifier(); | ||
const profile = profile_serializer_1.serializeTimeProfile(result, this.intervalMicros); | ||
const profile = profile_serializer_1.serializeTimeProfile(result, this.intervalMicros, sourceMapper); | ||
return profile; | ||
@@ -63,0 +63,0 @@ }); |
{ | ||
"name": "@google-cloud/profiler", | ||
"version": "0.2.3", | ||
"description": "Adds support for Stackdriver Profiler to node.js applications", | ||
"version": "1.0.0", | ||
"description": "Adds support for Stackdriver Profiler to Node.js applications", | ||
"repository": "googleapis/cloud-profiler-nodejs", | ||
@@ -9,4 +9,6 @@ "main": "out/src/index.js", | ||
"scripts": { | ||
"install": "node-gyp rebuild", | ||
"test": "nyc mocha out/test/test-*.js && nyc --no-clean mocha out/system-test/test-*.js --timeout=60000", | ||
"install": "node-pre-gyp install --build-from-source", | ||
"test": "nyc mocha out/test/test-*.js", | ||
"system-test": "nyc --no-clean mocha out/system-test/test-*.js --timeout=60000", | ||
"samples-test": "echo 'no sample tests'", | ||
"check": "gts check", | ||
@@ -17,2 +19,4 @@ "clean": "gts clean", | ||
"fix": "gts fix", | ||
"lint": "gts check", | ||
"docs": "echo 'no docs yet'", | ||
"prepare": "npm run compile", | ||
@@ -31,3 +35,3 @@ "pretest": "npm run compile", | ||
"dependencies": { | ||
"@google-cloud/common": "^0.26.0", | ||
"@google-cloud/common": "^0.27.0", | ||
"@types/console-log-level": "^1.4.0", | ||
@@ -39,4 +43,8 @@ "@types/semver": "^5.5.0", | ||
"extend": "^3.0.1", | ||
"findit2": "^2.2.3", | ||
"gcp-metadata": "^0.9.0", | ||
"nan": "^2.11.1", | ||
"lodash.pickby": "^4.6.0", | ||
"nan": "^2.12.0", | ||
"node-pre-gyp": "^0.12.0", | ||
"p-limit": "^2.0.0", | ||
"parse-duration": "^0.1.1", | ||
@@ -46,3 +54,5 @@ "pify": "^4.0.0", | ||
"protobufjs": "~6.8.6", | ||
"semver": "^5.5.0", | ||
"semver": "^5.5.1", | ||
"source-map": "^0.6.1", | ||
"split": "^1.0.1", | ||
"teeny-request": "^3.3.0" | ||
@@ -52,2 +62,3 @@ }, | ||
"@types/extend": "^3.0.0", | ||
"@types/lodash.pickby": "^4.6.4", | ||
"@types/long": "^4.0.0", | ||
@@ -57,6 +68,8 @@ "@types/mocha": "^5.0.0", | ||
"@types/node": "^10.0.3", | ||
"@types/p-limit": "^2.0.0", | ||
"@types/pify": "^3.0.0", | ||
"@types/pretty-ms": "^3.0.0", | ||
"@types/pretty-ms": "^4.0.0", | ||
"@types/request": "^2.47.1", | ||
"@types/sinon": "5.0.5", | ||
"@types/sinon": "^7.0.3", | ||
"@types/tmp": "0.0.33", | ||
"codecov": "^3.0.0", | ||
@@ -72,8 +85,9 @@ "deep-copy": "^1.4.2", | ||
"source-map-support": "^0.5.6", | ||
"tmp": "0.0.33", | ||
"ts-mockito": "^2.2.5", | ||
"typescript": "~3.1.4" | ||
"typescript": "~3.2.0" | ||
}, | ||
"files": [ | ||
"out/src", | ||
"out/third_party/types", | ||
"out/third_party/cloud-debug-nodejs", | ||
"bindings", | ||
@@ -95,3 +109,9 @@ "proto", | ||
"node": ">=6.12.3 <8.0.0 || >=8.9.4 <10.0.0 || >=10.4.1" | ||
}, | ||
"binary": { | ||
"module_name": "google_cloud_profiler", | ||
"module_path": "./build/{node_abi}-{platform}-{arch}-{libc}", | ||
"host": "https://storage.googleapis.com/cloud-profiler-e2e/cprof-e2e-artifacts/nodejs/release", | ||
"package_name": "{node_abi}-{platform}-{arch}-{libc}.tar.gz" | ||
} | ||
} |
@@ -277,2 +277,2 @@ # Google Cloud Profiler | ||
[snyk-image]: https://snyk.io/test/github/GoogleCloudPlatform/cloud-profiler-nodejs/badge.svg | ||
[snyk-url]: https://snyk.io/test/github/GoogleCloudPlatform/cloud-profiler-nodejs | ||
[snyk-url]: https://snyk.io/test/github/GoogleCloudPlatform/cloud-profiler-nodejs |
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 not supported yet
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 not supported yet
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
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1229321
47
23652
1
278
21
25
1
12
+ Addedfindit2@^2.2.3
+ Addedlodash.pickby@^4.6.0
+ Addednode-pre-gyp@^0.12.0
+ Addedp-limit@^2.0.0
+ Addedsource-map@^0.6.1
+ Addedsplit@^1.0.1
+ Added@google-cloud/common@0.27.0(transitive)
+ Addedabbrev@1.1.1(transitive)
+ Addedansi-regex@2.1.1(transitive)
+ Addedaproba@1.2.0(transitive)
+ Addedare-we-there-yet@1.1.7(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedchownr@1.1.4(transitive)
+ Addedcode-point-at@1.1.0(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedconsole-control-strings@1.1.0(transitive)
+ Addeddebug@3.2.7(transitive)
+ Addeddeep-extend@0.6.0(transitive)
+ Addeddelegates@1.0.0(transitive)
+ Addeddetect-libc@1.0.3(transitive)
+ Addedfindit2@2.2.3(transitive)
+ Addedfs-minipass@1.2.7(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedgauge@2.7.4(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedhas-unicode@2.0.1(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedignore-walk@3.0.4(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedini@1.3.8(transitive)
+ Addedis-fullwidth-code-point@1.0.0(transitive)
+ Addedlodash.pickby@4.6.0(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedminipass@2.9.0(transitive)
+ Addedminizlib@1.3.3(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedneedle@2.9.1(transitive)
+ Addednode-pre-gyp@0.12.0(transitive)
+ Addednopt@4.0.3(transitive)
+ Addednpm-bundled@1.1.2(transitive)
+ Addednpm-normalize-package-bin@1.0.1(transitive)
+ Addednpm-packlist@1.4.8(transitive)
+ Addednpmlog@4.1.2(transitive)
+ Addednumber-is-nan@1.0.1(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedos-homedir@1.0.2(transitive)
+ Addedos-tmpdir@1.0.2(transitive)
+ Addedosenv@0.1.5(transitive)
+ Addedp-limit@2.3.0(transitive)
+ Addedp-try@2.2.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedrc@1.2.8(transitive)
+ Addedrimraf@2.7.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsax@1.4.1(transitive)
+ Addedset-blocking@2.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedsplit@1.0.1(transitive)
+ Addedstring-width@1.0.2(transitive)
+ Addedstrip-ansi@3.0.1(transitive)
+ Addedstrip-json-comments@2.0.1(transitive)
+ Addedtar@4.4.19(transitive)
+ Addedthrough@2.3.8(transitive)
+ Addedwide-align@1.1.5(transitive)
- Removed@google-cloud/common@0.26.2(transitive)
- Removedthrough2@3.0.2(transitive)
Updated@google-cloud/common@^0.27.0
Updatednan@^2.12.0
Updatedsemver@^5.5.1