Skip to content
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions .chloggen/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ components:
- pkg/xexporterhelper
- pkg/xprocessor
- pkg/xreceiver
- pkg/xscraper
- processor/batch
- processor/memory_limiter
- processor/sample
Expand Down
25 changes: 25 additions & 0 deletions .chloggen/scraper-profiles.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: 'enhancement'

# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
component: pkg/xscraper

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Implement xscraper for Profiles.

# One or more tracking issues or pull requests related to the change
issues: [13915]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [user]
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ receiver/otlpreceiver/ @open-telemetry/collector-approvers
receiver/receiverhelper/ @open-telemetry/collector-approvers
receiver/xreceiver/ @open-telemetry/collector-approvers @mx-psi @dmathieu
scraper/ @open-telemetry/collector-approvers
scraper/xscraper @open-telemetry/collector-approvers
scraper/scraperhelper/ @open-telemetry/collector-approvers
service/ @open-telemetry/collector-approvers
service/internal/graph/ @open-telemetry/collector-approvers
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/utils/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@
"fileprovider",
"filterprocessor",
"filterset",
"florianl",
"fluentbit",
"fluentforward",
"forwardconnector",
Expand Down Expand Up @@ -500,6 +501,7 @@
"xprocessor",
"xprocessorhelper",
"xreceiver",
"xscraper",
"yamlmapprovider",
"yamlprovider",
"yamls",
Expand Down
1 change: 1 addition & 0 deletions scraper/xscraper/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include ../../Makefile.Common
7 changes: 7 additions & 0 deletions scraper/xscraper/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

//go:generate mdatagen metadata.yaml

// Package xscraper allows to define pull based receivers that can be configured using the scraperreceiver.
package xscraper // import "go.opentelemetry.io/collector/scraper/xscraper"
97 changes: 97 additions & 0 deletions scraper/xscraper/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package xscraper // import "go.opentelemetry.io/collector/scraper/xscraper"

import (
"context"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pipeline"
"go.opentelemetry.io/collector/scraper"
)

type Factory interface {
scraper.Factory

// CreateProfiles creates a Profiles scraper based on this config.
// If the scraper type does not support profiles,
// this function returns the error [pipeline.ErrSignalNotSupported].
CreateProfiles(ctx context.Context, set scraper.Settings, cfg component.Config) (Profiles, error)

// ProfilesStability gets the stability level of the Profiles scraper.
ProfilesStability() component.StabilityLevel
}

// FactoryOption apply changes to Options.
type FactoryOption interface {
// applyOption applies the option.
applyOption(o *factoryOpts)
}

type factoryOpts struct {
opts []scraper.FactoryOption
*factory
}

var _ FactoryOption = (*factoryOptionFunc)(nil)

// factoryOptionFunc is a FactoryOption created through a function.
type factoryOptionFunc func(*factoryOpts)

func (f factoryOptionFunc) applyOption(o *factoryOpts) {
f(o)
}

type factory struct {
scraper.Factory

createProfilesFunc CreateProfilesFunc
profilesStabilityLevel component.StabilityLevel
}

func (f *factory) ProfilesStability() component.StabilityLevel {
return f.profilesStabilityLevel
}

func (f *factory) CreateProfiles(ctx context.Context, set scraper.Settings, cfg component.Config) (Profiles, error) {
if f.createProfilesFunc == nil {
return nil, pipeline.ErrSignalNotSupported
}
return f.createProfilesFunc(ctx, set, cfg)
}

// WithLogs overrides the default "error not supported" implementation for CreateLogs and the default "undefined" stability level.
func WithLogs(createLogs scraper.CreateLogsFunc, sl component.StabilityLevel) FactoryOption {
return factoryOptionFunc(func(o *factoryOpts) {
o.opts = append(o.opts, scraper.WithLogs(createLogs, sl))
})
}

// WithMetrics overrides the default "error not supported" implementation for CreateMetrics and the default "undefined" stability level.
func WithMetrics(createMetrics scraper.CreateMetricsFunc, sl component.StabilityLevel) FactoryOption {
return factoryOptionFunc(func(o *factoryOpts) {
o.opts = append(o.opts, scraper.WithMetrics(createMetrics, sl))
})
}

// CreateProfilesFunc is the equivalent of Factory.CreateProfiles().
type CreateProfilesFunc func(context.Context, scraper.Settings, component.Config) (Profiles, error)

// WithProfiles overrides the default "error not supported" implementation for CreateProfiles and the default "undefined" stability level.
func WithProfiles(createProfiles CreateProfilesFunc, sl component.StabilityLevel) FactoryOption {
return factoryOptionFunc(func(o *factoryOpts) {
o.profilesStabilityLevel = sl
o.createProfilesFunc = createProfiles
})
}

