Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add stability level to component factory #5580

Merged
Merged
Show file tree
Hide file tree
Changes from 4 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
47 changes: 46 additions & 1 deletion component/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,40 @@ const (
KindExtension
)

// StabilityLevel represents the stability level of the component created by the factory.
mx-psi marked this conversation as resolved.
Show resolved Hide resolved
// The stability level is used to determine if the component should be used in production
// or not. For more details see:
// https://github.com/open-telemetry/opentelemetry-collector#stability-levels
type StabilityLevel int

const (
StabilityLevelUndefined = iota // skip 0, start types from 1.
StabilityLevelUnmaintained
StabilityLevelDeprecated
StabilityLevelInDevelopment
StabilityLevelAlpha
StabilityLevelBeta
StabilityLevelStable
)

func (sl StabilityLevel) String() string {
switch sl {
case StabilityLevelUnmaintained:
return "unmaintained"
case StabilityLevelDeprecated:
return "deprecated"
case StabilityLevelInDevelopment:
return "in development"
case StabilityLevelAlpha:
return "alpha"
case StabilityLevelBeta:
return "beta"
case StabilityLevelStable:
return "stable"
}
return "undefined"
}

// Factory is implemented by all component factories.
//
// This interface cannot be directly implemented. Implementations must
Expand All @@ -112,15 +146,26 @@ type Factory interface {
// Type gets the type of the component created by this factory.
Type() config.Type

// StabilityLevel gets the stability level of the component.
StabilityLevel(config.DataType) StabilityLevel

unexportedFactoryFunc()
}

type baseFactory struct {
cfgType config.Type
cfgType config.Type
stability map[config.Type]StabilityLevel
}

func (baseFactory) unexportedFactoryFunc() {}

func (bf baseFactory) Type() config.Type {
return bf.cfgType
}

func (bf baseFactory) StabilityLevel(dt config.DataType) StabilityLevel {
if val, ok := bf.stability[dt]; ok {
return val
}
return StabilityLevelUndefined
}
7 changes: 4 additions & 3 deletions component/componenttest/nop_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ func NewNopExporterFactory() component.ExporterFactory {
ExporterSettings: config.NewExporterSettings(config.NewComponentID("nop")),
}
},
component.WithTracesExporter(createTracesExporter),
component.WithMetricsExporter(createMetricsExporter),
component.WithLogsExporter(createLogsExporter))
component.WithTracesExporterAndStabilityLevel(createTracesExporter, component.StabilityLevelInDevelopment),
component.WithMetricsExporterAndStabilityLevel(createMetricsExporter, component.StabilityLevelInDevelopment),
component.WithLogsExporterAndStabilityLevel(createLogsExporter, component.StabilityLevelInDevelopment),
)
}

