From 37a9e7409dfbb1676b001a3eaece278ab4fee6b6 Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Thu, 26 Mar 2026 18:22:45 +0100 Subject: [PATCH] feat: dump node process information when running --- packages/core/src/index.ts | 8 +++ packages/core/src/native_core/index.ts | 8 +++ .../core/src/native_core/instruments/hooks | 2 +- .../core/src/native_core/instruments/hooks.ts | 16 ++++++ .../native_core/instruments/hooks_wrapper.cc | 52 +++++++++++++++++++ .../native_core/instruments/hooks_wrapper.h | 2 + 6 files changed, 87 insertions(+), 1 deletion(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 5aa37f2c..ddf35277 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -58,6 +58,14 @@ export const setupCore = () => { native_core.InstrumentHooks.setIntegration("codspeed-node", __VERSION__); linuxPerf.start(); checkV8Flags(); + + // Collect Node.js runtime environment to detect changes that could + // cause performance differences across runs + const hooks = native_core.InstrumentHooks; + hooks.setEnvironment("Node.js", "version", process.versions.node); + hooks.setEnvironment("Node.js", "v8", process.versions.v8); + hooks.setEnvironment("Node.js", "arch", process.arch); + hooks.writeEnvironment(process.pid); }; export const teardownCore = () => { diff --git a/packages/core/src/native_core/index.ts b/packages/core/src/native_core/index.ts index 64459a13..73499d31 100644 --- a/packages/core/src/native_core/index.ts +++ b/packages/core/src/native_core/index.ts @@ -51,6 +51,14 @@ try { setIntegration: (_name: string, _version: string) => { return 0; }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + setEnvironment: (_sectionName: string, _key: string, _value: string) => { + return 0; + }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + writeEnvironment: (_pid: number) => { + return 0; + }, __codspeed_root_frame__: (callback: () => T): T => { return callback(); }, diff --git a/packages/core/src/native_core/instruments/hooks b/packages/core/src/native_core/instruments/hooks index 89fb72a0..e86719c7 160000 --- a/packages/core/src/native_core/instruments/hooks +++ b/packages/core/src/native_core/instruments/hooks @@ -1 +1 @@ -Subproject commit 89fb72a076ec71c9eca6eee9bca98bada4b4dfb4 +Subproject commit e86719c70c9c0b1646db182a7c748230e243dace diff --git a/packages/core/src/native_core/instruments/hooks.ts b/packages/core/src/native_core/instruments/hooks.ts index 3d321a5f..24e3c9cd 100644 --- a/packages/core/src/native_core/instruments/hooks.ts +++ b/packages/core/src/native_core/instruments/hooks.ts @@ -32,6 +32,22 @@ export interface InstrumentHooks { */ setIntegration(name: string, version: string): number; + /** + * Register a key-value pair under a named environment section. + * @param sectionName Section name (e.g. "Node.js") + * @param key Key name (e.g. "version") + * @param value Value (e.g. "22.0.0") + * @returns 0 on success, non-zero on error + */ + setEnvironment(sectionName: string, key: string, value: string): number; + + /** + * Flush all registered environment sections to disk. + * @param pid Process ID + * @returns 0 on success, non-zero on error + */ + writeEnvironment(pid: number): number; + /** * Execute a callback function with __codspeed_root_frame__ in its stack trace * @param callback Function to execute diff --git a/packages/core/src/native_core/instruments/hooks_wrapper.cc b/packages/core/src/native_core/instruments/hooks_wrapper.cc index 3b6013bf..5c2f50b3 100644 --- a/packages/core/src/native_core/instruments/hooks_wrapper.cc +++ b/packages/core/src/native_core/instruments/hooks_wrapper.cc @@ -81,6 +81,54 @@ Napi::Number SetIntegration(const Napi::CallbackInfo &info) { return Napi::Number::New(env, result); } +Napi::Number SetEnvironment(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + + if (info.Length() != 3) { + Napi::TypeError::New( + env, "Expected 3 arguments: sectionName, key, and value") + .ThrowAsJavaScriptException(); + return Napi::Number::New(env, 1); + } + + if (!info[0].IsString() || !info[1].IsString() || !info[2].IsString()) { + Napi::TypeError::New( + env, + "Expected string (sectionName), string (key), and string (value)") + .ThrowAsJavaScriptException(); + return Napi::Number::New(env, 1); + } + + std::string section_name = info[0].As().Utf8Value(); + std::string key = info[1].As().Utf8Value(); + std::string value = info[2].As().Utf8Value(); + + uint8_t result = instrument_hooks_set_environment( + hooks, section_name.c_str(), key.c_str(), value.c_str()); + return Napi::Number::New(env, result); +} + +Napi::Number WriteEnvironment(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + + if (info.Length() != 1) { + Napi::TypeError::New(env, "Expected 1 argument: pid") + .ThrowAsJavaScriptException(); + return Napi::Number::New(env, 1); + } + + if (!info[0].IsNumber()) { + Napi::TypeError::New(env, "Expected number (pid)") + .ThrowAsJavaScriptException(); + return Napi::Number::New(env, 1); + } + + uint32_t pid = info[0].As().Uint32Value(); + + uint8_t result = instrument_hooks_write_environment(hooks, pid); + return Napi::Number::New(env, result); +} + Napi::Value __attribute__ ((noinline)) __codspeed_root_frame__(const Napi::CallbackInfo &info) { Napi::Env env = info.Env(); @@ -117,6 +165,10 @@ Napi::Object Initialize(Napi::Env env, Napi::Object exports) { Napi::Function::New(env, SetExecutedBenchmark)); instrumentHooksObj.Set(Napi::String::New(env, "setIntegration"), Napi::Function::New(env, SetIntegration)); + instrumentHooksObj.Set(Napi::String::New(env, "setEnvironment"), + Napi::Function::New(env, SetEnvironment)); + instrumentHooksObj.Set(Napi::String::New(env, "writeEnvironment"), + Napi::Function::New(env, WriteEnvironment)); instrumentHooksObj.Set(Napi::String::New(env, "__codspeed_root_frame__"), Napi::Function::New(env, __codspeed_root_frame__)); diff --git a/packages/core/src/native_core/instruments/hooks_wrapper.h b/packages/core/src/native_core/instruments/hooks_wrapper.h index 8f25d9a2..f63c4351 100644 --- a/packages/core/src/native_core/instruments/hooks_wrapper.h +++ b/packages/core/src/native_core/instruments/hooks_wrapper.h @@ -17,6 +17,8 @@ Napi::Number StartBenchmark(const Napi::CallbackInfo &info); Napi::Number StopBenchmark(const Napi::CallbackInfo &info); Napi::Number SetExecutedBenchmark(const Napi::CallbackInfo &info); Napi::Number SetIntegration(const Napi::CallbackInfo &info); +Napi::Number SetEnvironment(const Napi::CallbackInfo &info); +Napi::Number WriteEnvironment(const Napi::CallbackInfo &info); Napi::Object Initialize(Napi::Env env, Napi::Object exports); } // namespace hooks_wrapper