Skip to content

Commit 716e11a

Browse files
florianlmx-psi
andauthored
[xscraper] add Profiles support (#13915)
#### Description Implement scraper for Profiles. This will help implement receiver parts like open-telemetry/opentelemetry-collector-contrib#42843. --------- Signed-off-by: Florian Lehner <[email protected]> Co-authored-by: Pablo Baeyens <[email protected]>
1 parent 116c181 commit 716e11a

File tree

16 files changed

+547
-0
lines changed

16 files changed

+547
-0
lines changed

.chloggen/config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ components:
5050
- pkg/xexporterhelper
5151
- pkg/xprocessor
5252
- pkg/xreceiver
53+
- pkg/xscraper
5354
- processor/batch
5455
- processor/memory_limiter
5556
- processor/sample

.chloggen/scraper-profiles.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: 'enhancement'
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
7+
component: pkg/xscraper
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Implement xscraper for Profiles.
11+
12+
# One or more tracking issues or pull requests related to the change
13+
issues: [13915]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# Optional: The change log or logs in which this entry should be included.
21+
# e.g. '[user]' or '[user, api]'
22+
# Include 'user' if the change is relevant to end users.
23+
# Include 'api' if there is a change to a library API.
24+
# Default: '[user]'
25+
change_logs: [user]

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ receiver/otlpreceiver/ @open-telemetry/collector-approvers
6060
receiver/receiverhelper/ @open-telemetry/collector-approvers
6161
receiver/xreceiver/ @open-telemetry/collector-approvers @mx-psi @dmathieu
6262
scraper/ @open-telemetry/collector-approvers
63+
scraper/xscraper @open-telemetry/collector-approvers
6364
scraper/scraperhelper/ @open-telemetry/collector-approvers
6465
service/ @open-telemetry/collector-approvers
6566
service/internal/graph/ @open-telemetry/collector-approvers

.github/workflows/utils/cspell.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@
221221
"fileprovider",
222222
"filterprocessor",
223223
"filterset",
224+
"florianl",
224225
"fluentbit",
225226
"fluentforward",
226227
"forwardconnector",
@@ -503,6 +504,7 @@
503504
"xprocessor",
504505
"xprocessorhelper",
505506
"xreceiver",
507+
"xscraper",
506508
"yamlmapprovider",
507509
"yamlprovider",
508510
"yamls",

scraper/xscraper/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include ../../Makefile.Common

scraper/xscraper/doc.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//go:generate mdatagen metadata.yaml
5+
6+
// Package xscraper allows to define pull based receivers that can be configured using the scraperreceiver.
7+
package xscraper // import "go.opentelemetry.io/collector/scraper/xscraper"

scraper/xscraper/factory.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package xscraper // import "go.opentelemetry.io/collector/scraper/xscraper"
5+
6+
import (
7+
"context"
8+
9+
"go.opentelemetry.io/collector/component"
10+
"go.opentelemetry.io/collector/pipeline"
11+
"go.opentelemetry.io/collector/scraper"
12+
)
13+
14+
type Factory interface {
15+
scraper.Factory
16+
17+
// CreateProfiles creates a Profiles scraper based on this config.
18+
// If the scraper type does not support profiles,
19+
// this function returns the error [pipeline.ErrSignalNotSupported].
20+
CreateProfiles(ctx context.Context, set scraper.Settings, cfg component.Config) (Profiles, error)
21+
22+
// ProfilesStability gets the stability level of the Profiles scraper.
23+
ProfilesStability() component.StabilityLevel
24+
}
25+
26+
// FactoryOption apply changes to Options.
27+
type FactoryOption interface {
28+
// applyOption applies the option.
29+
applyOption(o *factoryOpts)
30+
}
31+
32+
type factoryOpts struct {
33+
opts []scraper.FactoryOption
34+
*factory
35+
}
36+
37+
var _ FactoryOption = (*factoryOptionFunc)(nil)
38+
39+
// factoryOptionFunc is a FactoryOption created through a function.
40+
type factoryOptionFunc func(*factoryOpts)
41+
42+
func (f factoryOptionFunc) applyOption(o *factoryOpts) {
43+
f(o)
44+
}
45+
46+
type factory struct {
47+
scraper.Factory
48+
49+
createProfilesFunc CreateProfilesFunc
50+
profilesStabilityLevel component.StabilityLevel
51+
}
52+
53+
func (f *factory) ProfilesStability() component.StabilityLevel {
54+
return f.profilesStabilityLevel
55+
}
56+
57+
func (f *factory) CreateProfiles(ctx context.Context, set scraper.Settings, cfg component.Config) (Profiles, error) {
58+
if f.createProfilesFunc == nil {
59+
return nil, pipeline.ErrSignalNotSupported
60+
}
61+
return f.createProfilesFunc(ctx, set, cfg)
62+
}
63+
64+
// WithLogs overrides the default "error not supported" implementation for CreateLogs and the default "undefined" stability level.
65+
func WithLogs(createLogs scraper.CreateLogsFunc, sl component.StabilityLevel) FactoryOption {
66+
return factoryOptionFunc(func(o *factoryOpts) {
67+
o.opts = append(o.opts, scraper.WithLogs(createLogs, sl))
68+
})
69+
}
70+
71+
// WithMetrics overrides the default "error not supported" implementation for CreateMetrics and the default "undefined" stability level.
72+
func WithMetrics(createMetrics scraper.CreateMetricsFunc, sl component.StabilityLevel) FactoryOption {
73+
return factoryOptionFunc(func(o *factoryOpts) {
74+
o.opts = append(o.opts, scraper.WithMetrics(createMetrics, sl))
75+
})
76+
}
77+
78+
// CreateProfilesFunc is the equivalent of Factory.CreateProfiles().
79+
type CreateProfilesFunc func(context.Context, scraper.Settings, component.Config) (Profiles, error)
80+
81+
// WithProfiles overrides the default "error not supported" implementation for CreateProfiles and the default "undefined" stability level.
82+
func WithProfiles(createProfiles CreateProfilesFunc, sl component.StabilityLevel) FactoryOption {
83+
return factoryOptionFunc(func(o *factoryOpts) {
84+
o.profilesStabilityLevel = sl
85+
o.createProfilesFunc = createProfiles
86+
})
87+
}
88+
89+
// NewFactory returns a Factory.
90+
func NewFactory(cfgType component.Type, createDefaultConfig component.CreateDefaultConfigFunc, options ...FactoryOption) Factory {
91+
opts := factoryOpts{factory: &factory{}}
92+
for _, opt := range options {
93+
opt.applyOption(&opts)
94+
}
95+
opts.Factory = scraper.NewFactory(cfgType, createDefaultConfig, opts.opts...)
96+
return opts.factory
97+
}

scraper/xscraper/factory_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package xscraper
5+
6+
import (
7+
"context"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
13+
"go.opentelemetry.io/collector/component"
14+
"go.opentelemetry.io/collector/component/componenttest"
15+
"go.opentelemetry.io/collector/pdata/plog"
16+
"go.opentelemetry.io/collector/pdata/pmetric"
17+
"go.opentelemetry.io/collector/pipeline"
18+
"go.opentelemetry.io/collector/scraper"
19+
)
20+
21+
var testType = component.MustNewType("test")
22+
23+
func nopSettings() scraper.Settings {
24+
return scraper.Settings{
25+
ID: component.NewID(testType),
26+
TelemetrySettings: componenttest.NewNopTelemetrySettings(),
27+
}
28+
}
29+
30+
func TestNewFactory(t *testing.T) {
31+
defaultCfg := struct{}{}
32+
f := NewFactory(
33+
testType,
34+
func() component.Config { return &defaultCfg })
35+
assert.Equal(t, testType, f.Type())
36+
assert.EqualValues(t, &defaultCfg, f.CreateDefaultConfig())
37+
_, err := f.CreateProfiles(context.Background(), nopSettings(), &defaultCfg)
38+
require.ErrorIs(t, err, pipeline.ErrSignalNotSupported)
39+
}
40+
41+
func TestNewFactoryWithOptions(t *testing.T) {
42+
testType := component.MustNewType("test")
43+
defaultCfg := struct{}{}
44+
f := NewFactory(
45+
testType,
46+
func() component.Config { return &defaultCfg },
47+
WithLogs(createLogs, component.StabilityLevelAlpha),
48+
WithMetrics(createMetrics, component.StabilityLevelAlpha),
49+
WithProfiles(createProfiles, component.StabilityLevelDevelopment))
50+
assert.Equal(t, testType, f.Type())
51+
assert.EqualValues(t, &defaultCfg, f.CreateDefaultConfig())
52+
53+
assert.Equal(t, component.StabilityLevelDevelopment, f.ProfilesStability())
54+
_, err := f.CreateProfiles(context.Background(), scraper.Settings{}, &defaultCfg)
55+
require.NoError(t, err)
56+
57+
assert.Equal(t, component.StabilityLevelAlpha, f.LogsStability())
58+
_, err = f.CreateLogs(context.Background(), scraper.Settings{}, &defaultCfg)
59+
require.NoError(t, err)
60+
61+
assert.Equal(t, component.StabilityLevelAlpha, f.MetricsStability())
62+
_, err = f.CreateMetrics(context.Background(), scraper.Settings{}, &defaultCfg)
63+
require.NoError(t, err)
64+
}
65+
66+
func createProfiles(context.Context, scraper.Settings, component.Config) (Profiles, error) {
67+
return NewProfiles(newTestScrapeProfilesFunc(nil))
68+
}
69+
70+
func createLogs(context.Context, scraper.Settings, component.Config) (scraper.Logs, error) {
71+
return scraper.NewLogs(newTestScrapeLogsFunc(nil))
72+
}
73+
74+
func createMetrics(context.Context, scraper.Settings, component.Config) (scraper.Metrics, error) {
75+
return scraper.NewMetrics(newTestScrapeMetricsFunc(nil))
76+
}
77+
78+
func newTestScrapeLogsFunc(retError error) scraper.ScrapeLogsFunc {
79+
return func(_ context.Context) (plog.Logs, error) {
80+
return plog.NewLogs(), retError
81+
}
82+
}
83+
84+
func newTestScrapeMetricsFunc(retError error) scraper.ScrapeMetricsFunc {
85+
return func(_ context.Context) (pmetric.Metrics, error) {
86+
return pmetric.NewMetrics(), retError
87+
}
88+
}

scraper/xscraper/generated_package_test.go

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scraper/xscraper/go.mod

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
module go.opentelemetry.io/collector/scraper/xscraper
2+
3+
go 1.24.0
4+
5+
require (
6+
github.com/stretchr/testify v1.11.1
7+
go.opentelemetry.io/collector/component v1.46.0
8+
go.opentelemetry.io/collector/component/componenttest v0.140.0
9+
go.opentelemetry.io/collector/pdata v1.46.0
10+
go.opentelemetry.io/collector/pdata/pprofile v0.136.0
11+
go.opentelemetry.io/collector/pipeline v1.46.0
12+
go.opentelemetry.io/collector/scraper v0.136.0
13+
go.uber.org/goleak v1.3.0
14+
)
15+
16+
require (
17+
github.com/davecgh/go-spew v1.1.1 // indirect
18+
github.com/go-logr/logr v1.4.3 // indirect
19+
github.com/go-logr/stdr v1.2.2 // indirect
20+
github.com/google/uuid v1.6.0 // indirect
21+
github.com/hashicorp/go-version v1.7.0 // indirect
22+
github.com/json-iterator/go v1.1.12 // indirect
23+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
24+
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
25+
github.com/pmezard/go-difflib v1.0.0 // indirect
26+
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
27+
go.opentelemetry.io/collector/featuregate v1.46.0 // indirect
28+
go.opentelemetry.io/otel v1.38.0 // indirect
29+
go.opentelemetry.io/otel/metric v1.38.0 // indirect
30+
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
31+
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
32+
go.opentelemetry.io/otel/trace v1.38.0 // indirect
33+
go.uber.org/multierr v1.11.0 // indirect
34+
go.uber.org/zap v1.27.0 // indirect
35+
golang.org/x/sys v0.37.0 // indirect
36+
gopkg.in/yaml.v3 v3.0.1 // indirect
37+
)
38+
39+
replace go.opentelemetry.io/collector/pipeline => ../../pipeline
40+
41+
replace go.opentelemetry.io/collector/pdata/pprofile => ../../pdata/pprofile
42+
43+
replace go.opentelemetry.io/collector/component => ../../component
44+
45+
replace go.opentelemetry.io/collector/component/componenttest => ../../component/componenttest
46+
47+
replace go.opentelemetry.io/collector/scraper => ../../scraper
48+
49+
replace go.opentelemetry.io/collector/featuregate => ../../featuregate
50+
51+
replace go.opentelemetry.io/collector/pdata => ../../pdata

0 commit comments

Comments
 (0)