Add a new scraper package to replace scraperhelper (#11657)
Update https://github.com/open-telemetry/opentelemetry-collector/issues/11238 No changelog since this is still in progress. Signed-off-by: Bogdan Drutu <bogdandrutu@gmail.com>
This commit is contained in:
parent
1828211ac8
commit
7ce4842d98
|
|
@ -0,0 +1 @@
|
|||
include ../Makefile.Common
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
# General Information
|
||||
|
||||
A scraper defines how to connect and scrape telemetry data from an external source.
|
||||
|
||||
<!-- status autogenerated section -->
|
||||
| Status | |
|
||||
| ------------- |-----------|
|
||||
| Stability | [development]: metrics |
|
||||
| Issues | [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aopen+is%3Aissue+label%3Apkg%2F) [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aclosed+is%3Aissue+label%3Apkg%2F) |
|
||||
|
||||
[development]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#development
|
||||
<!-- end autogenerated section -->
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//go:generate mdatagen metadata.yaml
|
||||
|
||||
// Package scraper allows to define pull based receivers that can be configured using the scraperreceiver.
|
||||
package scraper // import "go.opentelemetry.io/collector/scraper"
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package scraper // import "go.opentelemetry.io/collector/scraper"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"go.opentelemetry.io/collector/component"
|
||||
"go.opentelemetry.io/collector/pipeline"
|
||||
)
|
||||
|
||||
// Settings configures scraper creators.
|
||||
type Settings struct {
|
||||
// ID returns the ID of the component that will be created.
|
||||
ID component.ID
|
||||
|
||||
component.TelemetrySettings
|
||||
|
||||
// BuildInfo can be used by components for informational purposes.
|
||||
BuildInfo component.BuildInfo
|
||||
}
|
||||
|
||||
// Factory is factory interface for scrapers.
|
||||
//
|
||||
// This interface cannot be directly implemented. Implementations must
|
||||
// use the NewFactory to implement it.
|
||||
type Factory interface {
|
||||
component.Factory
|
||||
|
||||
// CreateMetrics creates a Metrics scraper based on this config.
|
||||
// If the scraper type does not support metrics,
|
||||
// this function returns the error [pipeline.ErrSignalNotSupported].
|
||||
// Implementers can assume `next` is never nil.
|
||||
CreateMetrics(ctx context.Context, set Settings, cfg component.Config) (Metrics, error)
|
||||
|
||||
// MetricsStability gets the stability level of the Metrics scraper.
|
||||
MetricsStability() component.StabilityLevel
|
||||
|
||||
unexportedFactoryFunc()
|
||||
}
|
||||
|
||||
// FactoryOption apply changes to Options.
|
||||
type FactoryOption interface {
|
||||
// applyOption applies the option.
|
||||
applyOption(o *factory)
|
||||
}
|
||||
|
||||
var _ FactoryOption = (*factoryOptionFunc)(nil)
|
||||
|
||||
// factoryOptionFunc is a FactoryOption created through a function.
|
||||
type factoryOptionFunc func(*factory)
|
||||
|
||||
func (f factoryOptionFunc) applyOption(o *factory) {
|
||||
f(o)
|
||||
}
|
||||
|
||||
type factory struct {
|
||||
cfgType component.Type
|
||||
component.CreateDefaultConfigFunc
|
||||
CreateMetricsFunc
|
||||
metricsStabilityLevel component.StabilityLevel
|
||||
}
|
||||
|
||||
func (f *factory) Type() component.Type {
|
||||
return f.cfgType
|
||||
}
|
||||
|
||||
func (f *factory) unexportedFactoryFunc() {}
|
||||
|
||||
func (f *factory) MetricsStability() component.StabilityLevel {
|
||||
return f.metricsStabilityLevel
|
||||
}
|
||||
|
||||
// CreateMetricsFunc is the equivalent of Factory.CreateMetrics().
|
||||
type CreateMetricsFunc func(context.Context, Settings, component.Config) (Metrics, error)
|
||||
|
||||
// CreateMetrics implements Factory.CreateMetrics.
|
||||
func (f CreateMetricsFunc) CreateMetrics(ctx context.Context, set Settings, cfg component.Config) (Metrics, error) {
|
||||
if f == nil {
|
||||
return nil, pipeline.ErrSignalNotSupported
|
||||
}
|
||||
return f(ctx, set, cfg)
|
||||
}
|
||||
|
||||
// WithMetrics overrides the default "error not supported" implementation for CreateMetrics and the default "undefined" stability level.
|
||||
func WithMetrics(createMetrics CreateMetricsFunc, sl component.StabilityLevel) FactoryOption {
|
||||
return factoryOptionFunc(func(o *factory) {
|
||||
o.metricsStabilityLevel = sl
|
||||
o.CreateMetricsFunc = createMetrics
|
||||
})
|
||||
}
|
||||
|
||||
// NewFactory returns a Factory.
|
||||
func NewFactory(cfgType component.Type, createDefaultConfig component.CreateDefaultConfigFunc, options ...FactoryOption) Factory {
|
||||
f := &factory{
|
||||
cfgType: cfgType,
|
||||
CreateDefaultConfigFunc: createDefaultConfig,
|
||||
}
|
||||
for _, opt := range options {
|
||||
opt.applyOption(f)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// MakeFactoryMap takes a list of receiver factories and returns a map with factory type as keys.
|
||||
// It returns a non-nil error when there are factories with duplicate type.
|
||||
func MakeFactoryMap(factories ...Factory) (map[component.Type]Factory, error) {
|
||||
fMap := map[component.Type]Factory{}
|
||||
for _, f := range factories {
|
||||
if _, ok := fMap[f.Type()]; ok {
|
||||
return fMap, fmt.Errorf("duplicate scraper factory %q", f.Type())
|
||||
}
|
||||
fMap[f.Type()] = f
|
||||
}
|
||||
return fMap, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package scraper
|
||||
|
||||
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/pipeline"
|
||||
)
|
||||
|
||||
var testType = component.MustNewType("test")
|
||||
|
||||
func nopSettings() Settings {
|
||||
return Settings{
|
||||
ID: component.NewID(testType),
|
||||
TelemetrySettings: componenttest.NewNopTelemetrySettings()}
|
||||
}
|
||||
|
||||
func TestNewFactory(t *testing.T) {
|
||||
defaultCfg := struct{}{}
|
||||
f := NewFactory(
|
||||
testType,
|
||||
func() component.Config { return &defaultCfg })
|
||||
assert.EqualValues(t, testType, f.Type())
|
||||
assert.EqualValues(t, &defaultCfg, f.CreateDefaultConfig())
|
||||
_, err := f.CreateMetrics(context.Background(), nopSettings(), &defaultCfg)
|
||||
require.ErrorIs(t, err, pipeline.ErrSignalNotSupported)
|
||||
}
|
||||
|
||||
func TestNewFactoryWithOptions(t *testing.T) {
|
||||
var testType = component.MustNewType("test")
|
||||
defaultCfg := struct{}{}
|
||||
f := NewFactory(
|
||||
testType,
|
||||
func() component.Config { return &defaultCfg },
|
||||
WithMetrics(createMetrics, component.StabilityLevelAlpha))
|
||||
assert.EqualValues(t, testType, f.Type())
|
||||
assert.EqualValues(t, &defaultCfg, f.CreateDefaultConfig())
|
||||
|
||||
assert.Equal(t, component.StabilityLevelAlpha, f.MetricsStability())
|
||||
_, err := f.CreateMetrics(context.Background(), Settings{}, &defaultCfg)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestMakeFactoryMap(t *testing.T) {
|
||||
type testCase struct {
|
||||
name string
|
||||
in []Factory
|
||||
out map[component.Type]Factory
|
||||
}
|
||||
|
||||
p1 := NewFactory(component.MustNewType("p1"), nil)
|
||||
p2 := NewFactory(component.MustNewType("p2"), nil)
|
||||
testCases := []testCase{
|
||||
{
|
||||
name: "different names",
|
||||
in: []Factory{p1, p2},
|
||||
out: map[component.Type]Factory{
|
||||
p1.Type(): p1,
|
||||
p2.Type(): p2,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "same name",
|
||||
in: []Factory{p1, p2, NewFactory(component.MustNewType("p1"), nil)},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
out, err := MakeFactoryMap(tt.in...)
|
||||
if tt.out == nil {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tt.out, out)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createMetrics(context.Context, Settings, component.Config) (Metrics, error) {
|
||||
return NewMetrics(context.Background(), nopSettings(), newTestScrapeMetricsFunc(nil))
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Code generated by mdatagen. DO NOT EDIT.
|
||||
|
||||
package scraper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go.uber.org/goleak"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
goleak.VerifyTestMain(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
module go.opentelemetry.io/collector/scraper
|
||||
|
||||
go 1.22.0
|
||||
|
||||
require (
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.opentelemetry.io/collector/component v0.113.0
|
||||
go.opentelemetry.io/collector/component/componenttest v0.113.0
|
||||
go.opentelemetry.io/collector/pdata v1.19.0
|
||||
go.opentelemetry.io/collector/pipeline v0.113.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.2 // 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/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.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
go.opentelemetry.io/collector/config/configtelemetry v0.113.0 // indirect
|
||||
go.opentelemetry.io/otel v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.32.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/net v0.28.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
google.golang.org/grpc v1.67.1 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace go.opentelemetry.io/collector/config/configtelemetry => ../config/configtelemetry
|
||||
|
||||
replace go.opentelemetry.io/collector/pipeline => ../pipeline
|
||||
|
||||
replace go.opentelemetry.io/collector/pdata => ../pdata
|
||||
|
||||
replace go.opentelemetry.io/collector/component => ../component
|
||||
|
||||
replace go.opentelemetry.io/collector/component/componenttest => ../component/componenttest
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
||||
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
|
||||
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
|
||||
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
|
||||
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
||||
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
type: service
|
||||
github_project: open-telemetry/opentelemetry-collector
|
||||
|
||||
status:
|
||||
class: pkg
|
||||
stability:
|
||||
development: [metrics]
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package scraper // import "go.opentelemetry.io/collector/scraper"
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/collector/component"
|
||||
"go.opentelemetry.io/collector/pdata/pmetric"
|
||||
)
|
||||
|
||||
// Metrics is the base interface for metrics scrapers.
|
||||
type Metrics interface {
|
||||
component.Component
|
||||
|
||||
ScrapeMetrics(context.Context) (pmetric.Metrics, error)
|
||||
}
|
||||
|
||||
// ScrapeMetricsFunc is a helper function that is similar to Metrics.ScrapeMetrics.
|
||||
type ScrapeMetricsFunc ScrapeFunc[pmetric.Metrics]
|
||||
|
||||
func (sf ScrapeMetricsFunc) ScrapeMetrics(ctx context.Context) (pmetric.Metrics, error) {
|
||||
return sf(ctx)
|
||||
}
|
||||
|
||||
type metrics struct {
|
||||
baseScraper
|
||||
ScrapeMetricsFunc
|
||||
}
|
||||
|
||||
// NewMetrics creates a new Metrics scraper.
|
||||
func NewMetrics(_ context.Context, _ Settings, scrape ScrapeMetricsFunc, options ...Option) (Metrics, error) {
|
||||
if scrape == nil {
|
||||
return nil, errNilFunc
|
||||
}
|
||||
bs := &metrics{
|
||||
baseScraper: newBaseScraper(options),
|
||||
ScrapeMetricsFunc: scrape,
|
||||
}
|
||||
|
||||
return bs, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package scraper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
"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/pmetric"
|
||||
)
|
||||
|
||||
func TestNewMetrics(t *testing.T) {
|
||||
mp, err := NewMetrics(context.Background(), nopSettings(), newTestScrapeMetricsFunc(nil))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, mp.Start(context.Background(), componenttest.NewNopHost()))
|
||||
md, err := mp.ScrapeMetrics(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, pmetric.NewMetrics(), md)
|
||||
require.NoError(t, mp.Shutdown(context.Background()))
|
||||
}
|
||||
|
||||
func TestNewMetrics_WithOptions(t *testing.T) {
|
||||
want := errors.New("my_error")
|
||||
mp, err := NewMetrics(context.Background(), nopSettings(), newTestScrapeMetricsFunc(nil),
|
||||
WithStart(func(context.Context, component.Host) error { return want }),
|
||||
WithShutdown(func(context.Context) error { return want }))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, want, mp.Start(context.Background(), componenttest.NewNopHost()))
|
||||
assert.Equal(t, want, mp.Shutdown(context.Background()))
|
||||
}
|
||||
|
||||
func TestNewMetrics_NilRequiredFields(t *testing.T) {
|
||||
_, err := NewMetrics(context.Background(), nopSettings(), nil)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestNewMetrics_ProcessMetricsError(t *testing.T) {
|
||||
want := errors.New("my_error")
|
||||
mp, err := NewMetrics(context.Background(), nopSettings(), newTestScrapeMetricsFunc(want))
|
||||
require.NoError(t, err)
|
||||
_, err = mp.ScrapeMetrics(context.Background())
|
||||
require.ErrorIs(t, err, want)
|
||||
}
|
||||
|
||||
func TestMetricsConcurrency(t *testing.T) {
|
||||
incomingMetrics := pmetric.NewMetrics()
|
||||
dps := incomingMetrics.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty().SetEmptySum().DataPoints()
|
||||
|
||||
// Add 2 data points to the incoming
|
||||
dps.AppendEmpty()
|
||||
dps.AppendEmpty()
|
||||
|
||||
mp, err := NewMetrics(context.Background(), nopSettings(), newTestScrapeMetricsFunc(nil))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, mp.Start(context.Background(), componenttest.NewNopHost()))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for j := 0; j < 10000; j++ {
|
||||
_, errScrape := mp.ScrapeMetrics(context.Background())
|
||||
assert.NoError(t, errScrape)
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
require.NoError(t, mp.Shutdown(context.Background()))
|
||||
}
|
||||
|
||||
func newTestScrapeMetricsFunc(retError error) ScrapeMetricsFunc {
|
||||
return func(_ context.Context) (pmetric.Metrics, error) {
|
||||
return pmetric.NewMetrics(), retError
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package scraper // import "go.opentelemetry.io/collector/scraper"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"go.opentelemetry.io/collector/component"
|
||||
)
|
||||
|
||||
var errNilFunc = errors.New("nil scrape func")
|
||||
|
||||
// ScrapeFunc scrapes metrics.
|
||||
type ScrapeFunc[T any] func(context.Context) (T, error)
|
||||
|
||||
// Option apply changes to internal options.
|
||||
type Option interface {
|
||||
apply(*baseScraper)
|
||||
}
|
||||
|
||||
type scraperOptionFunc func(*baseScraper)
|
||||
|
||||
func (of scraperOptionFunc) apply(e *baseScraper) {
|
||||
of(e)
|
||||
}
|
||||
|
||||
// WithStart sets the function that will be called on startup.
|
||||
func WithStart(start component.StartFunc) Option {
|
||||
return scraperOptionFunc(func(o *baseScraper) {
|
||||
o.StartFunc = start
|
||||
})
|
||||
}
|
||||
|
||||
// WithShutdown sets the function that will be called on shutdown.
|
||||
func WithShutdown(shutdown component.ShutdownFunc) Option {
|
||||
return scraperOptionFunc(func(o *baseScraper) {
|
||||
o.ShutdownFunc = shutdown
|
||||
})
|
||||
}
|
||||
|
||||
type baseScraper struct {
|
||||
component.StartFunc
|
||||
component.ShutdownFunc
|
||||
}
|
||||
|
||||
// newBaseScraper returns the internal settings starting from the default and applying all options.
|
||||
func newBaseScraper(options []Option) baseScraper {
|
||||
// Start from the default options:
|
||||
bs := baseScraper{}
|
||||
|
||||
for _, op := range options {
|
||||
op.apply(&bs)
|
||||
}
|
||||
|
||||
return bs
|
||||
}
|
||||
|
|
@ -76,6 +76,7 @@ module-sets:
|
|||
- go.opentelemetry.io/collector/receiver/otlpreceiver
|
||||
- go.opentelemetry.io/collector/receiver/receiverprofiles
|
||||
- go.opentelemetry.io/collector/receiver/receivertest
|
||||
- go.opentelemetry.io/collector/scraper
|
||||
- go.opentelemetry.io/collector/semconv
|
||||
- go.opentelemetry.io/collector/service
|
||||
- go.opentelemetry.io/collector/filter
|
||||
|
|
|
|||
Loading…
Reference in New Issue