Skip to content

Commit aa15bef

Browse files
committed
Simple probes WIP
1 parent f17d043 commit aa15bef

15 files changed

Lines changed: 979 additions & 19 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
/out
77
/bin
88
*.bpf.o
9+
probes/bpf/*.amd64
10+
probes/bpf/*.arm64
11+
probes/bpf/*.ll
912
TODO.md
1013
minikube-*
1114
/data

Makefile

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
1-
.PHONY: all crossbuild build build-debug snap
1+
.PHONY: all crossbuild build build-debug snap probes-bpf
2+
3+
GOARCH ?= $(shell go env GOARCH)
4+
PROBES_BPF_OBJ := probes/bpf/probe.bpf.$(GOARCH)
5+
CLANG ?= clang
26

37
all: crossbuild
48

9+
probes-bpf: $(PROBES_BPF_OBJ)
10+
11+
# Compiles the simple-probes-v1 uprobe program. Requires clang with the bpf
12+
# target and libbpf headers (libbpf-dev / libbpf-devel).
13+
$(PROBES_BPF_OBJ): probes/bpf/probe.bpf.c
14+
$(CLANG) -O2 -g -target bpf \
15+
-D__TARGET_ARCH_$(GOARCH) \
16+
-Wall -Werror \
17+
-c $< -o $@
18+
519
crossbuild:
620
DOCKER_CLI_EXPERIMENTAL="enabled" docker run \
721
--rm \
@@ -13,10 +27,10 @@ crossbuild:
1327
docker.io/goreleaser/goreleaser-cross:v1.22.4 \
1428
release --snapshot --clean --skip=publish --verbose
1529

16-
build:
30+
build: probes-bpf
1731
go build -o parca-agent -buildvcs=false -ldflags="-extldflags=-static" -tags osusergo,netgo
1832

19-
build-debug:
33+
build-debug: probes-bpf
2034
go build -o parca-agent-debug -buildvcs=false -ldflags="-extldflags=-static" -tags osusergo,netgo -gcflags "all=-N -l"
2135

2236
snap: crossbuild

flags/flags.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ type Flags struct {
160160

161161
EnableOOMProf bool `default:"false" help:"Enable OOMProf profiling integration."`
162162
EnableOOMProfAllocs bool `default:"false" help:"Enable OOMProf alloc counts."`
163+
164+
ProbeConfig string `default:"" help:"Path to a YAML file declaring uprobe attachments. When set, parca-agent attaches a uprobe per matching binary and streams probe-fire events to the configured remote-store as OTLP/Arrow logs. Empty disables the feature."`
163165
}
164166

165167
type ExitCode int

go.mod

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ require (
2323
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1
2424
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1
2525
github.com/klauspost/compress v1.18.5
26+
github.com/open-telemetry/otel-arrow/go v0.47.0
2627
github.com/parca-dev/oomprof v0.1.6
2728
github.com/prometheus/client_golang v1.22.0
2829
github.com/prometheus/common v0.63.0
@@ -33,6 +34,7 @@ require (
3334
github.com/xyproto/ainur v1.3.3
3435
github.com/zcalusic/sysinfo v1.1.3
3536
github.com/zeebo/xxh3 v1.1.0
37+
go.opentelemetry.io/collector/pdata v1.57.0
3638
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0
3739
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0
3840
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0
@@ -63,10 +65,12 @@ require (
6365
cyphar.com/go-pathrs v0.2.1 // indirect
6466
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect
6567
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect
68+
github.com/HdrHistogram/hdrhistogram-go v1.2.0 // indirect
6669
github.com/Microsoft/go-winio v0.6.2 // indirect
6770
github.com/Microsoft/hcsshim v0.12.9 // indirect
6871
github.com/andybalholm/brotli v1.2.0 // indirect
6972
github.com/apache/thrift v0.23.0 // indirect
73+
github.com/axiomhq/hyperloglog v0.2.6 // indirect
7074
github.com/beorn7/perks v1.0.1 // indirect
7175
github.com/blang/semver/v4 v4.0.0 // indirect
7276
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
@@ -84,14 +88,15 @@ require (
8488
github.com/containerd/typeurl/v2 v2.2.3 // indirect
8589
github.com/cyphar/filepath-securejoin v0.6.0 // indirect
8690
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
91+
github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33 // indirect
8792
github.com/distribution/reference v0.6.0 // indirect
8893
github.com/docker/go-connections v0.6.0 // indirect
8994
github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 // indirect
9095
github.com/docker/go-units v0.5.0 // indirect
9196
github.com/elastic/go-perf v0.0.0-20260224073651-af0ee0c731b7 // indirect
9297
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
9398
github.com/felixge/httpsnoop v1.0.4 // indirect
94-
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
99+
github.com/fxamacker/cbor/v2 v2.9.1 // indirect
95100
github.com/go-logr/logr v1.4.3 // indirect
96101
github.com/go-logr/stdr v1.2.2 // indirect
97102
github.com/go-openapi/jsonpointer v0.21.1 // indirect
@@ -108,12 +113,13 @@ require (
108113
github.com/google/uuid v1.6.0 // indirect
109114
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
110115
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
111-
github.com/hashicorp/go-version v1.8.0 // indirect
116+
github.com/hashicorp/go-version v1.9.0 // indirect
112117
github.com/inconshreveable/mousetrap v1.1.0 // indirect
113118
github.com/josharian/intern v1.0.0 // indirect
114119
github.com/josharian/native v1.1.0 // indirect
115120
github.com/jpillora/backoff v1.0.0 // indirect
116121
github.com/json-iterator/go v1.1.12 // indirect
122+
github.com/kamstrup/intmap v0.5.2 // indirect
117123
github.com/klauspost/asmfmt v1.3.2 // indirect
118124
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
119125
github.com/mailru/easyjson v0.9.0 // indirect
@@ -153,8 +159,7 @@ require (
153159
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
154160
go.opentelemetry.io/collector/consumer v1.54.0 // indirect
155161
go.opentelemetry.io/collector/consumer/xconsumer v0.148.0 // indirect
156-
go.opentelemetry.io/collector/featuregate v1.54.0 // indirect
157-
go.opentelemetry.io/collector/pdata v1.54.0 // indirect
162+
go.opentelemetry.io/collector/featuregate v1.57.0 // indirect
158163
go.opentelemetry.io/collector/pdata/pprofile v0.148.0 // indirect
159164
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
160165
go.uber.org/multierr v1.11.0 // indirect

go.sum

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod
1818
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
1919
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
2020
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
21+
github.com/HdrHistogram/hdrhistogram-go v1.2.0 h1:XMJkDWuz6bM9Fzy7zORuVFKH7ZJY41G2q8KWhVGkNiY=
22+
github.com/HdrHistogram/hdrhistogram-go v1.2.0/go.mod h1:CiIeGiHSd06zjX+FypuEJ5EQ07KKtxZ+8J6hszwVQig=
2123
github.com/KimMachineGun/automemlimit v0.7.3 h1:oPgMp0bsWez+4fvgSa11Rd9nUDrd8RLtDjBoT3ro+/A=
2224
github.com/KimMachineGun/automemlimit v0.7.3/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
2325
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
@@ -40,10 +42,14 @@ github.com/apache/thrift v0.23.0 h1:wKR6YnefQSEnxpEfmgTPuJibNG4bF0p2TK34tHLWi3s=
4042
github.com/apache/thrift v0.23.0/go.mod h1:zPt6WxgvTOM6hF92y8C+MkEM5LMxZuk4JcQOiU4Esvs=
4143
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 h1:7Ip0wMmLHLRJdrloDxZfhMm0xrLXZS8+COSu2bXmEQs=
4244
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
45+
github.com/axiomhq/hyperloglog v0.2.6 h1:sRhvvF3RIXWQgAXaTphLp4yJiX4S0IN3MWTaAgZoRJw=
46+
github.com/axiomhq/hyperloglog v0.2.6/go.mod h1:YjX/dQqCR/7QYX0g8mu8UZAjpIenz1FKM71UEsjFoTo=
4347
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
4448
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
4549
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
4650
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
51+
github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4=
52+
github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs=
4753
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
4854
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
4955
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
@@ -98,6 +104,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
98104
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
99105
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
100106
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
107+
github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33 h1:ucRHb6/lvW/+mTEIGbvhcYU3S8+uSNkuMjx/qZFfhtM=
108+
github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
101109
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
102110
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
103111
github.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM=
@@ -126,8 +134,8 @@ github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY=
126134
github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
127135
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
128136
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
129-
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
130-
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
137+
github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ=
138+
github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
131139
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
132140
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
133141
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -203,8 +211,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1 h1:KcFzXwzM/kGhIRHvc8jdix
203211
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc=
204212
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
205213
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
206-
github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=
207-
github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
214+
github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA=
215+
github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
208216
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
209217
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
210218
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
@@ -223,6 +231,8 @@ github.com/jsimonetti/rtnetlink/v2 v2.0.3 h1:Jcp7GTnTPepoUAJ9+LhTa7ZiebvNS56T1Gt
223231
github.com/jsimonetti/rtnetlink/v2 v2.0.3/go.mod h1:atIkksp/9fqtf6rpAw45JnttnP2gtuH9X88WPfWfS9A=
224232
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
225233
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
234+
github.com/kamstrup/intmap v0.5.2 h1:qnwBm1mh4XAnW9W9Ue9tZtTff8pS6+s6iKF6JRIV2Dk=
235+
github.com/kamstrup/intmap v0.5.2/go.mod h1:gWUVWHKzWj8xpJVFf5GC0O26bWmv3GqdnIX/LMT6Aq4=
226236
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
227237
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
228238
github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4=
@@ -302,6 +312,8 @@ github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM
302312
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
303313
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
304314
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
315+
github.com/open-telemetry/otel-arrow/go v0.47.0 h1:ujqc9I0oyZFnqUr9aY1xnjwqiYL5HRfNL08VsiEKeD8=
316+
github.com/open-telemetry/otel-arrow/go v0.47.0/go.mod h1:m28xKXi3VWa/DRu9p+9HNLgm93ZlxoncD9ufNlbwPzY=
305317
github.com/open-telemetry/sig-profiling/tools/profcheck v0.0.0-20260303084341-52f633d434c9 h1:3NStK3r8FVhXbU0qkVz/DpPQlaoLLgLHJOAMKyDX4WM=
306318
github.com/open-telemetry/sig-profiling/tools/profcheck v0.0.0-20260303084341-52f633d434c9/go.mod h1:KRO+Rec0+KycN1CrIP/6Pu0xOraPhbahCbL36i8FkfM=
307319
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@@ -380,8 +392,8 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo
380392
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
381393
github.com/zcalusic/sysinfo v1.1.3 h1:u/AVENkuoikKuIZ4sUEJ6iibpmQP6YpGD8SSMCrqAF0=
382394
github.com/zcalusic/sysinfo v1.1.3/go.mod h1:NX+qYnWGtJVPV0yWldff9uppNKU4h40hJIRPf/pGLv4=
383-
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
384-
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
395+
github.com/zeebo/assert v1.3.1 h1:vukIABvugfNMZMQO1ABsyQDJDTVQbn+LWSMy1ol1h6A=
396+
github.com/zeebo/assert v1.3.1/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
385397
github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
386398
github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
387399
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
@@ -392,12 +404,12 @@ go.opentelemetry.io/collector/consumer v1.54.0 h1:RGGtUN+GbkV1px3T6XdUHmgJ+ldJ1h
392404
go.opentelemetry.io/collector/consumer v1.54.0/go.mod h1:1PC6XINTL9DdT1bwvfMdHE72EB4RWU/WcPemUrhqKN8=
393405
go.opentelemetry.io/collector/consumer/xconsumer v0.148.0 h1:m3b9rY7CLD5Pcge6sSKHIT3OlcPN6xqYsdtVs9oJ528=
394406
go.opentelemetry.io/collector/consumer/xconsumer v0.148.0/go.mod h1:bG+Wz6xmIBl/gHzq1sqvksWXqTLuTX17Wo//zIsdZpw=
395-
go.opentelemetry.io/collector/featuregate v1.54.0 h1:ufo5Hy4Co9pcHVg24hyanm8qFG3TkkYbVyQXPVAbwDc=
396-
go.opentelemetry.io/collector/featuregate v1.54.0/go.mod h1:PS7zY/zaCb28EqciePVwRHVhc3oKortTFXsi3I6ee4g=
397-
go.opentelemetry.io/collector/internal/testutil v0.148.0 h1:3Z9hperte3vSmbBTYeNndoEUICICrNz8hzx+v0FYXBQ=
398-
go.opentelemetry.io/collector/internal/testutil v0.148.0/go.mod h1:Jkjs6rkqs973LqgZ0Fe3zrokQRKULYXPIf4HuqStiEE=
399-
go.opentelemetry.io/collector/pdata v1.54.0 h1:3LharKb792cQ3VrUGxd3IcpWwfu3ST+GSTU382jVz1s=
400-
go.opentelemetry.io/collector/pdata v1.54.0/go.mod h1:+MqC3VVOv/EX9YVFUo+mI4F0YmwJ+fXBYwjmu+mRiZ8=
407+
go.opentelemetry.io/collector/featuregate v1.57.0 h1:KPDSUKYn6MHwgyGRSGPPcW/G96HH93pxuvvPwM+R8nY=
408+
go.opentelemetry.io/collector/featuregate v1.57.0/go.mod h1:4ga1QBMPEejXXmpyJS8lmaRpknJ3Lb9Bvk6e420bUFU=
409+
go.opentelemetry.io/collector/internal/testutil v0.151.0 h1:CFjDItLuqzblItOsnK6IPSdrsOaZCaDjYpB8qWG+XHI=
410+
go.opentelemetry.io/collector/internal/testutil v0.151.0/go.mod h1:Jkjs6rkqs973LqgZ0Fe3zrokQRKULYXPIf4HuqStiEE=
411+
go.opentelemetry.io/collector/pdata v1.57.0 h1:oDWBMjEIqyJO3GJEB+iwqxj47rxDK19OKzwaFEaE4sg=
412+
go.opentelemetry.io/collector/pdata v1.57.0/go.mod h1:wZojinP6mNhLXudH8QXx/bjWzOsKMxi/FXwnk+12G/w=
401413
go.opentelemetry.io/collector/pdata/pprofile v0.148.0 h1:MgrNZmqwhZGfiYwcKKtM/iXgTZqqvG5dUphriRXMZHU=
402414
go.opentelemetry.io/collector/pdata/pprofile v0.148.0/go.mod h1:MTTMnZPqWX1S/rBDatU0W19udlycBkWuzVV5qnemHdc=
403415
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=

main.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ import (
6161
"github.com/parca-dev/parca-agent/flags"
6262
"github.com/parca-dev/parca-agent/oom"
6363
"github.com/parca-dev/parca-agent/parcagpu"
64+
"github.com/parca-dev/parca-agent/probes"
6465
"github.com/parca-dev/parca-agent/reporter"
6566
"github.com/parca-dev/parca-agent/uploader"
6667
)
@@ -432,6 +433,26 @@ func mainWithExitCode() flags.ExitCode {
432433
}
433434
parcaReporter.Start(mainCtx)
434435

436+
if f.ProbeConfig != "" {
437+
if grpcConn == nil {
438+
return flags.Failure("--probe-config requires a remote-store; cannot be used in offline mode")
439+
}
440+
probesSvc, err := probes.Start(mainCtx, probes.StartConfig{
441+
ConfigPath: f.ProbeConfig,
442+
Node: f.Node,
443+
ServiceVersion: buildInfo.VcsRevision,
444+
}, grpcConn)
445+
if err != nil {
446+
return flags.Failure("Failed to start probes: %v", err)
447+
}
448+
parcaReporter.SetProbes(probesSvc)
449+
defer func() {
450+
if err := probesSvc.Close(); err != nil {
451+
log.Warnf("probes: close: %v", err)
452+
}
453+
}()
454+
}
455+
435456
includeEnvVars := libpf.Set[string]{}
436457
if len(f.IncludeEnvVar) > 0 {
437458
for _, env := range f.IncludeEnvVar {

probes/attach.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//go:build linux
2+
3+
package probes
4+
5+
import (
6+
"context"
7+
"sync"
8+
9+
"github.com/cilium/ebpf"
10+
"github.com/cilium/ebpf/link"
11+
log "github.com/sirupsen/logrus"
12+
"go.opentelemetry.io/ebpf-profiler/libpf"
13+
)
14+
15+
// attachReq is enqueued by OnExecutable for the worker goroutine to process.
16+
type attachReq struct {
17+
filePath string
18+
fileID libpf.FileID
19+
specs []ProbeSpec
20+
}
21+
22+
// attacher owns the state for matching new binaries against the spec list and
23+
// attaching uprobes to them on a worker goroutine. The hot-path callback only
24+
// holds the mutex long enough to dedupe by FileID and run regexes.
25+
type attacher struct {
26+
prog *ebpf.Program
27+
specs []ProbeSpec
28+
29+
mu sync.Mutex
30+
attached map[libpf.FileID]struct{}
31+
links map[libpf.FileID][]link.Link
32+
33+
queue chan attachReq
34+
}
35+
36+
func newAttacher(prog *ebpf.Program, specs []ProbeSpec, queueDepth int) *attacher {
37+
return &attacher{
38+
prog: prog,
39+
specs: specs,
40+
attached: make(map[libpf.FileID]struct{}),
41+
links: make(map[libpf.FileID][]link.Link),
42+
queue: make(chan attachReq, queueDepth),
43+
}
44+
}
45+
46+
// OnExecutable is the cheap-path callback invoked from the otel ebpf-profiler
47+
// reporter goroutine. It must not block: dedupe, regex-match, and enqueue.
48+
// All disk I/O happens in attachWorker.
49+
func (a *attacher) OnExecutable(filePath string, fileID libpf.FileID) {
50+
a.mu.Lock()
51+
if _, seen := a.attached[fileID]; seen {
52+
a.mu.Unlock()
53+
return
54+
}
55+
a.attached[fileID] = struct{}{}
56+
a.mu.Unlock()
57+
58+
var matched []ProbeSpec
59+
for _, s := range a.specs {
60+
if s.FileMatchRE.MatchString(filePath) {
61+
matched = append(matched, s)
62+
}
63+
}
64+
if len(matched) == 0 {
65+
return
66+
}
67+
68+
select {
69+
case a.queue <- attachReq{filePath: filePath, fileID: fileID, specs: matched}:
70+
default:
71+
// Queue full: log and forget. We've already marked this fileID as
72+
// "seen" so we won't try again, which is fine for v1 — the user
73+
// can restart with a smaller probe-config or a deeper queue.
74+
log.Warnf("probes: attach queue full, dropping %s (fileID=%s)", filePath, fileID.StringNoQuotes())
75+
}
76+
}
77+
78+
// run is the attachWorker goroutine. Returns when the queue is drained after
79+
// ctx is cancelled.
80+
func (a *attacher) run(ctx context.Context) {
81+
for {
82+
select {
83+
case <-ctx.Done():
84+
return
85+
case req := <-a.queue:
86+
a.handle(req)
87+
}
88+
}
89+
}
90+
91+
func (a *attacher) handle(req attachReq) {
92+
ex, err := link.OpenExecutable(req.filePath)
93+
if err != nil {
94+
log.Warnf("probes: open executable %s: %v", req.filePath, err)
95+
return
96+
}
97+
98+
var newLinks []link.Link
99+
for _, s := range req.specs {
100+
l, err := ex.Uprobe(s.Symbol, a.prog, &link.UprobeOptions{
101+
Cookie: uint64(s.SpecID) << 32,
102+
PID: 0,
103+
})
104+
if err != nil {
105+
log.Warnf("probes: attach %s @ %s: %v", s.Symbol, req.filePath, err)
106+
continue
107+
}
108+
newLinks = append(newLinks, l)
109+
log.Debugf("probes: attached %s @ %s (spec_id=%d)", s.Symbol, req.filePath, s.SpecID)
110+
}
111+
if len(newLinks) == 0 {
112+
return
113+
}
114+
115+
a.mu.Lock()
116+
a.links[req.fileID] = append(a.links[req.fileID], newLinks...)
117+
a.mu.Unlock()
118+
}
119+
120+
// closeAllLinks tears down every attached uprobe link. Called from
121+
// service.Close.
122+
func (a *attacher) closeAllLinks() {
123+
a.mu.Lock()
124+
defer a.mu.Unlock()
125+
for fid, links := range a.links {
126+
for _, l := range links {
127+
if err := l.Close(); err != nil {
128+
log.Warnf("probes: close link for fileID=%s: %v", fid.StringNoQuotes(), err)
129+
}
130+
}
131+
}
132+
a.links = nil
133+
}

0 commit comments

Comments
 (0)