// NewFactory returns a Factory.
func NewFactory(cfgType component.Type, createDefaultConfig component.CreateDefaultConfigFunc, options ...FactoryOption) Factory {
opts := factoryOpts{factory: &factory{}}
for _, opt := range options {
opt.applyOption(&opts)
}
opts.Factory = scraper.NewFactory(cfgType, createDefaultConfig, opts.opts...)
return opts.factory
}
88 changes: 88 additions & 0 deletions scraper/xscraper/factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package xscraper

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/pipeline"
"go.opentelemetry.io/collector/scraper"
)

var testType = component.MustNewType("test")

func nopSettings() scraper.Settings {
return scraper.Settings{
ID: component.NewID(testType),
TelemetrySettings: componenttest.NewNopTelemetrySettings(),
}
}

func TestNewFactory(t *testing.T) {
defaultCfg := struct{}{}
f := NewFactory(
testType,
func() component.Config { return &defaultCfg })
assert.Equal(t, testType, f.Type())
assert.EqualValues(t, &defaultCfg, f.CreateDefaultConfig())
_, err := f.CreateProfiles(context.Background(), nopSettings(), &defaultCfg)
require.ErrorIs(t, err, pipeline.ErrSignalNotSupported)
}

func TestNewFactoryWithOptions(t *testing.T) {
testType := component.MustNewType("test")
defaultCfg := struct{}{}
f := NewFactory(
testType,
func() component.Config { return &defaultCfg },
WithLogs(createLogs, component.StabilityLevelAlpha),
WithMetrics(createMetrics, component.StabilityLevelAlpha),
WithProfiles(createProfiles, component.StabilityLevelDevelopment))
assert.Equal(t, testType, f.Type())
assert.EqualValues(t, &defaultCfg, f.CreateDefaultConfig())

assert.Equal(t, component.StabilityLevelDevelopment, f.ProfilesStability())
_, err := f.CreateProfiles(context.Background(), scraper.Settings{}, &defaultCfg)
require.NoError(t, err)

assert.Equal(t, component.StabilityLevelAlpha, f.LogsStability())
_, err = f.CreateLogs(context.Background(), scraper.Settings{}, &defaultCfg)
require.NoError(t, err)

assert.Equal(t, component.StabilityLevelAlpha, f.MetricsStability())
_, err = f.CreateMetrics(context.Background(), scraper.Settings{}, &defaultCfg)
require.NoError(t, err)
}

func createProfiles(context.Context, scraper.Settings, component.Config) (Profiles, error) {
return NewProfiles(newTestScrapeProfilesFunc(nil))
}

func createLogs(context.Context, scraper.Settings, component.Config) (scraper.Logs, error) {
return scraper.NewLogs(newTestScrapeLogsFunc(nil))
}

func createMetrics(context.Context, scraper.Settings, component.Config) (scraper.Metrics, error) {
return scraper.NewMetrics(newTestScrapeMetricsFunc(nil))
}

func newTestScrapeLogsFunc(retError error) scraper.ScrapeLogsFunc {
return func(_ context.Context) (plog.Logs, error) {
return plog.NewLogs(), retError
}
}

func newTestScrapeMetricsFunc(retError error) scraper.ScrapeMetricsFunc {
return func(_ context.Context) (pmetric.Metrics, error) {
return pmetric.NewMetrics(), retError
}
}
13 changes: 13 additions & 0 deletions scraper/xscraper/generated_package_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 62 additions & 0 deletions scraper/xscraper/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module go.opentelemetry.io/collector/scraper/xscraper

go 1.24.0

require (
github.com/stretchr/testify v1.11.1
go.opentelemetry.io/collector/component v1.43.0
go.opentelemetry.io/collector/component/componenttest v0.137.0
go.opentelemetry.io/collector/pdata v1.43.0
go.opentelemetry.io/collector/pdata/pprofile v0.136.0
go.opentelemetry.io/collector/pipeline v1.43.0
go.opentelemetry.io/collector/scraper v0.136.0
go.uber.org/goleak v1.3.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/collector/featuregate v1.43.0 // indirect
go.opentelemetry.io/collector/internal/telemetry v0.137.0 // indirect
go.opentelemetry.io/contrib/bridges/otelzap v0.13.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
go.opentelemetry.io/otel/log v0.14.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/net v0.44.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.29.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect
google.golang.org/grpc v1.76.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace go.opentelemetry.io/collector/pipeline => ../../pipeline

replace go.opentelemetry.io/collector/pdata/pprofile => ../../pdata/pprofile

replace go.opentelemetry.io/collector/component => ../../component

replace go.opentelemetry.io/collector/component/componenttest => ../../component/componenttest

replace go.opentelemetry.io/collector/scraper => ../../scraper

replace go.opentelemetry.io/collector/internal/telemetry => ../../internal/telemetry

replace go.opentelemetry.io/collector/featuregate => ../../featuregate

replace go.opentelemetry.io/collector/pdata => ../../pdata
Loading
Loading