Skip to content

Commit 2df36be

Browse files
committed
Wire up oomprof
1 parent dcc87a7 commit 2df36be

File tree

9 files changed

+765
-58
lines changed

9 files changed

+765
-58
lines changed

flags/flags.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ type Flags struct {
126126

127127
OfflineMode FlagsOfflineMode `embed:"" prefix:"offline-mode-"`
128128
OffCPUThreshold uint `default:"0" help:"The per-mille probablity of off-CPU event being recorded."`
129+
130+
EnableOOMProf bool `default:"false" help:"Enable OOMProf profiling integration."`
131+
EnableOOMProfAllocs bool `default:"false" help:"Enable OOMProf alloc counts."`
129132
}
130133

131134
type ExitCode int

go.mod

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
buf.build/gen/go/parca-dev/parca/grpc/go v1.5.1-20250212095114-4db6f2d46517.2
77
buf.build/gen/go/parca-dev/parca/protocolbuffers/go v1.36.6-20250212095114-4db6f2d46517.1
88
buf.build/gen/go/prometheus/prometheus/protocolbuffers/go v1.36.6-20250320161912-af2aab87b1b3.1
9-
github.com/KimMachineGun/automemlimit v0.7.1
9+
github.com/KimMachineGun/automemlimit v0.7.3
1010
github.com/alecthomas/kong v1.10.0
1111
github.com/apache/arrow/go/v16 v16.1.0
1212
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
@@ -20,6 +20,7 @@ require (
2020
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1
2121
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1
2222
github.com/klauspost/compress v1.18.0
23+
github.com/parca-dev/oomprof v0.1.5-0.20250731155753-0ad8f29d16f7
2324
github.com/prometheus/client_golang v1.22.0
2425
github.com/prometheus/common v0.63.0
2526
github.com/prometheus/prometheus v0.303.0
@@ -32,7 +33,7 @@ require (
3233
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0
3334
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0
3435
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0
35-
go.opentelemetry.io/ebpf-profiler v0.0.0-20250416113750-7ddc23ea135a
36+
go.opentelemetry.io/ebpf-profiler v0.0.0-20250519164423-009a07f3803c
3637
go.opentelemetry.io/otel v1.37.0
3738
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0
3839
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0
@@ -54,7 +55,7 @@ require (
5455
require (
5556
buf.build/gen/go/gogo/protobuf/protocolbuffers/go v1.36.6-20240617172848-e1dbca2775a7.1 // indirect
5657
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect
57-
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect
58+
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect
5859
github.com/Microsoft/go-winio v0.6.2 // indirect
5960
github.com/Microsoft/hcsshim v0.12.9 // indirect
6061
github.com/beorn7/perks v1.0.1 // indirect
@@ -92,14 +93,15 @@ require (
9293
github.com/google/gnostic-models v0.6.9 // indirect
9394
github.com/google/go-cmp v0.7.0 // indirect
9495
github.com/google/gofuzz v1.2.0 // indirect
96+
github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a // indirect
9597
github.com/google/uuid v1.6.0 // indirect
9698
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
9799
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
98100
github.com/josharian/intern v1.0.0 // indirect
99101
github.com/josharian/native v1.1.0 // indirect
100102
github.com/jpillora/backoff v1.0.0 // indirect
101103
github.com/json-iterator/go v1.1.12 // indirect
102-
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
104+
github.com/klauspost/cpuid/v2 v2.2.11 // indirect
103105
github.com/mailru/easyjson v0.9.0 // indirect
104106
github.com/mdlayher/kobject v0.0.0-20200520190114-19ca17470d7d // indirect
105107
github.com/mdlayher/netlink v1.7.2 // indirect
@@ -145,9 +147,10 @@ require (
145147
golang.org/x/time v0.11.0 // indirect
146148
golang.org/x/tools v0.34.0 // indirect
147149
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
150+
gonum.org/v1/gonum v0.16.0 // indirect
148151
google.golang.org/genproto v0.0.0-20250414145226-207652e42e2e // indirect
149152
google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect
150-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect
153+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250425173222-7b384671a197 // indirect
151154
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
152155
gopkg.in/inf.v0 v0.9.1 // indirect
153156
gopkg.in/yaml.v2 v2.4.0 // indirect
@@ -160,4 +163,4 @@ require (
160163
sigs.k8s.io/yaml v1.4.0 // indirect
161164
)
162165

163-
replace go.opentelemetry.io/ebpf-profiler => github.com/parca-dev/opentelemetry-ebpf-profiler v0.0.0-20250723163006-6ef58876b286
166+
replace go.opentelemetry.io/ebpf-profiler => github.com/parca-dev/opentelemetry-ebpf-profiler v0.0.0-20250731174540-1195e517db5c

go.sum

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
1111
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
1212
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
1313
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
14-
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M=
15-
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw=
14+
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA=
15+
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU=
1616
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
1717
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
1818
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
19-
github.com/KimMachineGun/automemlimit v0.7.1 h1:QcG/0iCOLChjfUweIMC3YL5Xy9C3VBeNmCZHrZfJMBw=
20-
github.com/KimMachineGun/automemlimit v0.7.1/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
19+
github.com/KimMachineGun/automemlimit v0.7.3 h1:oPgMp0bsWez+4fvgSa11Rd9nUDrd8RLtDjBoT3ro+/A=
20+
github.com/KimMachineGun/automemlimit v0.7.3/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
2121
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
2222
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
2323
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg=
@@ -67,6 +67,8 @@ github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRq
6767
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
6868
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
6969
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
70+
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
71+
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
7072
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
7173
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
7274
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -118,6 +120,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
118120
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
119121
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
120122
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
123+
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
124+
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
121125
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
122126
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
123127
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -155,8 +159,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
155159
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
156160
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
157161
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
158-
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
159-
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
162+
github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a h1://KbezygeMJZCSHH+HgUZiTeSoiuFspbMg1ge+eFj18=
163+
github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
160164
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
161165
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
162166
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -187,8 +191,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
187191
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
188192
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
189193
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
190-
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
191-
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
194+
github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU=
195+
github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
192196
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
193197
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
194198
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -253,8 +257,10 @@ github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU
253257
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
254258
github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
255259
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
256-
github.com/parca-dev/opentelemetry-ebpf-profiler v0.0.0-20250723163006-6ef58876b286 h1:P/fRnXyyq/8AY+g3RN+KSMX7xQeRPpEkiDJ23WtEOIE=
257-
github.com/parca-dev/opentelemetry-ebpf-profiler v0.0.0-20250723163006-6ef58876b286/go.mod h1:ZKCiLxqP47dzRIJgvvcj/jj+gpzco2AA8imbDZ4+Tac=
260+
github.com/parca-dev/oomprof v0.1.5-0.20250731155753-0ad8f29d16f7 h1:Xw96a25o3wIFDRv2SFrvQhs4GcqyFyvUEzC+m4G8uiI=
261+
github.com/parca-dev/oomprof v0.1.5-0.20250731155753-0ad8f29d16f7/go.mod h1:+vw0+rZYq/rTVouF6G+/+Uol758EOkUINi8/8RXPvX0=
262+
github.com/parca-dev/opentelemetry-ebpf-profiler v0.0.0-20250731174540-1195e517db5c h1:3K9ZevMtHUl+MBeGOhQ/XP1IKMcYl6WaEwg1+4YAv7A=
263+
github.com/parca-dev/opentelemetry-ebpf-profiler v0.0.0-20250731174540-1195e517db5c/go.mod h1:h8C/CuCo73JCYzKS7mcHtoT925k0TJRQq99N1c3UPpo=
258264
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
259265
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
260266
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
@@ -438,8 +444,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
438444
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
439445
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
440446
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
441-
gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ=
442-
gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo=
447+
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
448+
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
443449
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
444450
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
445451
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
@@ -449,8 +455,8 @@ google.golang.org/genproto v0.0.0-20250414145226-207652e42e2e h1:mYHFv3iX85YMwhG
449455
google.golang.org/genproto v0.0.0-20250414145226-207652e42e2e/go.mod h1:TQT1YpH/rlDCS5+EuFaqPIMqDfuNMFR1OI8EcZJGgAk=
450456
google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e h1:UdXH7Kzbj+Vzastr5nVfccbmFsmYNygVLSPk1pEfDoY=
451457
google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e/go.mod h1:085qFyf2+XaZlRdCgKNCIZ3afY2p4HHZdoIRpId8F4A=
452-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA=
453-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
458+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250425173222-7b384671a197 h1:29cjnHVylHwTzH66WfFZqgSQgnxzvWE+jvBwpZCLRxY=
459+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250425173222-7b384671a197/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
454460
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
455461
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
456462
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=

main.go

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@ import (
4848
"golang.org/x/sys/unix"
4949
"google.golang.org/grpc"
5050

51+
"github.com/parca-dev/oomprof/oomprof"
5152
"github.com/parca-dev/parca-agent/analytics"
5253
"github.com/parca-dev/parca-agent/config"
5354
"github.com/parca-dev/parca-agent/flags"
55+
"github.com/parca-dev/parca-agent/oom"
5456
"github.com/parca-dev/parca-agent/reporter"
5557
"github.com/parca-dev/parca-agent/uploader"
5658
)
@@ -208,10 +210,53 @@ func mainWithExitCode() flags.ExitCode {
208210
cmd.Stdout = os.Stdout
209211
cmd.Stderr = io.MultiWriter(os.Stderr, buf)
210212

213+
if f.EnableOOMProf {
214+
// Try to ensure oom killer leaves the parent alive by lowering our own oom adjustment,
215+
// if the parent gets oom killed too its possible no oom reports will be sent.
216+
// TODO: weigh this strategy's effectiveness against a canary/ballast approach.
217+
if err := os.WriteFile("/proc/self/oom_score_adj", []byte("-100"), 0644); err != nil {
218+
log.Errorf("Failed to set oom_score_adj: %v", err)
219+
}
220+
}
221+
211222
// Run garbage collector to minimize the amount of memory that the parent
212223
// telemetry process uses.
213224
runtime.GC()
214-
err := cmd.Run()
225+
226+
// Setup OOMProf integration if enabled.
227+
var oomProfState *oomprof.State
228+
if f.EnableOOMProf {
229+
state, err := oom.StartOOMProf(ctx, grpcConn, f.BPF.VerboseLogging, f.Node, f.Metadata.ExternalLabels, f.EnableOOMProfAllocs)
230+
if err != nil {
231+
return flags.Failure("Failed to start OOMProf: %v", err)
232+
}
233+
oomProfState = state
234+
}
235+
236+
// Start the subprocess instead of Run to get the PID
237+
err := cmd.Start()
238+
if err != nil {
239+
log.Errorf("Failed to start subprocess: %v", err)
240+
return flags.ExitFailure
241+
}
242+
243+
// Get the subprocess PID for oomprof monitoring
244+
subprocessPID := uint32(cmd.Process.Pid)
245+
log.Debugf("Started parca-agent subprocess with PID %d", subprocessPID)
246+
247+
// If oomprof is enabled, tell it to watch our subprocess
248+
if f.EnableOOMProf && oomProfState != nil {
249+
err = oomProfState.WatchPid(subprocessPID)
250+
if err != nil {
251+
log.Errorf("Failed to watch subprocess PID %d: %v", subprocessPID, err)
252+
} else {
253+
log.Infof("OOMProf is now monitoring main parca-agent PID %d", subprocessPID)
254+
}
255+
}
256+
257+
// Wait for the subprocess to complete
258+
err = cmd.Wait()
259+
log.Infof("Subprocess completed %v exit: %d", err, cmd.ProcessState.ExitCode())
215260
if err != nil {
216261
log.Error("======================= unexpected error =======================")
217262
log.Error(buf.String())
@@ -263,7 +308,7 @@ func mainWithExitCode() flags.ExitCode {
263308
}
264309

265310
if err = tracer.ProbeBPFSyscall(); err != nil {
266-
return flags.Failure(fmt.Sprintf("Failed to probe eBPF syscall: %v", err))
311+
return flags.Failure("Failed to probe eBPF syscall: %v", err)
267312
}
268313

269314
externalLabels := reporter.Labels{}
@@ -356,6 +401,8 @@ func mainWithExitCode() flags.ExitCode {
356401
buildInfo.VcsRevision,
357402
reg,
358403
offlineModeConfig,
404+
f.EnableOOMProf,
405+
f.EnableOOMProfAllocs,
359406
)
360407
if err != nil {
361408
return flags.Failure("Failed to start reporting: %v", err)

oom/oom_test_handler.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//go:build oomtest
2+
// +build oomtest
3+
4+
package oom
5+
6+
import (
7+
"os"
8+
"os/signal"
9+
"sync"
10+
"syscall"
11+
12+
log "github.com/sirupsen/logrus"
13+
)
14+
15+
// memoryBombs holds allocated memory to prevent GC from freeing it
16+
var memoryBombs [][]byte
17+
18+
// oomOnce ensures the OOM trigger only runs once
19+
var oomOnce sync.Once
20+
21+
// setupOOMTestHandler sets up a signal handler that triggers massive memory allocation
22+
// when SIGUSR2 is received.
23+
func setupOOMTestHandler() {
24+
log.Warn("OOM testing mode enabled - SIGUSR2 will trigger memory allocation bomb")
25+
26+
// Create a channel to receive SIGUSR2 signals
27+
sigChan := make(chan os.Signal, 1)
28+
signal.Notify(sigChan, syscall.SIGUSR2)
29+
30+
go func() {
31+
for range sigChan {
32+
// do once to avoid multiple triggers
33+
oomOnce.Do(func() {
34+
log.Warn("SIGUSR2 received - triggering OOM by allocating memory aggressively")
35+
// Start the memory allocation bomb
36+
triggerOOM()
37+
})
38+
}
39+
}()
40+
}
41+
42+
// triggerOOM allocates memory aggressively to force an OOM condition
43+
func triggerOOM() {
44+
// Start allocating memory in chunks
45+
chunkSize := 1 * 1024 * 1024
46+
allocations := 0
47+
48+
log.Info("Starting memory allocation bomb...")
49+
50+
// Allocate memory until we get killed
51+
for { // 10MB chunks
52+
// Allocate a chunk
53+
chunk := make([]byte, chunkSize)
54+
55+
// Fill it with data to ensure it's actually allocated
56+
for i := range chunk {
57+
chunk[i] = byte(i % 256)
58+
}
59+
60+
// Keep reference to prevent GC
61+
memoryBombs = append(memoryBombs, chunk)
62+
allocations++
63+
64+
// Log progress every 10 allocations
65+
if allocations%10 == 0 {
66+
totalMB := (allocations * chunkSize) / (1024 * 1024)
67+
log.Infof("Allocated %d chunks, total: %d MB", allocations, totalMB)
68+
}
69+
}
70+
}
71+
72+
// init is called automatically when the package is imported
73+
func init() {
74+
setupOOMTestHandler()
75+
}

oom/oom_test_handler_stub.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//go:build !oomtest
2+
// +build !oomtest
3+
4+
package oom
5+
6+
// setupOOMTestHandler is a no-op when the oomtest build tag is not present
7+
func setupOOMTestHandler() {
8+
// No-op - OOM testing is not compiled in
9+
}

0 commit comments

Comments
 (0)