Skip to content

Commit

Permalink
Enable configuring telemetry through service config file (#4069)
Browse files Browse the repository at this point in the history
* consolidate flags for configuring telemetry

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* Enable configuring metrics via service config

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* Make components take MetricsLevel from TelemetrySettings

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* Fix lint errors

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* Remove configuration for metrics prefix and adding instance ID

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* Make entire Collector available to telemetry initialization, use it to set metrics prefix to buildInfo.Command

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* fix metrics prefix tests

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* Fix lint errors

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* config/telemetry: parseLevel() no longer needs to be exported

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* config/telemetry: remove intanceID and prefix flags

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* Apply PR feedback

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* address PR feedback

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* Avoid linter complaining about use of deprecated functions

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* Update CHANGELOG

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
  • Loading branch information
Aneurysm9 committed Dec 16, 2021
1 parent 5514ecb commit e080cae
Show file tree
Hide file tree
Showing 22 changed files with 200 additions and 144 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@

- `confighttp`: add client-side compression support. (#4441)
- Each exporter should remove `compression` field if they have and should use `confighttp.HTTPClientSettings`
- Allow more zap logger configs: `disable_caller`, `disable_stacktrace`, `output_paths`, `error_output_paths`, `initial_fields` (#1048)
- Allow more zap logger configs: `disable_caller`, `disable_stacktrace`, `output_paths`, `error_output_paths`, `initial_fields` (#1048)
- `configauth`: add ServerAuthenticator interfaces for HTTP receivers. (#4506)
- Collector self-metrics may now be configured through the configuration file. (#4069)
- CLI flags for configuring self-metrics are deprecated and will be removed
in a future release.
- `service.telemetry.metrics.level` and `service.telemetry.metrics.address`
should be used to configure collector self-metrics.

## v0.41.0 Beta

Expand Down Expand Up @@ -69,6 +74,13 @@
- Move `config.WatchableRetrieved` and `config.Retrieved` interfaces to `config/configmapprovider` package (#4337)
- Remove `config.Pipeline.InputDataType` (#4343)
- otlpexporter: Do not retry on PermissionDenied and Unauthenticated (#4349)
- Enable configuring collector metrics through service config file. (#4069)
- New `service::telemetry::metrics` structure added to configuration
- Existing metrics configuration CLI flags are deprecated and to be
removed in the future.
- `--metrics-prefix` is no longer operative; the prefix is determined by
the value of `service.buildInfo.Command`.
- `--add-instance-id` is no longer operative; an instance ID will always be added.
- Remove deprecated funcs `consumererror.As[Traces|Metrics|Logs]` (#4364)
- Remove support to expand env variables in default configs (#4366)

Expand Down
2 changes: 2 additions & 0 deletions component/componenttest/nop_telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"go.uber.org/zap"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config/configtelemetry"
)

// NewNopTelemetrySettings returns a new nop telemetry settings for Create* functions.
Expand All @@ -28,5 +29,6 @@ func NewNopTelemetrySettings() component.TelemetrySettings {
Logger: zap.NewNop(),
TracerProvider: trace.NewNoopTracerProvider(),
MeterProvider: metric.NewNoopMeterProvider(),
MetricsLevel: configtelemetry.LevelNone,
}
}
6 changes: 6 additions & 0 deletions component/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap"

"go.opentelemetry.io/collector/config/configtelemetry"
)

type TelemetrySettings struct {
Expand All @@ -30,4 +32,8 @@ type TelemetrySettings struct {

// MeterProvider that the factory can pass to other instrumented third-party libraries.
MeterProvider metric.MeterProvider

// MetricsLevel controls the level of detail for metrics emitted by the collector.
// Experimental: *NOTE* this field is experimental and may be changed or removed.
MetricsLevel configtelemetry.Level
}
27 changes: 18 additions & 9 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (

"github.com/stretchr/testify/assert"
"go.uber.org/zap/zapcore"

"go.opentelemetry.io/collector/config/configtelemetry"
)

var errInvalidRecvConfig = errors.New("invalid receiver config")
Expand Down Expand Up @@ -255,15 +257,22 @@ func generateConfig() *Config {
},
},
Service: Service{
Telemetry: ServiceTelemetry{Logs: ServiceTelemetryLogs{
Level: zapcore.DebugLevel,
Development: true,
Encoding: "console",
DisableCaller: true,
DisableStacktrace: true,
OutputPaths: []string{"stderr", "./output-logs"},
ErrorOutputPaths: []string{"stderr", "./error-output-logs"},
InitialFields: map[string]interface{}{"fieldKey": "filed-value"}}},
Telemetry: ServiceTelemetry{
Logs: ServiceTelemetryLogs{
Level: zapcore.DebugLevel,
Development: true,
Encoding: "console",
DisableCaller: true,
DisableStacktrace: true,
OutputPaths: []string{"stderr", "./output-logs"},
ErrorOutputPaths: []string{"stderr", "./error-output-logs"},
InitialFields: map[string]interface{}{"fieldKey": "filed-value"},
},
Metrics: ServiceTelemetryMetrics{
Level: configtelemetry.LevelNormal,
Address: ":8080",
},
},
Extensions: []ComponentID{NewComponentID("nop")},
Pipelines: map[ComponentID]*Pipeline{
NewComponentID("traces"): {
Expand Down
74 changes: 42 additions & 32 deletions config/configtelemetry/configtelemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,30 @@ const (
levelDetailedStr = "detailed"

metricsLevelCfg = "metrics-level"
metricsAddrCfg = "metrics-addr"
)

const UseOpenTelemetryForInternalMetrics = false

var metricsLevelPtr = new(Level)
var (
metricsLevelPtr = new(Level)
metricsAddrPtr = new(string)
)

// Flags is a helper function to add telemetry config flags to the service that exposes
// the application flags.
func Flags(flags *flag.FlagSet) {
flags.Var(
metricsLevelPtr,
metricsLevelCfg,
"Output level of telemetry metrics (none, basic, normal, detailed)")
"Deprecated. Define the metrics configuration as part of the configuration file, under the 'service' section.")

// At least until we can use a generic, i.e.: OpenCensus, metrics exporter
// we default to Prometheus at port 8888, if not otherwise specified.
metricsAddrPtr = flags.String(
metricsAddrCfg,
GetMetricsAddrDefault(),
"Deprecated. Define the metrics configuration as part of the configuration file, under the 'service' section.")
}

// Level is the level of internal telemetry (metrics, logs, traces about the component itself)
Expand All @@ -57,8 +68,8 @@ type Level int32

var _ flag.Value = (*Level)(nil)

func (l *Level) String() string {
switch *l {
func (l Level) String() string {
switch l {
case LevelNone:
return levelNoneStr
case LevelBasic:
Expand All @@ -81,37 +92,17 @@ func (l *Level) Set(s string) error {
return nil
}

// GetMetricsLevelFlagValue returns the value of the "--metrics-level" flag.
// IMPORTANT: This must be used only in the core collector code for the moment.
func GetMetricsLevelFlagValue() Level {
return *metricsLevelPtr
}

// TelemetrySetting exposes the common Telemetry configuration for one component.
type TelemetrySetting struct {
// MetricsLevelStr is the level of telemetry metrics, the possible values are:
// - "none" indicates that no telemetry data should be collected;
// - "basic" is the recommended and covers the basics of the service telemetry.
// - "normal" adds some other indicators on top of basic.
// - "detailed" adds dimensions and views to the previous levels.
MetricsLevelStr string `mapstructure:"metrics_level"`
}

// DefaultTelemetrySetting returns the default TelemetrySetting.
// The level is set to the "--metrics-level" flag if set, otherwise the default "basic" level.
func DefaultTelemetrySetting() TelemetrySetting {
return TelemetrySetting{
MetricsLevelStr: metricsLevelPtr.String(),
// UnmarshalText unmarshals text to a Level.
func (l *Level) UnmarshalText(text []byte) error {
if l == nil {
return fmt.Errorf("cannot unmarshal to a nil *Level")
}
var err error
*l, err = parseLevel(string(text))
return err
}

// GetMetricsLevel returns the parsed level, or error if unknown value.
// Empty string is consider unknown value.
func (ts TelemetrySetting) GetMetricsLevel() (Level, error) {
return parseLevel(ts.MetricsLevelStr)
}

// ParseLevel returns the Level represented by the string. The parsing is case-insensitive
// parseLevel returns the Level represented by the string. The parsing is case-insensitive
// and it returns error if the string value is unknown.
func parseLevel(str string) (Level, error) {
str = strings.ToLower(str)
Expand All @@ -128,3 +119,22 @@ func parseLevel(str string) (Level, error) {
}
return LevelNone, fmt.Errorf("unknown metrics level %q", str)
}

// GetMetricsAddrDefault returns the default metrics bind address and port depending on
// the current build type.
// Deprecated: This function will be removed in the future.
func GetMetricsAddrDefault() string {
return ":8888"
}

// Deprecated: This function will be removed in the future.
func GetMetricsAddr() string {
return *metricsAddrPtr
}

// GetMetricsLevelFlagValue returns the value of the "--metrics-level" flag.
// IMPORTANT: This must be used only in the core collector code for the moment.
// Deprecated: This function will be removed in the future.
func GetMetricsLevelFlagValue() Level {
return *metricsLevelPtr
}
17 changes: 0 additions & 17 deletions config/configtelemetry/configtelemetry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"testing"

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

func TestParseFrom(t *testing.T) {
Expand Down Expand Up @@ -149,19 +148,3 @@ func TestLevelString(t *testing.T) {
})
}
}

func TestTelemetrySettings(t *testing.T) {
ts := &TelemetrySetting{
MetricsLevelStr: "unknown",
}
_, err := ts.GetMetricsLevel()
assert.Error(t, err)
}

func TestDefaultTelemetrySettings(t *testing.T) {
ts := DefaultTelemetrySetting()
assert.Equal(t, levelBasicStr, ts.MetricsLevelStr)
lvl, err := ts.GetMetricsLevel()
require.NoError(t, err)
assert.Equal(t, LevelBasic, lvl)
}
17 changes: 17 additions & 0 deletions config/configunmarshaler/defaultunmarshaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config"
"go.opentelemetry.io/collector/config/configtelemetry"
)

// These are errors that can be returned by Unmarshal(). Note that error codes are not part
Expand Down Expand Up @@ -177,6 +178,7 @@ func unmarshalService(srvRaw map[string]interface{}) (config.Service, error) {
DisableStacktrace: false,
InitialFields: map[string]interface{}(nil),
},
Metrics: defaultServiceTelemetryMetricsSettings(),
},
}

Expand All @@ -192,6 +194,21 @@ func unmarshalService(srvRaw map[string]interface{}) (config.Service, error) {
return srv, nil
}

func defaultServiceTelemetryMetricsSettings() config.ServiceTelemetryMetrics {
// These deprecated functions are still needed here so that the values provided through the CLI flags
// can be used as a baseline if no values are provided in configuration. This will eventually return
// a static default configuration when the CLI flags are removed.
addr := configtelemetry.GetMetricsAddr() //nolint:staticcheck
if addr == "" {
addr = configtelemetry.GetMetricsAddrDefault() //nolint:staticcheck
}

return config.ServiceTelemetryMetrics{
Level: configtelemetry.GetMetricsLevelFlagValue(), //nolint:staticcheck
Address: addr,
}
}

// LoadReceiver loads a receiver config from componentConfig using the provided factories.
func LoadReceiver(componentConfig *config.Map, id config.ComponentID, factory component.ReceiverFactory) (config.Receiver, error) {
// Create the default config for this receiver.
Expand Down
28 changes: 18 additions & 10 deletions config/configunmarshaler/defaultunmarshaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"go.opentelemetry.io/collector/config"
"go.opentelemetry.io/collector/config/configmapprovider"
"go.opentelemetry.io/collector/config/confignet"
"go.opentelemetry.io/collector/config/configtelemetry"
"go.opentelemetry.io/collector/internal/testcomponents"
)

Expand Down Expand Up @@ -100,16 +101,22 @@ func TestDecodeConfig(t *testing.T) {

// Verify Service Telemetry
assert.Equal(t,
config.ServiceTelemetry{Logs: config.ServiceTelemetryLogs{
Level: zapcore.DebugLevel,
Development: true,
Encoding: "console",
DisableCaller: true,
DisableStacktrace: true,
OutputPaths: []string{"stderr", "./output-logs"},
ErrorOutputPaths: []string{"stderr", "./error-output-logs"},
InitialFields: map[string]interface{}{"field_key": "filed_value"},
}}, cfg.Service.Telemetry)
config.ServiceTelemetry{
Logs: config.ServiceTelemetryLogs{
Level: zapcore.DebugLevel,
Development: true,
Encoding: "console",
DisableCaller: true,
DisableStacktrace: true,
OutputPaths: []string{"stderr", "./output-logs"},
ErrorOutputPaths: []string{"stderr", "./error-output-logs"},
InitialFields: map[string]interface{}{"field_key": "filed_value"},
},
Metrics: config.ServiceTelemetryMetrics{
Level: configtelemetry.LevelNormal,
Address: ":8081",
},
}, cfg.Service.Telemetry)

// Verify Service Extensions
assert.Equal(t, 2, len(cfg.Service.Extensions))
Expand Down Expand Up @@ -177,6 +184,7 @@ func TestDecodeConfig_Invalid(t *testing.T) {
{name: "invalid-pipeline-sub-config", expected: errUnmarshalService},

{name: "invalid-logs-level", expected: errUnmarshalService},
{name: "invalid-metrics-level", expected: errUnmarshalService},
}

factories, err := testcomponents.ExampleComponents()
Expand Down
19 changes: 19 additions & 0 deletions config/configunmarshaler/testdata/invalid-metrics-level.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
receivers:
examplereceiver:
processors:
exampleprocessor:
exporters:
exampleexporter:
extensions:
exampleextension:
service:
telemetry:
metrics:
level: "unknown"
extensions: [exampleextension]
pipelines:
traces:
receivers: [examplereceiver]
processors: [exampleprocessor]
exporters: [exampleexporter]

5 changes: 4 additions & 1 deletion config/configunmarshaler/testdata/valid-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ service:
disable_stacktrace: true
output_paths: ["stderr", "./output-logs"]
error_output_paths: ["stderr", "./error-output-logs"]
initial_fields:
initial_fields:
field_key: "filed_value"
metrics:
level: "normal"
address: ":8081"
extensions: [exampleextension/0, exampleextension/1]
pipelines:
traces:
Expand Down
Loading

0 comments on commit e080cae

Please sign in to comment.