Skip to content
Draft
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
14 changes: 8 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module github.com/grafana/alloy
go 1.25.1

require (
buf.build/gen/go/parca-dev/parca/grpc/go v1.5.1-20250212095114-4db6f2d46517.2
buf.build/gen/go/parca-dev/parca/protocolbuffers/go v1.36.6-20250212095114-4db6f2d46517.1
cloud.google.com/go/pubsub v1.50.1
cloud.google.com/go/pubsub/v2 v2.0.0
connectrpc.com/connect v1.18.1
Expand Down Expand Up @@ -38,7 +40,7 @@ require (
github.com/docker/docker v28.5.1+incompatible
github.com/docker/go-connections v0.6.0
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46
github.com/elastic/go-freelru v0.16.0 // indirect
github.com/elastic/go-freelru v0.16.0
github.com/fatih/color v1.18.0
github.com/fortytw2/leaktest v1.3.0
github.com/fsnotify/fsnotify v1.9.0
Expand Down Expand Up @@ -77,7 +79,7 @@ require (
github.com/grafana/pyroscope-go/godeltaprof v0.1.8
github.com/grafana/pyroscope/api v1.2.0
github.com/grafana/pyroscope/ebpf v0.4.11
github.com/grafana/pyroscope/lidia v0.0.0-20250716102313-506840f4afcd
github.com/grafana/pyroscope/lidia v0.0.0-20250716102313-506840f4afcd // indirect
github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853
github.com/grafana/snowflake-prometheus-exporter v0.0.0-20251023151319-9baba332b98a
github.com/grafana/vmware_exporter v0.0.5-beta.0.20250218170317-73398ba08329
Expand Down Expand Up @@ -304,10 +306,10 @@ require (
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
gotest.tools v2.2.0+incompatible
k8s.io/api v0.34.1
k8s.io/apimachinery v0.34.1
k8s.io/client-go v0.34.1
k8s.io/component-base v0.34.1
k8s.io/api v0.34.2
k8s.io/apimachinery v0.34.2
k8s.io/client-go v0.34.2
k8s.io/component-base v0.34.2
k8s.io/klog/v2 v2.130.1
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4
sigs.k8s.io/controller-runtime v0.22.2
Expand Down
20 changes: 12 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
buf.build/gen/go/parca-dev/parca/grpc/go v1.5.1-20250212095114-4db6f2d46517.2 h1:AiTEEAQ8AHE5udDizcA2r3GNjxxlk4f2Buot/hA2oYM=
buf.build/gen/go/parca-dev/parca/grpc/go v1.5.1-20250212095114-4db6f2d46517.2/go.mod h1:U8BtFPtz71GSALR7K7ALn39RnvrKsD++lJzMI5Gf4fs=
buf.build/gen/go/parca-dev/parca/protocolbuffers/go v1.36.6-20250212095114-4db6f2d46517.1 h1:gXHJuGlWoXUkH9O9Qxw9skNAhIDgNgJx0tYSbI8fjIo=
buf.build/gen/go/parca-dev/parca/protocolbuffers/go v1.36.6-20250212095114-4db6f2d46517.1/go.mod h1:58eXMQL4tavOGzyXIveWU4f3yTFGmLIHxM9uk11DOIo=
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
Expand Down Expand Up @@ -3237,16 +3241,16 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM=
k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk=
k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY=
k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw=
k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI=
k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc=
k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4=
k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY=
k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8=
k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A=
k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0=
k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4=
k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M=
k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE=
k8s.io/component-base v0.34.2 h1:HQRqK9x2sSAsd8+R4xxRirlTjowsg6fWCPwWYeSvogQ=
k8s.io/component-base v0.34.2/go.mod h1:9xw2FHJavUHBFpiGkZoKuYZ5pdtLKe97DEByaA+hHbM=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
Expand Down
38 changes: 7 additions & 31 deletions internal/component/pyroscope/appender.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Appendable interface {
type Appender interface {
Append(ctx context.Context, labels labels.Labels, samples []*RawSample) error
AppendIngest(ctx context.Context, profile *IncomingProfile) error
UploadDebugInfo(ctx context.Context, arg DebugInfoData)
}

type RawSample struct {
Expand Down Expand Up @@ -116,6 +117,12 @@ type appender struct {
writeLatency prometheus.Histogram
}

func (a *appender) UploadDebugInfo(ctx context.Context, arg DebugInfoData) {
for _, c := range a.children {
c.UploadDebugInfo(ctx, arg)
}
}

// Append satisfies the Appender interface.
func (a *appender) Append(ctx context.Context, labels labels.Labels, samples []*RawSample) error {
now := time.Now()
Expand Down Expand Up @@ -155,34 +162,3 @@ func (a *appender) AppendIngest(ctx context.Context, profile *IncomingProfile) e
}
return multiErr
}

type AppendableFunc func(ctx context.Context, labels labels.Labels, samples []*RawSample) error

func (f AppendableFunc) Appender() Appender {
return f
}

func (f AppendableFunc) Append(ctx context.Context, labels labels.Labels, samples []*RawSample) error {
return f(ctx, labels, samples)
}

func (f AppendableFunc) AppendIngest(_ context.Context, _ *IncomingProfile) error {
// This is a no-op implementation
return nil
}

// For testing AppendIngest operations
type AppendableIngestFunc func(ctx context.Context, profile *IncomingProfile) error

func (f AppendableIngestFunc) Appender() Appender {
return f
}

func (f AppendableIngestFunc) AppendIngest(ctx context.Context, p *IncomingProfile) error {
return f(ctx, p)
}

func (f AppendableIngestFunc) Append(_ context.Context, _ labels.Labels, _ []*RawSample) error {
// This is a no-op implementation
return nil
}
41 changes: 41 additions & 0 deletions internal/component/pyroscope/appender_mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package pyroscope

import (
"context"

"github.com/prometheus/prometheus/model/labels"
)

type AppenderMock struct {
AppendIngestFunc func(ctx context.Context, profile *IncomingProfile) error
AppendFunc func(ctx context.Context, labels labels.Labels, samples []*RawSample) error
UploadDebugInfoFunc func(ctx context.Context, arg DebugInfoData)
}

func (a AppenderMock) Append(ctx context.Context, labels labels.Labels, samples []*RawSample) error {
return a.AppendFunc(ctx, labels, samples)
}

func (a AppenderMock) AppendIngest(ctx context.Context, profile *IncomingProfile) error {
return a.AppendIngestFunc(ctx, profile)
}

func (a AppenderMock) UploadDebugInfo(ctx context.Context, arg DebugInfoData) {
a.UploadDebugInfoFunc(ctx, arg)
}

func (a AppenderMock) Appender() Appender {
return a
}

func AppendableFunc(f func(ctx context.Context, labels labels.Labels, samples []*RawSample) error) AppenderMock {
return AppenderMock{
AppendFunc: f,
}
}

func AppendableIngestFunc(f func(ctx context.Context, profile *IncomingProfile) error) AppenderMock {
return AppenderMock{
AppendIngestFunc: f,
}
}
15 changes: 15 additions & 0 deletions internal/component/pyroscope/debuginfo_impl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//go:build linux && (arm64 || amd64)

package pyroscope

import (
"go.opentelemetry.io/ebpf-profiler/libpf"
"go.opentelemetry.io/ebpf-profiler/process"
)

type DebugInfoData struct {
FileID libpf.FileID
FileName string
BuildID string
Open func() (process.ReadAtCloser, error)
}
5 changes: 5 additions & 0 deletions internal/component/pyroscope/debuginfo_stub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build !(linux && (arm64 || amd64))

package pyroscope

type DebugInfoData struct{}
65 changes: 44 additions & 21 deletions internal/component/pyroscope/ebpf/ebpf_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ import (
"github.com/grafana/alloy/internal/component/pyroscope"
"github.com/grafana/alloy/internal/component/pyroscope/ebpf/reporter"
"github.com/grafana/alloy/internal/featuregate"
"github.com/grafana/pyroscope/lidia"
"github.com/oklog/run"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
"go.opentelemetry.io/ebpf-profiler/interpreter/python"
ebpfmetrics "go.opentelemetry.io/ebpf-profiler/metrics"
"go.opentelemetry.io/ebpf-profiler/process"
discovery2 "go.opentelemetry.io/ebpf-profiler/pyroscope/discovery"
"go.opentelemetry.io/ebpf-profiler/pyroscope/dynamicprofiling"
"go.opentelemetry.io/ebpf-profiler/pyroscope/internalshim/controller"
"go.opentelemetry.io/ebpf-profiler/pyroscope/symb/irsymcache"
reporter2 "go.opentelemetry.io/ebpf-profiler/reporter"
metricnoop "go.opentelemetry.io/otel/metric/noop"
)

Expand Down Expand Up @@ -57,20 +58,6 @@ func New(logger log.Logger, reg prometheus.Registerer, id string, args Arguments

appendable := pyroscope.NewFanout(args.ForwardTo, id, reg)

nfs, err := irsymcache.NewFSCache(irsymcache.TableTableFactory{
Options: []lidia.Option{
lidia.WithFiles(),
lidia.WithLines(),
},
}, irsymcache.Options{
SizeEntries: uint32(args.SymbCacheSizeEntries),
Path: args.SymbCachePath,
})
if err != nil {
return nil, err
}
cfg.ExecutableReporter = nfs

if dynamicProfilingPolicy {
cfg.Policy = &dynamicprofiling.ServiceDiscoveryTargetsOnlyPolicy{Discovery: discovery}
} else {
Expand All @@ -88,23 +75,58 @@ func New(logger log.Logger, reg prometheus.Registerer, id string, args Arguments
argsUpdate: make(chan Arguments, 4),
}

cfg.Reporter = reporter.NewPPROF(logger, &reporter.Config{
r := reporter.NewPPROF(logger, &reporter.Config{
ReportInterval: cfg.ReporterInterval,
SamplesPerSecond: int64(cfg.SamplesPerSecond),
Demangle: args.Demangle,
ReporterUnsymbolizedStubs: args.ReporterUnsymbolizedStubs,
ExtraNativeSymbolResolver: nfs,
Consumer: reporter.PPROFConsumerFunc(func(ctx context.Context, ps []reporter.PPROF) {
res.sendProfiles(ctx, ps)
}),
}, discovery)
}, discovery, func(ctx context.Context, ps []reporter.PPROF) {
res.sendProfiles(ctx, ps)
})
cfg.Reporter = r
cfg.ExecutableReporter = ExecutableReporterFunc(func(args *reporter2.ExecutableMetadata) {
if !args.MappingFile.Valid() {
return
}
mf := args.MappingFile.Value()
arg := pyroscope.DebugInfoData{
FileID: mf.FileID,
FileName: mf.FileName.String(),
BuildID: mf.GnuBuildID,
Open: func() (process.ReadAtCloser, error) {
fallback := func() (process.ReadAtCloser, error) {
return args.Process.OpenMappingFile(args.Mapping)
}
if args.DebuglinkFileName == "" {
return fallback()
}
if file, err := args.Process.ExtractAsFile(args.DebuglinkFileName); err != nil {
return fallback()
} else {
if f, err := os.Open(file); err != nil {
return fallback()
} else {
return f, nil
}
}
},
}
res.appendable.Appender().UploadDebugInfo(context.Background(), arg)
})
// todo, should we keep the ontarget lidia symbolizer for a while?
if cfg.VerboseMode {
logrus.SetLevel(logrus.DebugLevel)
}

return res, nil
}

type ExecutableReporterFunc func(md *reporter2.ExecutableMetadata)

func (e ExecutableReporterFunc) ReportExecutable(md *reporter2.ExecutableMetadata) {
e(md)
}

type Component struct {
logger log.Logger
args Arguments
Expand Down Expand Up @@ -158,6 +180,7 @@ func (c *Component) Run(ctx context.Context) error {
}()

var g run.Group

g.Add(func() error {
for {
select {
Expand Down
6 changes: 6 additions & 0 deletions internal/component/pyroscope/ebpf/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type metrics struct {
pprofSamplesTotal *prometheus.CounterVec
ebpfMetrics *ebpfmetrics.Metrics
pprofsDroppedTotal prometheus.Counter
//debugInfoUploadBytes prometheus.Counter
}

func newMetrics(reg prometheus.Registerer) *metrics {
Expand Down Expand Up @@ -51,6 +52,10 @@ func newMetrics(reg prometheus.Registerer) *metrics {
Name: "pyroscope_ebpf_pprof_samples_total",
Help: "Total number of pprof profiles collected by the ebpf component",
}, []string{"service_name"}),
//debugInfoUploadBytes: prometheus.NewCounter(prometheus.CounterOpts{
// Name: "pyroscope_ebpf_debug_info_upload_bytes_total",
// Help: "Total number of bytes uploaded to the debug info endpoint",
//}),
ebpfMetrics: ebpfmetrics.New(reg),
}

Expand All @@ -62,6 +67,7 @@ func newMetrics(reg prometheus.Registerer) *metrics {
m.pprofBytesTotal = util.MustRegisterOrGet(reg, m.pprofBytesTotal).(*prometheus.CounterVec)
m.pprofSamplesTotal = util.MustRegisterOrGet(reg, m.pprofSamplesTotal).(*prometheus.CounterVec)
m.pprofsDroppedTotal = util.MustRegisterOrGet(reg, m.pprofsDroppedTotal).(prometheus.Counter)
//m.debugInfoUploadBytes = util.MustRegisterOrGet(reg, m.debugInfoUploadBytes).(prometheus.Counter)
}

return m
Expand Down
Loading
Loading