Skip to content

Commit e73d36c

Browse files
authored
Add configurable startup delay for JVM async-profiler (#302)
1 parent 18e2b96 commit e73d36c

2 files changed

Lines changed: 13 additions & 1 deletion

File tree

flags/flags.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ var (
1717
DisableGPUMonitoring = kingpin.Flag("disable-gpu-monitoring", "Disable GPU monitoring (NVML)").Default("false").Envar("DISABLE_GPU_MONITORING").Bool()
1818
EnableJavaTls = kingpin.Flag("enable-java-tls", "Enable Java TLS instrumentation via dynamic agent loading").Default("false").Envar("ENABLE_JAVA_TLS").Bool()
1919
EnableJavaAsyncProfiler = kingpin.Flag("enable-java-async-profiler", "Enable Java profiling via async-profiler (CPU, memory allocations, lock contention)").Default("false").Envar("ENABLE_JAVA_ASYNC_PROFILER").Bool()
20+
JavaAsyncProfilerDelay = kingpin.Flag("java-async-profiler-delay", "Delay in seconds before starting async-profiler after JVM process is detected").Default("30s").Envar("JAVA_ASYNC_PROFILER_DELAY").Duration()
2021
GoHeapProfilerMode = kingpin.Flag("go-heap-profiler", "Go heap profiling mode: disabled, enabled (collect from apps with profiling on), force (enable profiling in all Go apps)").Default("enabled").Envar("GO_HEAP_PROFILER").String()
2122

2223
ContainerAllowlist = kingpin.Flag("container-allowlist", "List of allowed containers (regex patterns)").Envar("CONTAINER_ALLOWLIST").Strings()

profiling/profiling.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ func collectAsyncProfilerProfiles() {
193193
serviceName string
194194
containerID string
195195
started bool
196+
startedAt time.Time
196197
}
197198
var jvms []jvmInfo
198199
for pid, pi := range targetFinder.processes {
@@ -202,13 +203,22 @@ func collectAsyncProfilerProfiles() {
202203
serviceName: pi.serviceName,
203204
containerID: pi.containerId,
204205
started: pi.asyncProfilerStarted,
206+
startedAt: time.Unix(0, pi.startedAt),
205207
})
206208
}
207209
}
208210
targetFinder.lock.Unlock()
209211

210212
for _, j := range jvms {
211213
if !j.started {
214+
delay := *flags.JavaAsyncProfilerDelay
215+
if delay > 0 && !j.startedAt.IsZero() {
216+
if time.Since(j.startedAt) < delay {
217+
klog.Infof("pid=%d: delaying async-profiler start (waiting for %s since start)", j.pid, delay)
218+
continue
219+
}
220+
}
221+
212222
if jvm.IsAsyncProfilerAlreadyLoaded(j.pid) {
213223
klog.Infof("pid=%d: async-profiler already loaded by another tool, skipping", j.pid)
214224
targetFinder.lock.Lock()
@@ -219,13 +229,14 @@ func collectAsyncProfilerProfiles() {
219229
continue
220230
}
221231
if err := jvm.DeployAndStartAsyncProfiler(j.pid); err != nil {
222-
klog.Warningf("async-profiler start pid=%d: %v", j.pid, err)
232+
klog.Warningf("async-profiler start pid=%d: %s", j.pid, err)
223233
targetFinder.lock.Lock()
224234
if pi := targetFinder.processes[j.pid]; pi != nil {
225235
pi.asyncProfilerErr = true
226236
}
227237
targetFinder.lock.Unlock()
228238
} else {
239+
klog.Infof("pid=%d: async-profiler started", j.pid)
229240
targetFinder.lock.Lock()
230241
if pi := targetFinder.processes[j.pid]; pi != nil {
231242
pi.asyncProfilerStarted = true

0 commit comments

Comments
 (0)