func createTracesExporter(context.Context, component.ExporterCreateSettings, config.Exporter) (component.TracesExporter, error) {
Expand Down
29 changes: 28 additions & 1 deletion component/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,30 +149,57 @@ type exporterFactory struct {
}

// WithTracesExporter overrides the default "error not supported" implementation for CreateTracesExporter.
// Deprecated: [v0.55.0] Use WithTracesExporterAndStabilityLevel instead.
codeboten marked this conversation as resolved.
Show resolved Hide resolved
func WithTracesExporter(createTracesExporter CreateTracesExporterFunc) ExporterFactoryOption {
return exporterFactoryOptionFunc(func(o *exporterFactory) {
o.CreateTracesExporterFunc = createTracesExporter
})
}

// WithTracesExporterAndStabilityLevel overrides the default "error not supported" implementation for CreateTracesExporter and the default "undefined" stability level.
func WithTracesExporterAndStabilityLevel(createTracesExporter CreateTracesExporterFunc, sl StabilityLevel) ExporterFactoryOption {
return exporterFactoryOptionFunc(func(o *exporterFactory) {
o.stability[config.TracesDataType] = sl
o.CreateTracesExporterFunc = createTracesExporter
})
}

// WithMetricsExporter overrides the default "error not supported" implementation for CreateMetricsExporter.
// Deprecated: [v0.55.0] Use WithMetricsExporterAndStabilityLevel instead.
func WithMetricsExporter(createMetricsExporter CreateMetricsExporterFunc) ExporterFactoryOption {
return exporterFactoryOptionFunc(func(o *exporterFactory) {
o.CreateMetricsExporterFunc = createMetricsExporter
})
}

// WithMetricsExporterAndStabilityLevel overrides the default "error not supported" implementation for CreateMetricsExporter and the default "undefined" stability level.
func WithMetricsExporterAndStabilityLevel(createMetricsExporter CreateMetricsExporterFunc, sl StabilityLevel) ExporterFactoryOption {
return exporterFactoryOptionFunc(func(o *exporterFactory) {
o.stability[config.MetricsDataType] = sl
o.CreateMetricsExporterFunc = createMetricsExporter
})
}

// WithLogsExporter overrides the default "error not supported" implementation for CreateLogsExporter.
// Deprecated: [v0.55.0] Use WithLogsExporterAndStabilityLevel instead.
func WithLogsExporter(createLogsExporter CreateLogsExporterFunc) ExporterFactoryOption {
return exporterFactoryOptionFunc(func(o *exporterFactory) {
o.CreateLogsExporterFunc = createLogsExporter
})
}

// WithLogsExporterAndStabilityLevel overrides the default "error not supported" implementation for CreateLogsExporter and the default "undefined" stability level.
func WithLogsExporterAndStabilityLevel(createLogsExporter CreateLogsExporterFunc, sl StabilityLevel) ExporterFactoryOption {
return exporterFactoryOptionFunc(func(o *exporterFactory) {
o.stability[config.LogsDataType] = sl
o.CreateLogsExporterFunc = createLogsExporter
})
}

// NewExporterFactory returns a ExporterFactory.
func NewExporterFactory(cfgType config.Type, createDefaultConfig ExporterCreateDefaultConfigFunc, options ...ExporterFactoryOption) ExporterFactory {
mx-psi marked this conversation as resolved.
Show resolved Hide resolved
f := &exporterFactory{
baseFactory: baseFactory{cfgType: cfgType},
baseFactory: baseFactory{cfgType: cfgType, stability: map[config.Type]StabilityLevel{}},
ExporterCreateDefaultConfigFunc: createDefaultConfig,
}
for _, opt := range options {
Expand Down
7 changes: 4 additions & 3 deletions exporter/loggingexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ func NewFactory() component.ExporterFactory {
return component.NewExporterFactory(
typeStr,
createDefaultConfig,
component.WithTracesExporter(createTracesExporter),
component.WithMetricsExporter(createMetricsExporter),
component.WithLogsExporter(createLogsExporter))
component.WithTracesExporterAndStabilityLevel(createTracesExporter, component.StabilityLevelInDevelopment),
component.WithMetricsExporterAndStabilityLevel(createMetricsExporter, component.StabilityLevelInDevelopment),
component.WithLogsExporterAndStabilityLevel(createLogsExporter, component.StabilityLevelInDevelopment),
)
}

func createDefaultConfig() config.Exporter {
Expand Down
7 changes: 4 additions & 3 deletions exporter/otlpexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ func NewFactory() component.ExporterFactory {
return component.NewExporterFactory(
typeStr,
createDefaultConfig,
component.WithTracesExporter(createTracesExporter),
component.WithMetricsExporter(createMetricsExporter),
component.WithLogsExporter(createLogsExporter))
component.WithTracesExporterAndStabilityLevel(createTracesExporter, component.StabilityLevelStable),
component.WithMetricsExporterAndStabilityLevel(createMetricsExporter, component.StabilityLevelStable),
component.WithLogsExporterAndStabilityLevel(createLogsExporter, component.StabilityLevelBeta),
)
}

func createDefaultConfig() config.Exporter {
Expand Down
7 changes: 4 additions & 3 deletions exporter/otlphttpexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ func NewFactory() component.ExporterFactory {
return component.NewExporterFactory(
typeStr,
createDefaultConfig,
component.WithTracesExporter(createTracesExporter),
component.WithMetricsExporter(createMetricsExporter),
component.WithLogsExporter(createLogsExporter))
component.WithTracesExporterAndStabilityLevel(createTracesExporter, component.StabilityLevelStable),
component.WithMetricsExporterAndStabilityLevel(createMetricsExporter, component.StabilityLevelStable),
component.WithLogsExporterAndStabilityLevel(createLogsExporter, component.StabilityLevelBeta),
)
}

func createDefaultConfig() config.Exporter {
Expand Down
16 changes: 10 additions & 6 deletions internal/testcomponents/example_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import (
"go.opentelemetry.io/collector/pdata/ptrace"
)

const expType = "exampleexporter"
const (
typeStr = "exampleexporter"
stability = component.StabilityLevelInDevelopment
)

// ExampleExporterConfig config for ExampleExporter.
type ExampleExporterConfig struct {
Expand All @@ -34,15 +37,16 @@ type ExampleExporterConfig struct {

// ExampleExporterFactory is factory for ExampleExporter.
var ExampleExporterFactory = component.NewExporterFactory(
expType,
typeStr,
createExporterDefaultConfig,
component.WithTracesExporter(createTracesExporter),
component.WithMetricsExporter(createMetricsExporter),
component.WithLogsExporter(createLogsExporter))
component.WithTracesExporterAndStabilityLevel(createTracesExporter, stability),
component.WithMetricsExporterAndStabilityLevel(createMetricsExporter, stability),
component.WithLogsExporterAndStabilityLevel(createLogsExporter, stability),
)

func createExporterDefaultConfig() config.Exporter {
return &ExampleExporterConfig{
ExporterSettings: config.NewExporterSettings(config.NewComponentID(expType)),
ExporterSettings: config.NewExporterSettings(config.NewComponentID(typeStr)),
}
}

Expand Down
1 change: 1 addition & 0 deletions service/internal/components/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ const (
ZapKindPipeline = "pipeline"
ZapNameKey = "name"
ZapDataTypeKey = "data_type"
ZapStabilityKey = "stability"
)
22 changes: 21 additions & 1 deletion service/internal/pipelines/pipelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ type Pipelines struct {

// StartAll starts all pipelines.
//
// Start with exporters, processors (in revers configured order), then receivers.
// Start with exporters, processors (in reverse configured order), then receivers.
// This is important so that components that are earlier in the pipeline and reference components that are
// later in the pipeline do not start sending data to later components which are not yet started.
func (bps *Pipelines) StartAll(ctx context.Context, host component.Host) error {
Expand Down Expand Up @@ -304,6 +304,25 @@ func Build(ctx context.Context, settings component.TelemetrySettings, buildInfo
return exps, nil
}

func logStabilityMessage(logger *zap.Logger, sl component.StabilityLevel) {
codeboten marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have a "InfoMessage" (or find a better name) on component.StabilityLevel (can even accept zap.Log or return the string) to help with this?

Reason: you forget to do the same in extensions package, where you will need to duplicate this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I thought about it and ended up choosing to go this route, but you're right we'll need the same thing for extensions.

I'll follow up this PR with a fix for this that can be used in extensions

switch sl {
case component.StabilityLevelDeprecated:
logger.Info("Component has been deprecated and will be removed in future releases.", zap.String(components.ZapStabilityKey, sl.String()))
case component.StabilityLevelUnmaintained:
logger.Info("Component is unmaintained and actively looking for contributors. This component will become deprecated after 6 months of remaining unmaintained", zap.String(components.ZapStabilityKey, sl.String()))
case component.StabilityLevelInDevelopment:
logger.Info("Component is under development.", zap.String(components.ZapStabilityKey, sl.String()))
case component.StabilityLevelAlpha:
fallthrough
case component.StabilityLevelBeta:
fallthrough
case component.StabilityLevelStable:
codeboten marked this conversation as resolved.
Show resolved Hide resolved
logger.Debug("Stability level", zap.String(components.ZapStabilityKey, sl.String()))
default:
logger.Info("Stability level of component undefined", zap.String(components.ZapStabilityKey, sl.String()))
}
}

func buildExporter(
ctx context.Context,
settings component.TelemetrySettings,
Expand All @@ -328,6 +347,7 @@ func buildExporter(
BuildInfo: buildInfo,
}
set.TelemetrySettings.Logger = exporterLogger(settings.Logger, id, pipelineID.Type())
logStabilityMessage(set.TelemetrySettings.Logger, factory.StabilityLevel(pipelineID.Type()))

exp, err := createExporter(ctx, set, cfg, id, pipelineID, factory)
if err != nil {
Expand Down