Skip to content
This repository has been archived by the owner on Sep 17, 2024. It is now read-only.

feat(profiling): use env variable instead of compile time #61

Merged
merged 1 commit into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,15 @@ const transaction = Sentry.startTransaction({ name: 'I will do some work' });
transaction.finish();
```

### Compile time flags
### Runtime time flags

The default mode of the v8 CpuProfiler is kLazyLogging which disables logging when no profiles are active - this is good because it does not add any overhead to the runtime, however it may result in calls to startProfiling to take longer. When profiling a script that starts many profiles serially (e.g. jest with --runInBand), each profile may add to that performance penalty and ultimately result in prohibitively large overhead. To allow changes to logging mode, we allow you to change the default behavior by setting an environment variable `SENTRY_PROFILER_LOGGING_MODE` with values `eager|lazy` before running npm install.
The default mode of the v8 CpuProfiler is kLazyLogging which disables logging when no profiles are active - this is good because it does not add any overhead to the runtime, however it may result in calls to startProfiling to significantly block script execution when the first profiles starts. You can switch to eager logging which decreases the startup cost for the tradeoff of some CPU overhead by specifying environment variable `SENTRY_PROFILER_LOGGING_MODE` with values `eager|lazy` before running npm install.

Example of starting a webserver with eager logging mode.

```javascript
SENTRY_PROFILER_LOGGING_MODE=eager node server.js
```

## FAQ 💭

Expand Down
8 changes: 0 additions & 8 deletions binding.gyp
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
{
'variables': {
'PROFILER_LOGGING_MODE%': '<!(echo "$SENTRY_PROFILER_LOGGING_MODE")',
},
"targets": [
{
"target_name": "cpu_profiler",
"sources": [ "bindings/cpu_profiler.cc" ],
"defines": ["PROFILER_FORMAT=FORMAT_SAMPLED"],
'conditions': [
['PROFILER_LOGGING_MODE == "eager"', {
'defines': ['PROFILER_LOGGING_MODE=1']
}]
],
'include_dirs': [
'<!(node -e "require(\'nan\')")'
]
Expand Down
53 changes: 26 additions & 27 deletions bindings/cpu_profiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
#define PROFILER_FORMAT FORMAT_SAMPLED
#endif

#ifndef PROFILER_LOGGING_MODE
#define PROFILER_LOGGING_MODE 0
#endif

#ifndef FORMAT_BENCHMARK
#define FORMAT_BENCHMARK 0
#endif
Expand All @@ -26,25 +22,33 @@ static const uint8_t MAX_STACK_DEPTH = 128;
static const float SAMPLING_FREQUENCY = 99.0; // 99 to avoid lockstep sampling
static const float SAMPLING_HZ = 1 / SAMPLING_FREQUENCY;
static const int SAMPLING_INTERVAL_US = static_cast<int>(SAMPLING_HZ * 1e6);

static const v8::CpuProfilingNamingMode NAMING_MODE = v8::CpuProfilingNamingMode::kDebugNaming;
v8::CpuProfilingLoggingMode LOGGING_MODE = v8::CpuProfilingLoggingMode::kLazyLogging;

// Allow users to override the default logging mode via env variable. This is useful
// because sometimes the flow of the profiled program can be to execute many sequential
// transaction - in that case, it may be preferable to set eager logging to avoid paying the
// high cost of profiling for each individual transaction (one example for this are jest
// tests when run with --runInBand option).
v8::CpuProfilingLoggingMode getLoggingMode(){
char* logging_mode = getenv("SENTRY_PROFILER_LOGGING_MODE");
if(logging_mode){
if(std::strcmp(logging_mode, "eager") == 0) {
return v8::CpuProfilingLoggingMode::kEagerLogging;
} if(std::strcmp(logging_mode, "lazy") == 0) {
return v8::CpuProfilingLoggingMode::kLazyLogging;
}
}

return LOGGING_MODE;
}
class Profiler {
public:
explicit Profiler(v8::Isolate* isolate) :

// Allow users to override the default logging mode via compile time flags. This is useful
// because sometimes the flow of the profiled program can be to execute many sequential
// transaction - in that case, it may be preferable to set eager logging to avoid paying the
// high cost of profiling for each individual transaction (one example for this are jest
// tests when run with --runInBand option).
#if PROFILER_LOGGING_MODE == 1
cpu_profiler(v8::CpuProfiler::New(isolate, v8::CpuProfilingNamingMode::kDebugNaming, v8::CpuProfilingLoggingMode::kEagerLogging)) {
node::AddEnvironmentCleanupHook(isolate, DeleteInstance, this);
}
#else
cpu_profiler(v8::CpuProfiler::New(isolate, v8::CpuProfilingNamingMode::kDebugNaming, v8::CpuProfilingLoggingMode::kLazyLogging)) {
node::AddEnvironmentCleanupHook(isolate, DeleteInstance, this);
}
#endif
explicit Profiler(v8::Isolate* isolate):
cpu_profiler(
v8::CpuProfiler::New(isolate, NAMING_MODE, getLoggingMode())) {
node::AddEnvironmentCleanupHook(isolate, DeleteInstance, this);
}

v8::CpuProfiler* cpu_profiler;

Expand Down Expand Up @@ -236,12 +240,7 @@ v8::Local<v8::Value> CreateProfile(const v8::CpuProfile* profile, uint32_t threa
Nan::Set(js_profile, Nan::New<v8::String>("profile_relative_started_at_ns").ToLocalChecked(), Nan::New<v8::Number>(profile->GetStartTime() * 1000));
Nan::Set(js_profile, Nan::New<v8::String>("profile_relative_ended_at_ns").ToLocalChecked(), Nan::New<v8::Number>(profile->GetEndTime() * 1000));

#if PROFILER_LOGGING_MODE == 1
Nan::Set(js_profile, Nan::New<v8::String>("profiler_logging_mode").ToLocalChecked(), Nan::New<v8::String>("eager").ToLocalChecked());
#else
Nan::Set(js_profile, Nan::New<v8::String>("profiler_logging_mode").ToLocalChecked(), Nan::New<v8::String>("lazy").ToLocalChecked());
#endif

Nan::Set(js_profile, Nan::New<v8::String>("profiler_logging_mode").ToLocalChecked(), Nan::New<v8::String>(getLoggingMode() == v8::CpuProfilingLoggingMode::kEagerLogging ? "eager" : "lazy").ToLocalChecked());


#if PROFILER_FORMAT == FORMAT_SAMPLED || FORMAT_BENCHMARK == 1
Expand Down