@datadog/pprof
Advanced tools
Comparing version 5.0.0-pre-56cf286 to 5.0.0-pre-d624748
@@ -18,3 +18,3 @@ /** | ||
import { SourceMapper } from './sourcemapper/sourcemapper'; | ||
import { AllocationProfileNode, LabelSet } from './v8-types'; | ||
import { AllocationProfileNode, GenerateAllocationLabelsFunction } from './v8-types'; | ||
export declare function v8Profile(): AllocationProfileNode; | ||
@@ -28,4 +28,4 @@ /** | ||
*/ | ||
export declare function profile(ignoreSamplePath?: string, sourceMapper?: SourceMapper, generateLabels?: (node: AllocationProfileNode) => LabelSet): Profile; | ||
export declare function convertProfile(rootNode: AllocationProfileNode, ignoreSamplePath?: string, sourceMapper?: SourceMapper, generateLabels?: (node: AllocationProfileNode) => LabelSet): Profile; | ||
export declare function profile(ignoreSamplePath?: string, sourceMapper?: SourceMapper, generateLabels?: GenerateAllocationLabelsFunction): Profile; | ||
export declare function convertProfile(rootNode: AllocationProfileNode, ignoreSamplePath?: string, sourceMapper?: SourceMapper, generateLabels?: GenerateAllocationLabelsFunction): Profile; | ||
/** | ||
@@ -32,0 +32,0 @@ * Starts heap profiling. If heap profiling has already been started with |
@@ -12,2 +12,3 @@ import * as heapProfiler from './heap-profiler'; | ||
stop: typeof timeProfiler.stop; | ||
getContext: typeof timeProfiler.getContext; | ||
setContext: typeof timeProfiler.setContext; | ||
@@ -19,2 +20,3 @@ isStarted: typeof timeProfiler.isStarted; | ||
kSampleCount: any; | ||
NON_JS_THREADS_FUNCTION_NAME: string; | ||
}; | ||
@@ -21,0 +23,0 @@ }; |
@@ -59,2 +59,3 @@ "use strict"; | ||
stop: timeProfiler.stop, | ||
getContext: timeProfiler.getContext, | ||
setContext: timeProfiler.setContext, | ||
@@ -61,0 +62,0 @@ isStarted: timeProfiler.isStarted, |
@@ -18,3 +18,4 @@ /** | ||
import { SourceMapper } from './sourcemapper/sourcemapper'; | ||
import { AllocationProfileNode, LabelSet, TimeProfile, TimeProfileNodeContext } from './v8-types'; | ||
import { AllocationProfileNode, GenerateAllocationLabelsFunction, GenerateTimeLabelsFunction, TimeProfile } from './v8-types'; | ||
export declare const NON_JS_THREADS_FUNCTION_NAME = "(non-JS threads)"; | ||
/** | ||
@@ -27,3 +28,3 @@ * Converts v8 time profile into into a profile proto. | ||
*/ | ||
export declare function serializeTimeProfile(prof: TimeProfile, intervalMicros: number, sourceMapper?: SourceMapper, recomputeSamplingInterval?: boolean, generateLabels?: (context: TimeProfileNodeContext) => LabelSet): Profile; | ||
export declare function serializeTimeProfile(prof: TimeProfile, intervalMicros: number, sourceMapper?: SourceMapper, recomputeSamplingInterval?: boolean, generateLabels?: GenerateTimeLabelsFunction): Profile; | ||
/** | ||
@@ -39,2 +40,2 @@ * Converts v8 heap profile into into a profile proto. | ||
*/ | ||
export declare function serializeHeapProfile(prof: AllocationProfileNode, startTimeNanos: number, intervalBytes: number, ignoreSamplesPath?: string, sourceMapper?: SourceMapper, generateLabels?: (node: AllocationProfileNode) => LabelSet): Profile; | ||
export declare function serializeHeapProfile(prof: AllocationProfileNode, startTimeNanos: number, intervalBytes: number, ignoreSamplesPath?: string, sourceMapper?: SourceMapper, generateLabels?: GenerateAllocationLabelsFunction): Profile; |
@@ -18,4 +18,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.serializeHeapProfile = exports.serializeTimeProfile = void 0; | ||
exports.serializeHeapProfile = exports.serializeTimeProfile = exports.NON_JS_THREADS_FUNCTION_NAME = void 0; | ||
const pprof_format_1 = require("pprof-format"); | ||
exports.NON_JS_THREADS_FUNCTION_NAME = '(non-JS threads)'; | ||
function isGeneratedLocation(location) { | ||
@@ -156,2 +157,12 @@ return (location.column !== undefined && | ||
/** | ||
* @return value type for cpu samples (type:cpu, units:nanoseconds), and | ||
* adds strings used in this value type to the table. | ||
*/ | ||
function createCpuValueType(table) { | ||
return new pprof_format_1.ValueType({ | ||
type: table.dedup('cpu'), | ||
unit: table.dedup('nanoseconds'), | ||
}); | ||
} | ||
/** | ||
* @return value type for object counts (type:objects, units:count), and | ||
@@ -203,8 +214,15 @@ * adds strings used in this value type to the table. | ||
let unlabelledHits = entry.node.hitCount; | ||
let unlabelledCpuTime = 0; | ||
for (const context of entry.node.contexts || []) { | ||
const labels = generateLabels ? generateLabels(context) : context.context; | ||
const labels = generateLabels | ||
? generateLabels({ node: entry.node, context }) | ||
: context.context; | ||
if (Object.keys(labels).length > 0) { | ||
const values = [1, intervalNanos]; | ||
if (prof.hasCpuTime) { | ||
values.push(context.cpuTime); | ||
} | ||
const sample = new pprof_format_1.Sample({ | ||
locationId: entry.stack, | ||
value: [1, intervalNanos], | ||
value: values, | ||
label: buildLabels(labels, stringTable), | ||
@@ -215,7 +233,16 @@ }); | ||
} | ||
else if (prof.hasCpuTime) { | ||
unlabelledCpuTime += context.cpuTime; | ||
} | ||
} | ||
if (unlabelledHits > 0) { | ||
if (unlabelledHits > 0 || unlabelledCpuTime > 0) { | ||
const labels = generateLabels ? generateLabels({ node: entry.node }) : {}; | ||
const values = [unlabelledHits, unlabelledHits * intervalNanos]; | ||
if (prof.hasCpuTime) { | ||
values.push(unlabelledCpuTime); | ||
} | ||
const sample = new pprof_format_1.Sample({ | ||
locationId: entry.stack, | ||
value: [unlabelledHits, unlabelledHits * intervalNanos], | ||
value: values, | ||
label: buildLabels(labels, stringTable), | ||
}); | ||
@@ -228,4 +255,9 @@ samples.push(sample); | ||
const timeValueType = createTimeValueType(stringTable); | ||
const sampleTypes = [sampleValueType, timeValueType]; | ||
if (prof.hasCpuTime) { | ||
const cpuValueType = createCpuValueType(stringTable); | ||
sampleTypes.push(cpuValueType); | ||
} | ||
const profile = { | ||
sampleType: [sampleValueType, timeValueType], | ||
sampleType: sampleTypes, | ||
timeNanos: Date.now() * 1000 * 1000, | ||
@@ -236,2 +268,21 @@ durationNanos: (prof.endTime - prof.startTime) * 1000, | ||
}; | ||
if (prof.nonJSThreadsCpuTime) { | ||
const node = { | ||
name: exports.NON_JS_THREADS_FUNCTION_NAME, | ||
scriptName: '', | ||
scriptId: 0, | ||
lineNumber: 0, | ||
columnNumber: 0, | ||
children: [], | ||
hitCount: 0, | ||
contexts: [ | ||
{ | ||
context: {}, | ||
timestamp: BigInt(0), | ||
cpuTime: prof.nonJSThreadsCpuTime, | ||
}, | ||
], | ||
}; | ||
prof.topDownRoot.children.push(node); | ||
} | ||
serialize(profile, prof.topDownRoot, appendTimeEntryToSamples, stringTable, undefined, sourceMapper); | ||
@@ -276,3 +327,3 @@ return new pprof_format_1.Profile(profile); | ||
const labels = generateLabels | ||
? buildLabels(generateLabels(entry.node), stringTable) | ||
? buildLabels(generateLabels({ node: entry.node }), stringTable) | ||
: []; | ||
@@ -279,0 +330,0 @@ for (const alloc of entry.node.allocations) { |
@@ -18,3 +18,3 @@ /** | ||
import { getNativeThreadId } from './time-profiler-bindings'; | ||
import { LabelSet, TimeProfileNodeContext } from './v8-types'; | ||
import { GenerateTimeLabelsFunction } from './v8-types'; | ||
type Microseconds = number; | ||
@@ -37,8 +37,10 @@ type Milliseconds = number; | ||
workaroundV8Bug?: boolean; | ||
collectCpuTime?: boolean; | ||
} | ||
export declare function profile({ intervalMicros, durationMillis, sourceMapper, lineNumbers, withContexts, workaroundV8Bug, }: TimeProfilerOptions): Promise<import("pprof-format").Profile>; | ||
export declare function start({ intervalMicros, durationMillis, sourceMapper, lineNumbers, withContexts, workaroundV8Bug, }: TimeProfilerOptions): void; | ||
export declare function stop(restart?: boolean, generateLabels?: (context: TimeProfileNodeContext) => LabelSet): import("pprof-format").Profile; | ||
export declare function profile(options?: TimeProfilerOptions): Promise<import("pprof-format").Profile>; | ||
export declare function start(options?: TimeProfilerOptions): void; | ||
export declare function stop(restart?: boolean, generateLabels?: GenerateTimeLabelsFunction): import("pprof-format").Profile; | ||
export declare function getState(): any; | ||
export declare function setContext(context?: object): void; | ||
export declare function getContext(): any; | ||
export declare function isStarted(): boolean; | ||
@@ -48,4 +50,4 @@ export declare function v8ProfilerStuckEventLoopDetected(): number; | ||
kSampleCount: any; | ||
NON_JS_THREADS_FUNCTION_NAME: string; | ||
}; | ||
export { LabelSet }; | ||
export { getNativeThreadId }; |
@@ -21,3 +21,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getNativeThreadId = exports.constants = exports.v8ProfilerStuckEventLoopDetected = exports.isStarted = exports.setContext = exports.getState = exports.stop = exports.start = exports.profile = void 0; | ||
exports.getNativeThreadId = exports.constants = exports.v8ProfilerStuckEventLoopDetected = exports.isStarted = exports.getContext = exports.setContext = exports.getState = exports.stop = exports.start = exports.profile = void 0; | ||
const delay_1 = __importDefault(require("delay")); | ||
@@ -27,2 +27,3 @@ const profile_serializer_1 = require("./profile-serializer"); | ||
Object.defineProperty(exports, "getNativeThreadId", { enumerable: true, get: function () { return time_profiler_bindings_1.getNativeThreadId; } }); | ||
const node_worker_threads_1 = require("node:worker_threads"); | ||
const { kSampleCount } = time_profiler_bindings_1.constants; | ||
@@ -41,12 +42,14 @@ const DEFAULT_INTERVAL_MICROS = 1000; | ||
}); | ||
async function profile({ intervalMicros = DEFAULT_INTERVAL_MICROS, durationMillis = DEFAULT_DURATION_MILLIS, sourceMapper, lineNumbers = false, withContexts = false, workaroundV8Bug = true, }) { | ||
start({ | ||
intervalMicros, | ||
durationMillis, | ||
sourceMapper, | ||
lineNumbers, | ||
withContexts, | ||
workaroundV8Bug, | ||
}); | ||
await (0, delay_1.default)(durationMillis); | ||
const DEFAULT_OPTIONS = { | ||
durationMillis: DEFAULT_DURATION_MILLIS, | ||
intervalMicros: DEFAULT_INTERVAL_MICROS, | ||
lineNumbers: false, | ||
withContexts: false, | ||
workaroundV8Bug: true, | ||
collectCpuTime: false, | ||
}; | ||
async function profile(options = {}) { | ||
options = { ...DEFAULT_OPTIONS, ...options }; | ||
start(options); | ||
await (0, delay_1.default)(options.durationMillis); | ||
return stop(); | ||
@@ -56,11 +59,16 @@ } | ||
// Temporarily retained for backwards compatibility with older tracer | ||
function start({ intervalMicros = DEFAULT_INTERVAL_MICROS, durationMillis = DEFAULT_DURATION_MILLIS, sourceMapper, lineNumbers = false, withContexts = false, workaroundV8Bug = true, }) { | ||
function start(options = {}) { | ||
options = { ...DEFAULT_OPTIONS, ...options }; | ||
if (gProfiler) { | ||
throw new Error('Wall profiler is already started'); | ||
} | ||
gProfiler = new time_profiler_bindings_1.TimeProfiler(intervalMicros, durationMillis * 1000, lineNumbers, withContexts, workaroundV8Bug); | ||
gSourceMapper = sourceMapper; | ||
gIntervalMicros = intervalMicros; | ||
gProfiler = new time_profiler_bindings_1.TimeProfiler({ ...options, isMainThread: node_worker_threads_1.isMainThread }); | ||
gSourceMapper = options.sourceMapper; | ||
gIntervalMicros = options.intervalMicros; | ||
gV8ProfilerStuckEventLoopDetected = 0; | ||
gProfiler.start(); | ||
// If contexts are enabled, set an initial empty context | ||
if (options.withContexts) { | ||
setContext({}); | ||
} | ||
} | ||
@@ -109,2 +117,9 @@ exports.start = start; | ||
exports.setContext = setContext; | ||
function getContext() { | ||
if (!gProfiler) { | ||
throw new Error('Wall profiler is not started'); | ||
} | ||
return gProfiler.context; | ||
} | ||
exports.getContext = getContext; | ||
function isStarted() { | ||
@@ -119,3 +134,3 @@ return !!gProfiler; | ||
exports.v8ProfilerStuckEventLoopDetected = v8ProfilerStuckEventLoopDetected; | ||
exports.constants = { kSampleCount }; | ||
exports.constants = { kSampleCount, NON_JS_THREADS_FUNCTION_NAME: profile_serializer_1.NON_JS_THREADS_FUNCTION_NAME }; | ||
//# sourceMappingURL=time-profiler.js.map |
@@ -22,2 +22,5 @@ /** | ||
startTime: number; | ||
hasCpuTime?: boolean; | ||
/** CPU time of non-JS threads, only reported for the main worker thread */ | ||
nonJSThreadsCpuTime?: number; | ||
} | ||
@@ -35,2 +38,3 @@ export interface ProfileNode { | ||
timestamp: bigint; | ||
cpuTime: number; | ||
} | ||
@@ -51,1 +55,13 @@ export interface TimeProfileNode extends ProfileNode { | ||
} | ||
export interface GenerateAllocationLabelsFunction { | ||
({ node }: { | ||
node: AllocationProfileNode; | ||
}): LabelSet; | ||
} | ||
export interface GenerateTimeLabelsArgs { | ||
node: TimeProfileNode; | ||
context?: TimeProfileNodeContext; | ||
} | ||
export interface GenerateTimeLabelsFunction { | ||
(args: GenerateTimeLabelsArgs): LabelSet; | ||
} |
{ | ||
"name": "@datadog/pprof", | ||
"version": "5.0.0-pre-56cf286", | ||
"version": "5.0.0-pre-d624748", | ||
"description": "pprof support for Node.js", | ||
@@ -5,0 +5,0 @@ "repository": "datadog/pprof-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 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 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 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 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 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 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 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
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
9587754
1596