From a7da76ac7dc461b8eb2e8f83549a9a2b1928c872 Mon Sep 17 00:00:00 2001 From: braydonk Date: Wed, 16 Oct 2024 13:26:25 +0000 Subject: [PATCH] mdatagen: get package name from metadata I noticed a mistake in my previous PR #11232; some function calls did not pass the correct package name in (passing in "metadata" instead of the intended generated package name). This PR attempts to address the potential for this mistake to even occur by providing a wrapper `generateFile` function that automatically uses the generated package name from the metadata. The original version of the function that accepts a package name is intact for the templates that are going in the base package instead of the generated one. --- Makefile | 1 + cmd/mdatagen/internal/command.go | 18 +- cmd/mdatagen/internal/command_test.go | 16 +- cmd/mdatagen/internal/sampleprocessor/doc.go | 1 + .../internal/custom/generated_config.go | 67 ++ .../internal/custom/generated_config_test.go | 72 +++ .../internal/custom/generated_resource.go | 92 +++ .../custom/generated_resource_test.go | 82 +++ .../internal/custom/generated_status.go | 18 + .../internal/custom/testdata/config.yaml | 37 ++ .../sampleprocessor/metadata_custom.yaml | 70 +++ cmd/mdatagen/internal/samplereceiver/doc.go | 1 + .../internal/custom/generated_config.go | 136 ++++ .../internal/custom/generated_config_test.go | 146 +++++ .../internal/custom/generated_metrics.go | 579 ++++++++++++++++++ .../internal/custom/generated_metrics_test.go | 264 ++++++++ .../internal/custom/generated_resource.go | 92 +++ .../custom/generated_resource_test.go | 82 +++ .../internal/custom/generated_status.go | 18 + .../internal/custom/generated_telemetry.go | 111 ++++ .../custom/generated_telemetry_test.go | 83 +++ .../internal/custom/testdata/config.yaml | 127 ++++ .../samplereceiver/metadata_custom.yaml | 201 ++++++ 23 files changed, 2301 insertions(+), 13 deletions(-) create mode 100644 cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_config.go create mode 100644 cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_config_test.go create mode 100644 cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_resource.go create mode 100644 cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_resource_test.go create mode 100644 cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_status.go create mode 100644 cmd/mdatagen/internal/sampleprocessor/internal/custom/testdata/config.yaml create mode 100644 cmd/mdatagen/internal/sampleprocessor/metadata_custom.yaml create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/custom/generated_config.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/custom/generated_config_test.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/custom/generated_metrics.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/custom/generated_metrics_test.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/custom/generated_resource.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/custom/generated_resource_test.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/custom/generated_status.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/custom/generated_telemetry.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/custom/generated_telemetry_test.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/custom/testdata/config.yaml create mode 100644 cmd/mdatagen/internal/samplereceiver/metadata_custom.yaml diff --git a/Makefile b/Makefile index adefd0f647b..12c2aded197 100644 --- a/Makefile +++ b/Makefile @@ -539,3 +539,4 @@ mdatagen-test: cd cmd/mdatagen && $(GOCMD) install . cd cmd/mdatagen && $(GOCMD) generate ./... cd cmd/mdatagen && $(GOCMD) test ./... + $(MAKE) -C cmd/mdatagen fmt diff --git a/cmd/mdatagen/internal/command.go b/cmd/mdatagen/internal/command.go index 5abe033a943..c4c60514411 100644 --- a/cmd/mdatagen/internal/command.go +++ b/cmd/mdatagen/internal/command.go @@ -81,16 +81,16 @@ func run(ymlPath string) error { if md.Status != nil { if md.Status.Class != "cmd" && md.Status.Class != "pkg" && !md.Status.NotComponent { if err = generateFile(filepath.Join(tmplDir, "status.go.tmpl"), - filepath.Join(codeDir, "generated_status.go"), md, "metadata"); err != nil { + filepath.Join(codeDir, "generated_status.go"), md); err != nil { return err } - if err = generateFile(filepath.Join(tmplDir, "component_test.go.tmpl"), + if err = generateFileWithPackageName(filepath.Join(tmplDir, "component_test.go.tmpl"), filepath.Join(ymlDir, "generated_component_test.go"), md, packageName); err != nil { return err } } - if err = generateFile(filepath.Join(tmplDir, "package_test.go.tmpl"), + if err = generateFileWithPackageName(filepath.Join(tmplDir, "package_test.go.tmpl"), filepath.Join(ymlDir, "generated_package_test.go"), md, packageName); err != nil { return err } @@ -108,7 +108,7 @@ func run(ymlPath string) error { toGenerate := map[string]string{} if len(md.Telemetry.Metrics) != 0 { // if there are telemetry metrics, generate telemetry specific files - if err = generateFile(filepath.Join(tmplDir, "component_telemetry_test.go.tmpl"), + if err = generateFileWithPackageName(filepath.Join(tmplDir, "component_telemetry_test.go.tmpl"), filepath.Join(ymlDir, "generated_component_telemetry_test.go"), md, packageName); err != nil { return err } @@ -121,7 +121,7 @@ func run(ymlPath string) error { } for tmpl, dst := range toGenerate { - if err = generateFile(tmpl, dst, md, "metadata"); err != nil { + if err = generateFile(tmpl, dst, md); err != nil { return err } } @@ -151,7 +151,7 @@ func run(ymlPath string) error { } for tmpl, dst := range toGenerate { - if err = generateFile(tmpl, dst, md, md.GeneratedPackageName); err != nil { + if err = generateFile(tmpl, dst, md); err != nil { return err } } @@ -400,7 +400,11 @@ func inlineReplace(tmplFile string, outputFile string, md Metadata, start string return nil } -func generateFile(tmplFile string, outputFile string, md Metadata, goPackage string) error { +func generateFile(tmplFile string, outputFile string, md Metadata) error { + return generateFileWithPackageName(tmplFile, outputFile, md, md.GeneratedPackageName) +} + +func generateFileWithPackageName(tmplFile string, outputFile string, md Metadata, goPackage string) error { if err := os.Remove(outputFile); err != nil && !errors.Is(err, os.ErrNotExist) { return fmt.Errorf("unable to remove generated file %q: %w", outputFile, err) } diff --git a/cmd/mdatagen/internal/command_test.go b/cmd/mdatagen/internal/command_test.go index 27358666ed4..c1d41221d40 100644 --- a/cmd/mdatagen/internal/command_test.go +++ b/cmd/mdatagen/internal/command_test.go @@ -501,7 +501,8 @@ func TestGenerateStatusMetadata(t *testing.T) { { name: "foo component with beta status", md: Metadata{ - Type: "foo", + Type: "foo", + GeneratedPackageName: "metadata", Status: &Status{ Stability: map[component.StabilityLevel][]string{ component.StabilityLevelBeta: {"metrics"}, @@ -531,7 +532,8 @@ const ( { name: "foo component with alpha status", md: Metadata{ - Type: "foo", + Type: "foo", + GeneratedPackageName: "metadata", Status: &Status{ Stability: map[component.StabilityLevel][]string{ component.StabilityLevelAlpha: {"metrics"}, @@ -564,7 +566,7 @@ const ( t.Run(tt.name, func(t *testing.T) { tmpdir := t.TempDir() err := generateFile("templates/status.go.tmpl", - filepath.Join(tmpdir, "generated_status.go"), tt.md, "metadata") + filepath.Join(tmpdir, "generated_status.go"), tt.md) require.NoError(t, err) actual, err := os.ReadFile(filepath.Join(tmpdir, "generated_status.go")) // nolint: gosec require.NoError(t, err) @@ -583,7 +585,8 @@ func TestGenerateTelemetryMetadata(t *testing.T) { { name: "foo component with beta status", md: Metadata{ - Type: "foo", + Type: "foo", + GeneratedPackageName: "metadata", Status: &Status{ Stability: map[component.StabilityLevel][]string{ component.StabilityLevelBeta: {"metrics"}, @@ -621,7 +624,8 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { { name: "foo component with alpha status", md: Metadata{ - Type: "foo", + Type: "foo", + GeneratedPackageName: "metadata", Status: &Status{ Stability: map[component.StabilityLevel][]string{ component.StabilityLevelAlpha: {"metrics"}, @@ -662,7 +666,7 @@ func Tracer(settings component.TelemetrySettings) trace.Tracer { t.Run(tt.name, func(t *testing.T) { tmpdir := t.TempDir() err := generateFile("templates/telemetry.go.tmpl", - filepath.Join(tmpdir, "generated_telemetry.go"), tt.md, "metadata") + filepath.Join(tmpdir, "generated_telemetry.go"), tt.md) require.NoError(t, err) actual, err := os.ReadFile(filepath.Join(tmpdir, "generated_telemetry.go")) // nolint: gosec require.NoError(t, err) diff --git a/cmd/mdatagen/internal/sampleprocessor/doc.go b/cmd/mdatagen/internal/sampleprocessor/doc.go index 0fc1c748f91..d54caa6b771 100644 --- a/cmd/mdatagen/internal/sampleprocessor/doc.go +++ b/cmd/mdatagen/internal/sampleprocessor/doc.go @@ -3,6 +3,7 @@ // Generate a test metrics builder from a sample metrics set covering all configuration options. //go:generate mdatagen metadata.yaml +//go:generate mdatagen metadata_custom.yaml // Deprecated: This package is moving to https://github.com/open-telemetry/opentelemetry-collector and will eventually be removed. // Please see https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/30497 diff --git a/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_config.go b/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_config.go new file mode 100644 index 00000000000..b43495060a7 --- /dev/null +++ b/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_config.go @@ -0,0 +1,67 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "go.opentelemetry.io/collector/confmap" +) + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` + + enabledSetByUser bool +} + +func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(rac) + if err != nil { + return err + } + rac.enabledSetByUser = parser.IsSet("enabled") + return nil +} + +// ResourceAttributesConfig provides config for sample resource attributes. +type ResourceAttributesConfig struct { + MapResourceAttr ResourceAttributeConfig `mapstructure:"map.resource.attr"` + OptionalResourceAttr ResourceAttributeConfig `mapstructure:"optional.resource.attr"` + SliceResourceAttr ResourceAttributeConfig `mapstructure:"slice.resource.attr"` + StringEnumResourceAttr ResourceAttributeConfig `mapstructure:"string.enum.resource.attr"` + StringResourceAttr ResourceAttributeConfig `mapstructure:"string.resource.attr"` + StringResourceAttrDisableWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_disable_warning"` + StringResourceAttrRemoveWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_remove_warning"` + StringResourceAttrToBeRemoved ResourceAttributeConfig `mapstructure:"string.resource.attr_to_be_removed"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + OptionalResourceAttr: ResourceAttributeConfig{ + Enabled: false, + }, + SliceResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + StringEnumResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + StringResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + StringResourceAttrDisableWarning: ResourceAttributeConfig{ + Enabled: true, + }, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{ + Enabled: false, + }, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_config_test.go b/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_config_test.go new file mode 100644 index 00000000000..15be0e80064 --- /dev/null +++ b/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_config_test.go @@ -0,0 +1,72 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{Enabled: true}, + OptionalResourceAttr: ResourceAttributeConfig{Enabled: true}, + SliceResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{Enabled: false}, + OptionalResourceAttr: ResourceAttributeConfig{Enabled: false}, + SliceResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := loadResourceAttributesConfig(t, tt.name) + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} + +func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, sub.Unmarshal(&cfg)) + return cfg +} diff --git a/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_resource.go b/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_resource.go new file mode 100644 index 00000000000..9641095cdc4 --- /dev/null +++ b/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_resource.go @@ -0,0 +1,92 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "go.opentelemetry.io/collector/pdata/pcommon" +) + +// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml. +// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines. +type ResourceBuilder struct { + config ResourceAttributesConfig + res pcommon.Resource +} + +// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application. +func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder { + return &ResourceBuilder{ + config: rac, + res: pcommon.NewResource(), + } +} + +// SetMapResourceAttr sets provided value as "map.resource.attr" attribute. +func (rb *ResourceBuilder) SetMapResourceAttr(val map[string]any) { + if rb.config.MapResourceAttr.Enabled { + rb.res.Attributes().PutEmptyMap("map.resource.attr").FromRaw(val) + } +} + +// SetOptionalResourceAttr sets provided value as "optional.resource.attr" attribute. +func (rb *ResourceBuilder) SetOptionalResourceAttr(val string) { + if rb.config.OptionalResourceAttr.Enabled { + rb.res.Attributes().PutStr("optional.resource.attr", val) + } +} + +// SetSliceResourceAttr sets provided value as "slice.resource.attr" attribute. +func (rb *ResourceBuilder) SetSliceResourceAttr(val []any) { + if rb.config.SliceResourceAttr.Enabled { + rb.res.Attributes().PutEmptySlice("slice.resource.attr").FromRaw(val) + } +} + +// SetStringEnumResourceAttrOne sets "string.enum.resource.attr=one" attribute. +func (rb *ResourceBuilder) SetStringEnumResourceAttrOne() { + if rb.config.StringEnumResourceAttr.Enabled { + rb.res.Attributes().PutStr("string.enum.resource.attr", "one") + } +} + +// SetStringEnumResourceAttrTwo sets "string.enum.resource.attr=two" attribute. +func (rb *ResourceBuilder) SetStringEnumResourceAttrTwo() { + if rb.config.StringEnumResourceAttr.Enabled { + rb.res.Attributes().PutStr("string.enum.resource.attr", "two") + } +} + +// SetStringResourceAttr sets provided value as "string.resource.attr" attribute. +func (rb *ResourceBuilder) SetStringResourceAttr(val string) { + if rb.config.StringResourceAttr.Enabled { + rb.res.Attributes().PutStr("string.resource.attr", val) + } +} + +// SetStringResourceAttrDisableWarning sets provided value as "string.resource.attr_disable_warning" attribute. +func (rb *ResourceBuilder) SetStringResourceAttrDisableWarning(val string) { + if rb.config.StringResourceAttrDisableWarning.Enabled { + rb.res.Attributes().PutStr("string.resource.attr_disable_warning", val) + } +} + +// SetStringResourceAttrRemoveWarning sets provided value as "string.resource.attr_remove_warning" attribute. +func (rb *ResourceBuilder) SetStringResourceAttrRemoveWarning(val string) { + if rb.config.StringResourceAttrRemoveWarning.Enabled { + rb.res.Attributes().PutStr("string.resource.attr_remove_warning", val) + } +} + +// SetStringResourceAttrToBeRemoved sets provided value as "string.resource.attr_to_be_removed" attribute. +func (rb *ResourceBuilder) SetStringResourceAttrToBeRemoved(val string) { + if rb.config.StringResourceAttrToBeRemoved.Enabled { + rb.res.Attributes().PutStr("string.resource.attr_to_be_removed", val) + } +} + +// Emit returns the built resource and resets the internal builder state. +func (rb *ResourceBuilder) Emit() pcommon.Resource { + r := rb.res + rb.res = pcommon.NewResource() + return r +} diff --git a/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_resource_test.go b/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_resource_test.go new file mode 100644 index 00000000000..b8e33e3258d --- /dev/null +++ b/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_resource_test.go @@ -0,0 +1,82 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResourceBuilder(t *testing.T) { + for _, tt := range []string{"default", "all_set", "none_set"} { + t.Run(tt, func(t *testing.T) { + cfg := loadResourceAttributesConfig(t, tt) + rb := NewResourceBuilder(cfg) + rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}) + rb.SetOptionalResourceAttr("optional.resource.attr-val") + rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"}) + rb.SetStringEnumResourceAttrOne() + rb.SetStringResourceAttr("string.resource.attr-val") + rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val") + rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val") + rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val") + + res := rb.Emit() + assert.Equal(t, 0, rb.Emit().Attributes().Len()) // Second call should return empty Resource + + switch tt { + case "default": + assert.Equal(t, 6, res.Attributes().Len()) + case "all_set": + assert.Equal(t, 8, res.Attributes().Len()) + case "none_set": + assert.Equal(t, 0, res.Attributes().Len()) + return + default: + assert.Failf(t, "unexpected test case: %s", tt) + } + + val, ok := res.Attributes().Get("map.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}, val.Map().AsRaw()) + } + val, ok = res.Attributes().Get("optional.resource.attr") + assert.Equal(t, tt == "all_set", ok) + if ok { + assert.EqualValues(t, "optional.resource.attr-val", val.Str()) + } + val, ok = res.Attributes().Get("slice.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, []any{"slice.resource.attr-item1", "slice.resource.attr-item2"}, val.Slice().AsRaw()) + } + val, ok = res.Attributes().Get("string.enum.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "one", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "string.resource.attr-val", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr_disable_warning") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "string.resource.attr_disable_warning-val", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr_remove_warning") + assert.Equal(t, tt == "all_set", ok) + if ok { + assert.EqualValues(t, "string.resource.attr_remove_warning-val", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr_to_be_removed") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "string.resource.attr_to_be_removed-val", val.Str()) + } + }) + } +} diff --git a/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_status.go b/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_status.go new file mode 100644 index 00000000000..4349b26b285 --- /dev/null +++ b/cmd/mdatagen/internal/sampleprocessor/internal/custom/generated_status.go @@ -0,0 +1,18 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("sample") + ScopeName = "go.opentelemetry.io/collector/internal/receiver/samplereceiver" +) + +const ( + LogsStability = component.StabilityLevelDevelopment + TracesStability = component.StabilityLevelBeta + MetricsStability = component.StabilityLevelStable +) diff --git a/cmd/mdatagen/internal/sampleprocessor/internal/custom/testdata/config.yaml b/cmd/mdatagen/internal/sampleprocessor/internal/custom/testdata/config.yaml new file mode 100644 index 00000000000..bcc1a519f60 --- /dev/null +++ b/cmd/mdatagen/internal/sampleprocessor/internal/custom/testdata/config.yaml @@ -0,0 +1,37 @@ +default: +all_set: + resource_attributes: + map.resource.attr: + enabled: true + optional.resource.attr: + enabled: true + slice.resource.attr: + enabled: true + string.enum.resource.attr: + enabled: true + string.resource.attr: + enabled: true + string.resource.attr_disable_warning: + enabled: true + string.resource.attr_remove_warning: + enabled: true + string.resource.attr_to_be_removed: + enabled: true +none_set: + resource_attributes: + map.resource.attr: + enabled: false + optional.resource.attr: + enabled: false + slice.resource.attr: + enabled: false + string.enum.resource.attr: + enabled: false + string.resource.attr: + enabled: false + string.resource.attr_disable_warning: + enabled: false + string.resource.attr_remove_warning: + enabled: false + string.resource.attr_to_be_removed: + enabled: false diff --git a/cmd/mdatagen/internal/sampleprocessor/metadata_custom.yaml b/cmd/mdatagen/internal/sampleprocessor/metadata_custom.yaml new file mode 100644 index 00000000000..ca6e52bf275 --- /dev/null +++ b/cmd/mdatagen/internal/sampleprocessor/metadata_custom.yaml @@ -0,0 +1,70 @@ +# Sample metadata file with all available configurations for a receiver. + +type: sample +scope_name: go.opentelemetry.io/collector/internal/receiver/samplereceiver +github_project: open-telemetry/opentelemetry-collector + +generated_package_name: custom + +sem_conv_version: 1.9.0 + +status: + class: processor + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [] + unsupported_platforms: [freebsd, illumos] + codeowners: + active: [some] + warnings: + - Any additional information that should be brought to the consumer's attention + +resource_attributes: + string.resource.attr: + description: Resource attribute with any string value. + type: string + enabled: true + + string.enum.resource.attr: + description: Resource attribute with a known set of string values. + type: string + enum: [one, two] + enabled: true + + optional.resource.attr: + description: Explicitly disabled ResourceAttribute. + type: string + enabled: false + + slice.resource.attr: + description: Resource attribute with a slice value. + type: slice + enabled: true + + map.resource.attr: + description: Resource attribute with a map value. + type: map + enabled: true + + string.resource.attr_disable_warning: + description: Resource attribute with any string value. + type: string + enabled: true + warnings: + if_enabled_not_set: This resource_attribute will be disabled by default soon. + + string.resource.attr_remove_warning: + description: Resource attribute with any string value. + type: string + enabled: false + warnings: + if_configured: This resource_attribute is deprecated and will be removed soon. + + string.resource.attr_to_be_removed: + description: Resource attribute with any string value. + type: string + enabled: true + warnings: + if_enabled: This resource_attribute is deprecated and will be removed soon. diff --git a/cmd/mdatagen/internal/samplereceiver/doc.go b/cmd/mdatagen/internal/samplereceiver/doc.go index 7b7505667ae..20e8cc52ced 100644 --- a/cmd/mdatagen/internal/samplereceiver/doc.go +++ b/cmd/mdatagen/internal/samplereceiver/doc.go @@ -3,6 +3,7 @@ // Generate a test metrics builder from a sample metrics set covering all configuration options. //go:generate mdatagen metadata.yaml +//go:generate mdatagen metadata_custom.yaml // Deprecated: This package is moving to https://github.com/open-telemetry/opentelemetry-collector and will eventually be removed. // Please see https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/30497 diff --git a/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_config.go b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_config.go new file mode 100644 index 00000000000..f3ed50141fb --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_config.go @@ -0,0 +1,136 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "go.opentelemetry.io/collector/confmap" + "go.opentelemetry.io/collector/filter" +) + +// MetricConfig provides common config for a particular metric. +type MetricConfig struct { + Enabled bool `mapstructure:"enabled"` + + enabledSetByUser bool +} + +func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(ms) + if err != nil { + return err + } + ms.enabledSetByUser = parser.IsSet("enabled") + return nil +} + +// MetricsConfig provides config for sample metrics. +type MetricsConfig struct { + DefaultMetric MetricConfig `mapstructure:"default.metric"` + DefaultMetricToBeRemoved MetricConfig `mapstructure:"default.metric.to_be_removed"` + MetricInputType MetricConfig `mapstructure:"metric.input_type"` + OptionalMetric MetricConfig `mapstructure:"optional.metric"` + OptionalMetricEmptyUnit MetricConfig `mapstructure:"optional.metric.empty_unit"` +} + +func DefaultMetricsConfig() MetricsConfig { + return MetricsConfig{ + DefaultMetric: MetricConfig{ + Enabled: true, + }, + DefaultMetricToBeRemoved: MetricConfig{ + Enabled: true, + }, + MetricInputType: MetricConfig{ + Enabled: true, + }, + OptionalMetric: MetricConfig{ + Enabled: false, + }, + OptionalMetricEmptyUnit: MetricConfig{ + Enabled: false, + }, + } +} + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` + // Experimental: MetricsInclude defines a list of filters for attribute values. + // If the list is not empty, only metrics with matching resource attribute values will be emitted. + MetricsInclude []filter.Config `mapstructure:"metrics_include"` + // Experimental: MetricsExclude defines a list of filters for attribute values. + // If the list is not empty, metrics with matching resource attribute values will not be emitted. + // MetricsInclude has higher priority than MetricsExclude. + MetricsExclude []filter.Config `mapstructure:"metrics_exclude"` + + enabledSetByUser bool +} + +func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(rac) + if err != nil { + return err + } + rac.enabledSetByUser = parser.IsSet("enabled") + return nil +} + +// ResourceAttributesConfig provides config for sample resource attributes. +type ResourceAttributesConfig struct { + MapResourceAttr ResourceAttributeConfig `mapstructure:"map.resource.attr"` + OptionalResourceAttr ResourceAttributeConfig `mapstructure:"optional.resource.attr"` + SliceResourceAttr ResourceAttributeConfig `mapstructure:"slice.resource.attr"` + StringEnumResourceAttr ResourceAttributeConfig `mapstructure:"string.enum.resource.attr"` + StringResourceAttr ResourceAttributeConfig `mapstructure:"string.resource.attr"` + StringResourceAttrDisableWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_disable_warning"` + StringResourceAttrRemoveWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_remove_warning"` + StringResourceAttrToBeRemoved ResourceAttributeConfig `mapstructure:"string.resource.attr_to_be_removed"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + OptionalResourceAttr: ResourceAttributeConfig{ + Enabled: false, + }, + SliceResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + StringEnumResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + StringResourceAttr: ResourceAttributeConfig{ + Enabled: true, + }, + StringResourceAttrDisableWarning: ResourceAttributeConfig{ + Enabled: true, + }, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{ + Enabled: false, + }, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{ + Enabled: true, + }, + } +} + +// MetricsBuilderConfig is a configuration for sample metrics builder. +type MetricsBuilderConfig struct { + Metrics MetricsConfig `mapstructure:"metrics"` + ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func DefaultMetricsBuilderConfig() MetricsBuilderConfig { + return MetricsBuilderConfig{ + Metrics: DefaultMetricsConfig(), + ResourceAttributes: DefaultResourceAttributesConfig(), + } +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_config_test.go b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_config_test.go new file mode 100644 index 00000000000..e228a064683 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_config_test.go @@ -0,0 +1,146 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + + "go.opentelemetry.io/collector/confmap/confmaptest" +) + +func TestMetricsBuilderConfig(t *testing.T) { + tests := []struct { + name string + want MetricsBuilderConfig + }{ + { + name: "default", + want: DefaultMetricsBuilderConfig(), + }, + { + name: "all_set", + want: MetricsBuilderConfig{ + Metrics: MetricsConfig{ + DefaultMetric: MetricConfig{Enabled: true}, + DefaultMetricToBeRemoved: MetricConfig{Enabled: true}, + MetricInputType: MetricConfig{Enabled: true}, + OptionalMetric: MetricConfig{Enabled: true}, + OptionalMetricEmptyUnit: MetricConfig{Enabled: true}, + }, + ResourceAttributes: ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{Enabled: true}, + OptionalResourceAttr: ResourceAttributeConfig{Enabled: true}, + SliceResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true}, + }, + }, + }, + { + name: "none_set", + want: MetricsBuilderConfig{ + Metrics: MetricsConfig{ + DefaultMetric: MetricConfig{Enabled: false}, + DefaultMetricToBeRemoved: MetricConfig{Enabled: false}, + MetricInputType: MetricConfig{Enabled: false}, + OptionalMetric: MetricConfig{Enabled: false}, + OptionalMetricEmptyUnit: MetricConfig{Enabled: false}, + }, + ResourceAttributes: ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{Enabled: false}, + OptionalResourceAttr: ResourceAttributeConfig{Enabled: false}, + SliceResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false}, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := loadMetricsBuilderConfig(t, tt.name) + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(MetricConfig{}, ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} + +func loadMetricsBuilderConfig(t *testing.T, name string) MetricsBuilderConfig { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(name) + require.NoError(t, err) + cfg := DefaultMetricsBuilderConfig() + require.NoError(t, sub.Unmarshal(&cfg)) + return cfg +} + +func TestResourceAttributesConfig(t *testing.T) { + tests := []struct { + name string + want ResourceAttributesConfig + }{ + { + name: "default", + want: DefaultResourceAttributesConfig(), + }, + { + name: "all_set", + want: ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{Enabled: true}, + OptionalResourceAttr: ResourceAttributeConfig{Enabled: true}, + SliceResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringResourceAttr: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true}, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true}, + }, + }, + { + name: "none_set", + want: ResourceAttributesConfig{ + MapResourceAttr: ResourceAttributeConfig{Enabled: false}, + OptionalResourceAttr: ResourceAttributeConfig{Enabled: false}, + SliceResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringResourceAttr: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false}, + StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := loadResourceAttributesConfig(t, tt.name) + if diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{})); diff != "" { + t.Errorf("Config mismatch (-expected +actual):\n%s", diff) + } + }) + } +} + +func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig { + cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) + require.NoError(t, err) + sub, err := cm.Sub(name) + require.NoError(t, err) + sub, err = sub.Sub("resource_attributes") + require.NoError(t, err) + cfg := DefaultResourceAttributesConfig() + require.NoError(t, sub.Unmarshal(&cfg)) + return cfg +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_metrics.go b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_metrics.go new file mode 100644 index 00000000000..2c7a820d98b --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_metrics.go @@ -0,0 +1,579 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "fmt" + "strconv" + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/filter" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver" + conventions "go.opentelemetry.io/collector/semconv/v1.9.0" +) + +// AttributeEnumAttr specifies the a value enum_attr attribute. +type AttributeEnumAttr int + +const ( + _ AttributeEnumAttr = iota + AttributeEnumAttrRed + AttributeEnumAttrGreen + AttributeEnumAttrBlue +) + +// String returns the string representation of the AttributeEnumAttr. +func (av AttributeEnumAttr) String() string { + switch av { + case AttributeEnumAttrRed: + return "red" + case AttributeEnumAttrGreen: + return "green" + case AttributeEnumAttrBlue: + return "blue" + } + return "" +} + +// MapAttributeEnumAttr is a helper map of string to AttributeEnumAttr attribute value. +var MapAttributeEnumAttr = map[string]AttributeEnumAttr{ + "red": AttributeEnumAttrRed, + "green": AttributeEnumAttrGreen, + "blue": AttributeEnumAttrBlue, +} + +type metricDefaultMetric struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills default.metric metric with initial data. +func (m *metricDefaultMetric) init() { + m.data.SetName("default.metric") + m.data.SetDescription("Monotonic cumulative sum int metric enabled by default.") + m.data.SetUnit("s") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(true) + m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative) + m.data.Sum().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricDefaultMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue string, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) { + if !m.config.Enabled { + return + } + dp := m.data.Sum().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) + dp.Attributes().PutStr("string_attr", stringAttrAttributeValue) + dp.Attributes().PutInt("state", overriddenIntAttrAttributeValue) + dp.Attributes().PutStr("enum_attr", enumAttrAttributeValue) + dp.Attributes().PutEmptySlice("slice_attr").FromRaw(sliceAttrAttributeValue) + dp.Attributes().PutEmptyMap("map_attr").FromRaw(mapAttrAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricDefaultMetric) updateCapacity() { + if m.data.Sum().DataPoints().Len() > m.capacity { + m.capacity = m.data.Sum().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricDefaultMetric) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricDefaultMetric(cfg MetricConfig) metricDefaultMetric { + m := metricDefaultMetric{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricDefaultMetricToBeRemoved struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills default.metric.to_be_removed metric with initial data. +func (m *metricDefaultMetricToBeRemoved) init() { + m.data.SetName("default.metric.to_be_removed") + m.data.SetDescription("[DEPRECATED] Non-monotonic delta sum double metric enabled by default.") + m.data.SetUnit("s") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(false) + m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta) +} + +func (m *metricDefaultMetricToBeRemoved) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) { + if !m.config.Enabled { + return + } + dp := m.data.Sum().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricDefaultMetricToBeRemoved) updateCapacity() { + if m.data.Sum().DataPoints().Len() > m.capacity { + m.capacity = m.data.Sum().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricDefaultMetricToBeRemoved) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricDefaultMetricToBeRemoved(cfg MetricConfig) metricDefaultMetricToBeRemoved { + m := metricDefaultMetricToBeRemoved{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricMetricInputType struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills metric.input_type metric with initial data. +func (m *metricMetricInputType) init() { + m.data.SetName("metric.input_type") + m.data.SetDescription("Monotonic cumulative sum int metric with string input_type enabled by default.") + m.data.SetUnit("s") + m.data.SetEmptySum() + m.data.Sum().SetIsMonotonic(true) + m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative) + m.data.Sum().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricMetricInputType) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue string, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) { + if !m.config.Enabled { + return + } + dp := m.data.Sum().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetIntValue(val) + dp.Attributes().PutStr("string_attr", stringAttrAttributeValue) + dp.Attributes().PutInt("state", overriddenIntAttrAttributeValue) + dp.Attributes().PutStr("enum_attr", enumAttrAttributeValue) + dp.Attributes().PutEmptySlice("slice_attr").FromRaw(sliceAttrAttributeValue) + dp.Attributes().PutEmptyMap("map_attr").FromRaw(mapAttrAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricMetricInputType) updateCapacity() { + if m.data.Sum().DataPoints().Len() > m.capacity { + m.capacity = m.data.Sum().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricMetricInputType) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricMetricInputType(cfg MetricConfig) metricMetricInputType { + m := metricMetricInputType{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricOptionalMetric struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills optional.metric metric with initial data. +func (m *metricOptionalMetric) init() { + m.data.SetName("optional.metric") + m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.") + m.data.SetUnit("1") + m.data.SetEmptyGauge() + m.data.Gauge().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricOptionalMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool, booleanAttr2AttributeValue bool) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) + dp.Attributes().PutStr("string_attr", stringAttrAttributeValue) + dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue) + dp.Attributes().PutBool("boolean_attr2", booleanAttr2AttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricOptionalMetric) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricOptionalMetric) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricOptionalMetric(cfg MetricConfig) metricOptionalMetric { + m := metricOptionalMetric{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +type metricOptionalMetricEmptyUnit struct { + data pmetric.Metric // data buffer for generated metric. + config MetricConfig // metric config provided by user. + capacity int // max observed number of data points added to the metric. +} + +// init fills optional.metric.empty_unit metric with initial data. +func (m *metricOptionalMetricEmptyUnit) init() { + m.data.SetName("optional.metric.empty_unit") + m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.") + m.data.SetUnit("") + m.data.SetEmptyGauge() + m.data.Gauge().DataPoints().EnsureCapacity(m.capacity) +} + +func (m *metricOptionalMetricEmptyUnit) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) { + if !m.config.Enabled { + return + } + dp := m.data.Gauge().DataPoints().AppendEmpty() + dp.SetStartTimestamp(start) + dp.SetTimestamp(ts) + dp.SetDoubleValue(val) + dp.Attributes().PutStr("string_attr", stringAttrAttributeValue) + dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue) +} + +// updateCapacity saves max length of data point slices that will be used for the slice capacity. +func (m *metricOptionalMetricEmptyUnit) updateCapacity() { + if m.data.Gauge().DataPoints().Len() > m.capacity { + m.capacity = m.data.Gauge().DataPoints().Len() + } +} + +// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points. +func (m *metricOptionalMetricEmptyUnit) emit(metrics pmetric.MetricSlice) { + if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 { + m.updateCapacity() + m.data.MoveTo(metrics.AppendEmpty()) + m.init() + } +} + +func newMetricOptionalMetricEmptyUnit(cfg MetricConfig) metricOptionalMetricEmptyUnit { + m := metricOptionalMetricEmptyUnit{config: cfg} + if cfg.Enabled { + m.data = pmetric.NewMetric() + m.init() + } + return m +} + +// MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations +// required to produce metric representation defined in metadata and user config. +type MetricsBuilder struct { + config MetricsBuilderConfig // config of the metrics builder. + startTime pcommon.Timestamp // start time that will be applied to all recorded data points. + metricsCapacity int // maximum observed number of metrics per resource. + metricsBuffer pmetric.Metrics // accumulates metrics data before emitting. + buildInfo component.BuildInfo // contains version information. + resourceAttributeIncludeFilter map[string]filter.Filter + resourceAttributeExcludeFilter map[string]filter.Filter + metricDefaultMetric metricDefaultMetric + metricDefaultMetricToBeRemoved metricDefaultMetricToBeRemoved + metricMetricInputType metricMetricInputType + metricOptionalMetric metricOptionalMetric + metricOptionalMetricEmptyUnit metricOptionalMetricEmptyUnit +} + +// MetricBuilderOption applies changes to default metrics builder. +type MetricBuilderOption interface { + apply(*MetricsBuilder) +} + +type metricBuilderOptionFunc func(mb *MetricsBuilder) + +func (mbof metricBuilderOptionFunc) apply(mb *MetricsBuilder) { + mbof(mb) +} + +// WithStartTime sets startTime on the metrics builder. +func WithStartTime(startTime pcommon.Timestamp) MetricBuilderOption { + return metricBuilderOptionFunc(func(mb *MetricsBuilder) { + mb.startTime = startTime + }) +} + +func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.Settings, options ...MetricBuilderOption) *MetricsBuilder { + if !mbc.Metrics.DefaultMetric.enabledSetByUser { + settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `default.metric`: This metric will be disabled by default soon.") + } + if mbc.Metrics.DefaultMetricToBeRemoved.Enabled { + settings.Logger.Warn("[WARNING] `default.metric.to_be_removed` should not be enabled: This metric is deprecated and will be removed soon.") + } + if mbc.Metrics.OptionalMetric.enabledSetByUser { + settings.Logger.Warn("[WARNING] `optional.metric` should not be configured: This metric is deprecated and will be removed soon.") + } + if mbc.Metrics.OptionalMetricEmptyUnit.enabledSetByUser { + settings.Logger.Warn("[WARNING] `optional.metric.empty_unit` should not be configured: This metric is deprecated and will be removed soon.") + } + if !mbc.ResourceAttributes.StringResourceAttrDisableWarning.enabledSetByUser { + settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `string.resource.attr_disable_warning`: This resource_attribute will be disabled by default soon.") + } + if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.enabledSetByUser || mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsInclude != nil || mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsExclude != nil { + settings.Logger.Warn("[WARNING] `string.resource.attr_remove_warning` should not be configured: This resource_attribute is deprecated and will be removed soon.") + } + if mbc.ResourceAttributes.StringResourceAttrToBeRemoved.Enabled { + settings.Logger.Warn("[WARNING] `string.resource.attr_to_be_removed` should not be enabled: This resource_attribute is deprecated and will be removed soon.") + } + mb := &MetricsBuilder{ + config: mbc, + startTime: pcommon.NewTimestampFromTime(time.Now()), + metricsBuffer: pmetric.NewMetrics(), + buildInfo: settings.BuildInfo, + metricDefaultMetric: newMetricDefaultMetric(mbc.Metrics.DefaultMetric), + metricDefaultMetricToBeRemoved: newMetricDefaultMetricToBeRemoved(mbc.Metrics.DefaultMetricToBeRemoved), + metricMetricInputType: newMetricMetricInputType(mbc.Metrics.MetricInputType), + metricOptionalMetric: newMetricOptionalMetric(mbc.Metrics.OptionalMetric), + metricOptionalMetricEmptyUnit: newMetricOptionalMetricEmptyUnit(mbc.Metrics.OptionalMetricEmptyUnit), + resourceAttributeIncludeFilter: make(map[string]filter.Filter), + resourceAttributeExcludeFilter: make(map[string]filter.Filter), + } + if mbc.ResourceAttributes.MapResourceAttr.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["map.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.MapResourceAttr.MetricsInclude) + } + if mbc.ResourceAttributes.MapResourceAttr.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["map.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.MapResourceAttr.MetricsExclude) + } + if mbc.ResourceAttributes.OptionalResourceAttr.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["optional.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.OptionalResourceAttr.MetricsInclude) + } + if mbc.ResourceAttributes.OptionalResourceAttr.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["optional.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.OptionalResourceAttr.MetricsExclude) + } + if mbc.ResourceAttributes.SliceResourceAttr.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["slice.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.SliceResourceAttr.MetricsInclude) + } + if mbc.ResourceAttributes.SliceResourceAttr.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["slice.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.SliceResourceAttr.MetricsExclude) + } + if mbc.ResourceAttributes.StringEnumResourceAttr.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["string.enum.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.StringEnumResourceAttr.MetricsInclude) + } + if mbc.ResourceAttributes.StringEnumResourceAttr.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["string.enum.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.StringEnumResourceAttr.MetricsExclude) + } + if mbc.ResourceAttributes.StringResourceAttr.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["string.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttr.MetricsInclude) + } + if mbc.ResourceAttributes.StringResourceAttr.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["string.resource.attr"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttr.MetricsExclude) + } + if mbc.ResourceAttributes.StringResourceAttrDisableWarning.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["string.resource.attr_disable_warning"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrDisableWarning.MetricsInclude) + } + if mbc.ResourceAttributes.StringResourceAttrDisableWarning.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["string.resource.attr_disable_warning"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrDisableWarning.MetricsExclude) + } + if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["string.resource.attr_remove_warning"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsInclude) + } + if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["string.resource.attr_remove_warning"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrRemoveWarning.MetricsExclude) + } + if mbc.ResourceAttributes.StringResourceAttrToBeRemoved.MetricsInclude != nil { + mb.resourceAttributeIncludeFilter["string.resource.attr_to_be_removed"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrToBeRemoved.MetricsInclude) + } + if mbc.ResourceAttributes.StringResourceAttrToBeRemoved.MetricsExclude != nil { + mb.resourceAttributeExcludeFilter["string.resource.attr_to_be_removed"] = filter.CreateFilter(mbc.ResourceAttributes.StringResourceAttrToBeRemoved.MetricsExclude) + } + + for _, op := range options { + op.apply(mb) + } + return mb +} + +// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted metrics. +func (mb *MetricsBuilder) NewResourceBuilder() *ResourceBuilder { + return NewResourceBuilder(mb.config.ResourceAttributes) +} + +// updateCapacity updates max length of metrics and resource attributes that will be used for the slice capacity. +func (mb *MetricsBuilder) updateCapacity(rm pmetric.ResourceMetrics) { + if mb.metricsCapacity < rm.ScopeMetrics().At(0).Metrics().Len() { + mb.metricsCapacity = rm.ScopeMetrics().At(0).Metrics().Len() + } +} + +// ResourceMetricsOption applies changes to provided resource metrics. +type ResourceMetricsOption interface { + apply(pmetric.ResourceMetrics) +} + +type resourceMetricsOptionFunc func(pmetric.ResourceMetrics) + +func (rmof resourceMetricsOptionFunc) apply(rm pmetric.ResourceMetrics) { + rmof(rm) +} + +// WithResource sets the provided resource on the emitted ResourceMetrics. +// It's recommended to use ResourceBuilder to create the resource. +func WithResource(res pcommon.Resource) ResourceMetricsOption { + return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) { + res.CopyTo(rm.Resource()) + }) +} + +// WithStartTimeOverride overrides start time for all the resource metrics data points. +// This option should be only used if different start time has to be set on metrics coming from different resources. +func WithStartTimeOverride(start pcommon.Timestamp) ResourceMetricsOption { + return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) { + var dps pmetric.NumberDataPointSlice + metrics := rm.ScopeMetrics().At(0).Metrics() + for i := 0; i < metrics.Len(); i++ { + switch metrics.At(i).Type() { + case pmetric.MetricTypeGauge: + dps = metrics.At(i).Gauge().DataPoints() + case pmetric.MetricTypeSum: + dps = metrics.At(i).Sum().DataPoints() + } + for j := 0; j < dps.Len(); j++ { + dps.At(j).SetStartTimestamp(start) + } + } + }) +} + +// EmitForResource saves all the generated metrics under a new resource and updates the internal state to be ready for +// recording another set of data points as part of another resource. This function can be helpful when one scraper +// needs to emit metrics from several resources. Otherwise calling this function is not required, +// just `Emit` function can be called instead. +// Resource attributes should be provided as ResourceMetricsOption arguments. +func (mb *MetricsBuilder) EmitForResource(options ...ResourceMetricsOption) { + rm := pmetric.NewResourceMetrics() + rm.SetSchemaUrl(conventions.SchemaURL) + ils := rm.ScopeMetrics().AppendEmpty() + ils.Scope().SetName("go.opentelemetry.io/collector/internal/receiver/samplereceiver") + ils.Scope().SetVersion(mb.buildInfo.Version) + ils.Metrics().EnsureCapacity(mb.metricsCapacity) + mb.metricDefaultMetric.emit(ils.Metrics()) + mb.metricDefaultMetricToBeRemoved.emit(ils.Metrics()) + mb.metricMetricInputType.emit(ils.Metrics()) + mb.metricOptionalMetric.emit(ils.Metrics()) + mb.metricOptionalMetricEmptyUnit.emit(ils.Metrics()) + + for _, op := range options { + op.apply(rm) + } + for attr, filter := range mb.resourceAttributeIncludeFilter { + if val, ok := rm.Resource().Attributes().Get(attr); ok && !filter.Matches(val.AsString()) { + return + } + } + for attr, filter := range mb.resourceAttributeExcludeFilter { + if val, ok := rm.Resource().Attributes().Get(attr); ok && filter.Matches(val.AsString()) { + return + } + } + + if ils.Metrics().Len() > 0 { + mb.updateCapacity(rm) + rm.MoveTo(mb.metricsBuffer.ResourceMetrics().AppendEmpty()) + } +} + +// Emit returns all the metrics accumulated by the metrics builder and updates the internal state to be ready for +// recording another set of metrics. This function will be responsible for applying all the transformations required to +// produce metric representation defined in metadata and user config, e.g. delta or cumulative. +func (mb *MetricsBuilder) Emit(options ...ResourceMetricsOption) pmetric.Metrics { + mb.EmitForResource(options...) + metrics := mb.metricsBuffer + mb.metricsBuffer = pmetric.NewMetrics() + return metrics +} + +// RecordDefaultMetricDataPoint adds a data point to default.metric metric. +func (mb *MetricsBuilder) RecordDefaultMetricDataPoint(ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue AttributeEnumAttr, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) { + mb.metricDefaultMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, overriddenIntAttrAttributeValue, enumAttrAttributeValue.String(), sliceAttrAttributeValue, mapAttrAttributeValue) +} + +// RecordDefaultMetricToBeRemovedDataPoint adds a data point to default.metric.to_be_removed metric. +func (mb *MetricsBuilder) RecordDefaultMetricToBeRemovedDataPoint(ts pcommon.Timestamp, val float64) { + mb.metricDefaultMetricToBeRemoved.recordDataPoint(mb.startTime, ts, val) +} + +// RecordMetricInputTypeDataPoint adds a data point to metric.input_type metric. +func (mb *MetricsBuilder) RecordMetricInputTypeDataPoint(ts pcommon.Timestamp, inputVal string, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue AttributeEnumAttr, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) error { + val, err := strconv.ParseInt(inputVal, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse int64 for MetricInputType, value was %s: %w", inputVal, err) + } + mb.metricMetricInputType.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, overriddenIntAttrAttributeValue, enumAttrAttributeValue.String(), sliceAttrAttributeValue, mapAttrAttributeValue) + return nil +} + +// RecordOptionalMetricDataPoint adds a data point to optional.metric metric. +func (mb *MetricsBuilder) RecordOptionalMetricDataPoint(ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool, booleanAttr2AttributeValue bool) { + mb.metricOptionalMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue, booleanAttr2AttributeValue) +} + +// RecordOptionalMetricEmptyUnitDataPoint adds a data point to optional.metric.empty_unit metric. +func (mb *MetricsBuilder) RecordOptionalMetricEmptyUnitDataPoint(ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) { + mb.metricOptionalMetricEmptyUnit.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue) +} + +// Reset resets metrics builder to its initial state. It should be used when external metrics source is restarted, +// and metrics builder should update its startTime and reset it's internal state accordingly. +func (mb *MetricsBuilder) Reset(options ...MetricBuilderOption) { + mb.startTime = pcommon.NewTimestampFromTime(time.Now()) + for _, op := range options { + op.apply(mb) + } +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_metrics_test.go b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_metrics_test.go new file mode 100644 index 00000000000..8ef7ef3d711 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_metrics_test.go @@ -0,0 +1,264 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" + + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +type testDataSet int + +const ( + testDataSetDefault testDataSet = iota + testDataSetAll + testDataSetNone +) + +func TestMetricsBuilder(t *testing.T) { + tests := []struct { + name string + metricsSet testDataSet + resAttrsSet testDataSet + expectEmpty bool + }{ + { + name: "default", + }, + { + name: "all_set", + metricsSet: testDataSetAll, + resAttrsSet: testDataSetAll, + }, + { + name: "none_set", + metricsSet: testDataSetNone, + resAttrsSet: testDataSetNone, + expectEmpty: true, + }, + { + name: "filter_set_include", + resAttrsSet: testDataSetAll, + }, + { + name: "filter_set_exclude", + resAttrsSet: testDataSetAll, + expectEmpty: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + start := pcommon.Timestamp(1_000_000_000) + ts := pcommon.Timestamp(1_000_001_000) + observedZapCore, observedLogs := observer.New(zap.WarnLevel) + settings := receivertest.NewNopSettings() + settings.Logger = zap.New(observedZapCore) + mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, tt.name), settings, WithStartTime(start)) + + expectedWarnings := 0 + if tt.metricsSet == testDataSetDefault { + assert.Equal(t, "[WARNING] Please set `enabled` field explicitly for `default.metric`: This metric will be disabled by default soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if tt.metricsSet == testDataSetDefault || tt.metricsSet == testDataSetAll { + assert.Equal(t, "[WARNING] `default.metric.to_be_removed` should not be enabled: This metric is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if tt.metricsSet == testDataSetAll || tt.metricsSet == testDataSetNone { + assert.Equal(t, "[WARNING] `optional.metric` should not be configured: This metric is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if tt.metricsSet == testDataSetAll || tt.metricsSet == testDataSetNone { + assert.Equal(t, "[WARNING] `optional.metric.empty_unit` should not be configured: This metric is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if tt.resAttrsSet == testDataSetDefault { + assert.Equal(t, "[WARNING] Please set `enabled` field explicitly for `string.resource.attr_disable_warning`: This resource_attribute will be disabled by default soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if tt.resAttrsSet == testDataSetAll || tt.resAttrsSet == testDataSetNone { + assert.Equal(t, "[WARNING] `string.resource.attr_remove_warning` should not be configured: This resource_attribute is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + if tt.resAttrsSet == testDataSetDefault || tt.resAttrsSet == testDataSetAll { + assert.Equal(t, "[WARNING] `string.resource.attr_to_be_removed` should not be enabled: This resource_attribute is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message) + expectedWarnings++ + } + + assert.Equal(t, expectedWarnings, observedLogs.Len()) + + defaultMetricsCount := 0 + allMetricsCount := 0 + + defaultMetricsCount++ + allMetricsCount++ + mb.RecordDefaultMetricDataPoint(ts, 1, "string_attr-val", 19, AttributeEnumAttrRed, []any{"slice_attr-item1", "slice_attr-item2"}, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}) + + defaultMetricsCount++ + allMetricsCount++ + mb.RecordDefaultMetricToBeRemovedDataPoint(ts, 1) + + defaultMetricsCount++ + allMetricsCount++ + mb.RecordMetricInputTypeDataPoint(ts, "1", "string_attr-val", 19, AttributeEnumAttrRed, []any{"slice_attr-item1", "slice_attr-item2"}, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}) + + allMetricsCount++ + mb.RecordOptionalMetricDataPoint(ts, 1, "string_attr-val", true, false) + + allMetricsCount++ + mb.RecordOptionalMetricEmptyUnitDataPoint(ts, 1, "string_attr-val", true) + + rb := mb.NewResourceBuilder() + rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}) + rb.SetOptionalResourceAttr("optional.resource.attr-val") + rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"}) + rb.SetStringEnumResourceAttrOne() + rb.SetStringResourceAttr("string.resource.attr-val") + rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val") + rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val") + rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val") + res := rb.Emit() + metrics := mb.Emit(WithResource(res)) + + if tt.expectEmpty { + assert.Equal(t, 0, metrics.ResourceMetrics().Len()) + return + } + + assert.Equal(t, 1, metrics.ResourceMetrics().Len()) + rm := metrics.ResourceMetrics().At(0) + assert.Equal(t, res, rm.Resource()) + assert.Equal(t, 1, rm.ScopeMetrics().Len()) + ms := rm.ScopeMetrics().At(0).Metrics() + if tt.metricsSet == testDataSetDefault { + assert.Equal(t, defaultMetricsCount, ms.Len()) + } + if tt.metricsSet == testDataSetAll { + assert.Equal(t, allMetricsCount, ms.Len()) + } + validatedMetrics := make(map[string]bool) + for i := 0; i < ms.Len(); i++ { + switch ms.At(i).Name() { + case "default.metric": + assert.False(t, validatedMetrics["default.metric"], "Found a duplicate in the metrics slice: default.metric") + validatedMetrics["default.metric"] = true + assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len()) + assert.Equal(t, "Monotonic cumulative sum int metric enabled by default.", ms.At(i).Description()) + assert.Equal(t, "s", ms.At(i).Unit()) + assert.True(t, ms.At(i).Sum().IsMonotonic()) + assert.Equal(t, pmetric.AggregationTemporalityCumulative, ms.At(i).Sum().AggregationTemporality()) + dp := ms.At(i).Sum().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeInt, dp.ValueType()) + assert.Equal(t, int64(1), dp.IntValue()) + attrVal, ok := dp.Attributes().Get("string_attr") + assert.True(t, ok) + assert.EqualValues(t, "string_attr-val", attrVal.Str()) + attrVal, ok = dp.Attributes().Get("state") + assert.True(t, ok) + assert.EqualValues(t, 19, attrVal.Int()) + attrVal, ok = dp.Attributes().Get("enum_attr") + assert.True(t, ok) + assert.EqualValues(t, "red", attrVal.Str()) + attrVal, ok = dp.Attributes().Get("slice_attr") + assert.True(t, ok) + assert.EqualValues(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw()) + attrVal, ok = dp.Attributes().Get("map_attr") + assert.True(t, ok) + assert.EqualValues(t, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, attrVal.Map().AsRaw()) + case "default.metric.to_be_removed": + assert.False(t, validatedMetrics["default.metric.to_be_removed"], "Found a duplicate in the metrics slice: default.metric.to_be_removed") + validatedMetrics["default.metric.to_be_removed"] = true + assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len()) + assert.Equal(t, "[DEPRECATED] Non-monotonic delta sum double metric enabled by default.", ms.At(i).Description()) + assert.Equal(t, "s", ms.At(i).Unit()) + assert.False(t, ms.At(i).Sum().IsMonotonic()) + assert.Equal(t, pmetric.AggregationTemporalityDelta, ms.At(i).Sum().AggregationTemporality()) + dp := ms.At(i).Sum().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01) + case "metric.input_type": + assert.False(t, validatedMetrics["metric.input_type"], "Found a duplicate in the metrics slice: metric.input_type") + validatedMetrics["metric.input_type"] = true + assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len()) + assert.Equal(t, "Monotonic cumulative sum int metric with string input_type enabled by default.", ms.At(i).Description()) + assert.Equal(t, "s", ms.At(i).Unit()) + assert.True(t, ms.At(i).Sum().IsMonotonic()) + assert.Equal(t, pmetric.AggregationTemporalityCumulative, ms.At(i).Sum().AggregationTemporality()) + dp := ms.At(i).Sum().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeInt, dp.ValueType()) + assert.Equal(t, int64(1), dp.IntValue()) + attrVal, ok := dp.Attributes().Get("string_attr") + assert.True(t, ok) + assert.EqualValues(t, "string_attr-val", attrVal.Str()) + attrVal, ok = dp.Attributes().Get("state") + assert.True(t, ok) + assert.EqualValues(t, 19, attrVal.Int()) + attrVal, ok = dp.Attributes().Get("enum_attr") + assert.True(t, ok) + assert.EqualValues(t, "red", attrVal.Str()) + attrVal, ok = dp.Attributes().Get("slice_attr") + assert.True(t, ok) + assert.EqualValues(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw()) + attrVal, ok = dp.Attributes().Get("map_attr") + assert.True(t, ok) + assert.EqualValues(t, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, attrVal.Map().AsRaw()) + case "optional.metric": + assert.False(t, validatedMetrics["optional.metric"], "Found a duplicate in the metrics slice: optional.metric") + validatedMetrics["optional.metric"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description()) + assert.Equal(t, "1", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01) + attrVal, ok := dp.Attributes().Get("string_attr") + assert.True(t, ok) + assert.EqualValues(t, "string_attr-val", attrVal.Str()) + attrVal, ok = dp.Attributes().Get("boolean_attr") + assert.True(t, ok) + assert.True(t, attrVal.Bool()) + attrVal, ok = dp.Attributes().Get("boolean_attr2") + assert.True(t, ok) + assert.False(t, attrVal.Bool()) + case "optional.metric.empty_unit": + assert.False(t, validatedMetrics["optional.metric.empty_unit"], "Found a duplicate in the metrics slice: optional.metric.empty_unit") + validatedMetrics["optional.metric.empty_unit"] = true + assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type()) + assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len()) + assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description()) + assert.Equal(t, "", ms.At(i).Unit()) + dp := ms.At(i).Gauge().DataPoints().At(0) + assert.Equal(t, start, dp.StartTimestamp()) + assert.Equal(t, ts, dp.Timestamp()) + assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType()) + assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01) + attrVal, ok := dp.Attributes().Get("string_attr") + assert.True(t, ok) + assert.EqualValues(t, "string_attr-val", attrVal.Str()) + attrVal, ok = dp.Attributes().Get("boolean_attr") + assert.True(t, ok) + assert.True(t, attrVal.Bool()) + } + } + }) + } +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_resource.go b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_resource.go new file mode 100644 index 00000000000..9641095cdc4 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_resource.go @@ -0,0 +1,92 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "go.opentelemetry.io/collector/pdata/pcommon" +) + +// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml. +// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines. +type ResourceBuilder struct { + config ResourceAttributesConfig + res pcommon.Resource +} + +// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application. +func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder { + return &ResourceBuilder{ + config: rac, + res: pcommon.NewResource(), + } +} + +// SetMapResourceAttr sets provided value as "map.resource.attr" attribute. +func (rb *ResourceBuilder) SetMapResourceAttr(val map[string]any) { + if rb.config.MapResourceAttr.Enabled { + rb.res.Attributes().PutEmptyMap("map.resource.attr").FromRaw(val) + } +} + +// SetOptionalResourceAttr sets provided value as "optional.resource.attr" attribute. +func (rb *ResourceBuilder) SetOptionalResourceAttr(val string) { + if rb.config.OptionalResourceAttr.Enabled { + rb.res.Attributes().PutStr("optional.resource.attr", val) + } +} + +// SetSliceResourceAttr sets provided value as "slice.resource.attr" attribute. +func (rb *ResourceBuilder) SetSliceResourceAttr(val []any) { + if rb.config.SliceResourceAttr.Enabled { + rb.res.Attributes().PutEmptySlice("slice.resource.attr").FromRaw(val) + } +} + +// SetStringEnumResourceAttrOne sets "string.enum.resource.attr=one" attribute. +func (rb *ResourceBuilder) SetStringEnumResourceAttrOne() { + if rb.config.StringEnumResourceAttr.Enabled { + rb.res.Attributes().PutStr("string.enum.resource.attr", "one") + } +} + +// SetStringEnumResourceAttrTwo sets "string.enum.resource.attr=two" attribute. +func (rb *ResourceBuilder) SetStringEnumResourceAttrTwo() { + if rb.config.StringEnumResourceAttr.Enabled { + rb.res.Attributes().PutStr("string.enum.resource.attr", "two") + } +} + +// SetStringResourceAttr sets provided value as "string.resource.attr" attribute. +func (rb *ResourceBuilder) SetStringResourceAttr(val string) { + if rb.config.StringResourceAttr.Enabled { + rb.res.Attributes().PutStr("string.resource.attr", val) + } +} + +// SetStringResourceAttrDisableWarning sets provided value as "string.resource.attr_disable_warning" attribute. +func (rb *ResourceBuilder) SetStringResourceAttrDisableWarning(val string) { + if rb.config.StringResourceAttrDisableWarning.Enabled { + rb.res.Attributes().PutStr("string.resource.attr_disable_warning", val) + } +} + +// SetStringResourceAttrRemoveWarning sets provided value as "string.resource.attr_remove_warning" attribute. +func (rb *ResourceBuilder) SetStringResourceAttrRemoveWarning(val string) { + if rb.config.StringResourceAttrRemoveWarning.Enabled { + rb.res.Attributes().PutStr("string.resource.attr_remove_warning", val) + } +} + +// SetStringResourceAttrToBeRemoved sets provided value as "string.resource.attr_to_be_removed" attribute. +func (rb *ResourceBuilder) SetStringResourceAttrToBeRemoved(val string) { + if rb.config.StringResourceAttrToBeRemoved.Enabled { + rb.res.Attributes().PutStr("string.resource.attr_to_be_removed", val) + } +} + +// Emit returns the built resource and resets the internal builder state. +func (rb *ResourceBuilder) Emit() pcommon.Resource { + r := rb.res + rb.res = pcommon.NewResource() + return r +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_resource_test.go b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_resource_test.go new file mode 100644 index 00000000000..b8e33e3258d --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_resource_test.go @@ -0,0 +1,82 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResourceBuilder(t *testing.T) { + for _, tt := range []string{"default", "all_set", "none_set"} { + t.Run(tt, func(t *testing.T) { + cfg := loadResourceAttributesConfig(t, tt) + rb := NewResourceBuilder(cfg) + rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}) + rb.SetOptionalResourceAttr("optional.resource.attr-val") + rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"}) + rb.SetStringEnumResourceAttrOne() + rb.SetStringResourceAttr("string.resource.attr-val") + rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val") + rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val") + rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val") + + res := rb.Emit() + assert.Equal(t, 0, rb.Emit().Attributes().Len()) // Second call should return empty Resource + + switch tt { + case "default": + assert.Equal(t, 6, res.Attributes().Len()) + case "all_set": + assert.Equal(t, 8, res.Attributes().Len()) + case "none_set": + assert.Equal(t, 0, res.Attributes().Len()) + return + default: + assert.Failf(t, "unexpected test case: %s", tt) + } + + val, ok := res.Attributes().Get("map.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}, val.Map().AsRaw()) + } + val, ok = res.Attributes().Get("optional.resource.attr") + assert.Equal(t, tt == "all_set", ok) + if ok { + assert.EqualValues(t, "optional.resource.attr-val", val.Str()) + } + val, ok = res.Attributes().Get("slice.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, []any{"slice.resource.attr-item1", "slice.resource.attr-item2"}, val.Slice().AsRaw()) + } + val, ok = res.Attributes().Get("string.enum.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "one", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "string.resource.attr-val", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr_disable_warning") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "string.resource.attr_disable_warning-val", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr_remove_warning") + assert.Equal(t, tt == "all_set", ok) + if ok { + assert.EqualValues(t, "string.resource.attr_remove_warning-val", val.Str()) + } + val, ok = res.Attributes().Get("string.resource.attr_to_be_removed") + assert.True(t, ok) + if ok { + assert.EqualValues(t, "string.resource.attr_to_be_removed-val", val.Str()) + } + }) + } +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_status.go b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_status.go new file mode 100644 index 00000000000..4349b26b285 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_status.go @@ -0,0 +1,18 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("sample") + ScopeName = "go.opentelemetry.io/collector/internal/receiver/samplereceiver" +) + +const ( + LogsStability = component.StabilityLevelDevelopment + TracesStability = component.StabilityLevelBeta + MetricsStability = component.StabilityLevelStable +) diff --git a/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_telemetry.go b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_telemetry.go new file mode 100644 index 00000000000..2dbb3ad4e39 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_telemetry.go @@ -0,0 +1,111 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "context" + "errors" + + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configtelemetry" +) + +// Deprecated: [v0.108.0] use LeveledMeter instead. +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/internal/receiver/samplereceiver") +} + +func LeveledMeter(settings component.TelemetrySettings, level configtelemetry.Level) metric.Meter { + return settings.LeveledMeterProvider(level).Meter("go.opentelemetry.io/collector/internal/receiver/samplereceiver") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/internal/receiver/samplereceiver") +} + +// TelemetryBuilder provides an interface for components to report telemetry +// as defined in metadata and user config. +type TelemetryBuilder struct { + meter metric.Meter + BatchSizeTriggerSend metric.Int64Counter + ProcessRuntimeTotalAllocBytes metric.Int64ObservableCounter + observeProcessRuntimeTotalAllocBytes func(context.Context, metric.Observer) error + QueueLength metric.Int64ObservableGauge + RequestDuration metric.Float64Histogram + meters map[configtelemetry.Level]metric.Meter +} + +// TelemetryBuilderOption applies changes to default builder. +type TelemetryBuilderOption interface { + apply(*TelemetryBuilder) +} + +type telemetryBuilderOptionFunc func(mb *TelemetryBuilder) + +func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { + tbof(mb) +} + +// WithProcessRuntimeTotalAllocBytesCallback sets callback for observable ProcessRuntimeTotalAllocBytes metric. +func WithProcessRuntimeTotalAllocBytesCallback(cb func() int64, opts ...metric.ObserveOption) TelemetryBuilderOption { + return telemetryBuilderOptionFunc(func(builder *TelemetryBuilder) { + builder.observeProcessRuntimeTotalAllocBytes = func(_ context.Context, o metric.Observer) error { + o.ObserveInt64(builder.ProcessRuntimeTotalAllocBytes, cb(), opts...) + return nil + } + }) +} + +// InitQueueLength configures the QueueLength metric. +func (builder *TelemetryBuilder) InitQueueLength(cb func() int64, opts ...metric.ObserveOption) error { + var err error + builder.QueueLength, err = builder.meters[configtelemetry.LevelBasic].Int64ObservableGauge( + "otelcol_queue_length", + metric.WithDescription("This metric is optional and therefore not initialized in NewTelemetryBuilder."), + metric.WithUnit("{items}"), + ) + if err != nil { + return err + } + _, err = builder.meters[configtelemetry.LevelBasic].RegisterCallback(func(_ context.Context, o metric.Observer) error { + o.ObserveInt64(builder.QueueLength, cb(), opts...) + return nil + }, builder.QueueLength) + return err +} + +// NewTelemetryBuilder provides a struct with methods to update all internal telemetry +// for a component +func NewTelemetryBuilder(settings component.TelemetrySettings, options ...TelemetryBuilderOption) (*TelemetryBuilder, error) { + builder := TelemetryBuilder{meters: map[configtelemetry.Level]metric.Meter{}} + for _, op := range options { + op.apply(&builder) + } + builder.meters[configtelemetry.LevelBasic] = LeveledMeter(settings, configtelemetry.LevelBasic) + var err, errs error + builder.BatchSizeTriggerSend, err = builder.meters[configtelemetry.LevelBasic].Int64Counter( + "otelcol_batch_size_trigger_send", + metric.WithDescription("Number of times the batch was sent due to a size trigger [deprecated since v0.110.0]"), + metric.WithUnit("{times}"), + ) + errs = errors.Join(errs, err) + builder.ProcessRuntimeTotalAllocBytes, err = builder.meters[configtelemetry.LevelBasic].Int64ObservableCounter( + "otelcol_process_runtime_total_alloc_bytes", + metric.WithDescription("Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')"), + metric.WithUnit("By"), + ) + errs = errors.Join(errs, err) + _, err = builder.meters[configtelemetry.LevelBasic].RegisterCallback(builder.observeProcessRuntimeTotalAllocBytes, builder.ProcessRuntimeTotalAllocBytes) + errs = errors.Join(errs, err) + builder.RequestDuration, err = builder.meters[configtelemetry.LevelBasic].Float64Histogram( + "otelcol_request_duration", + metric.WithDescription("Duration of request [alpha]"), + metric.WithUnit("s"), + metric.WithExplicitBucketBoundaries([]float64{1, 10, 100}...), + ) + errs = errors.Join(errs, err) + return &builder, errs +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_telemetry_test.go b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_telemetry_test.go new file mode 100644 index 00000000000..b387e3c4782 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/custom/generated_telemetry_test.go @@ -0,0 +1,83 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package custom + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configtelemetry" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + LeveledMeterProvider: func(_ configtelemetry.Level) metric.MeterProvider { + return mockMeterProvider{} + }, + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/internal/receiver/samplereceiver", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/internal/receiver/samplereceiver", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} + +func TestNewTelemetryBuilder(t *testing.T) { + set := component.TelemetrySettings{ + LeveledMeterProvider: func(_ configtelemetry.Level) metric.MeterProvider { + return mockMeterProvider{} + }, + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + applied := false + _, err := NewTelemetryBuilder(set, telemetryBuilderOptionFunc(func(b *TelemetryBuilder) { + applied = true + })) + require.NoError(t, err) + require.True(t, applied) +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/custom/testdata/config.yaml b/cmd/mdatagen/internal/samplereceiver/internal/custom/testdata/config.yaml new file mode 100644 index 00000000000..c4b7edd6568 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/custom/testdata/config.yaml @@ -0,0 +1,127 @@ +default: +all_set: + metrics: + default.metric: + enabled: true + default.metric.to_be_removed: + enabled: true + metric.input_type: + enabled: true + optional.metric: + enabled: true + optional.metric.empty_unit: + enabled: true + resource_attributes: + map.resource.attr: + enabled: true + optional.resource.attr: + enabled: true + slice.resource.attr: + enabled: true + string.enum.resource.attr: + enabled: true + string.resource.attr: + enabled: true + string.resource.attr_disable_warning: + enabled: true + string.resource.attr_remove_warning: + enabled: true + string.resource.attr_to_be_removed: + enabled: true +none_set: + metrics: + default.metric: + enabled: false + default.metric.to_be_removed: + enabled: false + metric.input_type: + enabled: false + optional.metric: + enabled: false + optional.metric.empty_unit: + enabled: false + resource_attributes: + map.resource.attr: + enabled: false + optional.resource.attr: + enabled: false + slice.resource.attr: + enabled: false + string.enum.resource.attr: + enabled: false + string.resource.attr: + enabled: false + string.resource.attr_disable_warning: + enabled: false + string.resource.attr_remove_warning: + enabled: false + string.resource.attr_to_be_removed: + enabled: false +filter_set_include: + resource_attributes: + map.resource.attr: + enabled: true + metrics_include: + - regexp: ".*" + optional.resource.attr: + enabled: true + metrics_include: + - regexp: ".*" + slice.resource.attr: + enabled: true + metrics_include: + - regexp: ".*" + string.enum.resource.attr: + enabled: true + metrics_include: + - regexp: ".*" + string.resource.attr: + enabled: true + metrics_include: + - regexp: ".*" + string.resource.attr_disable_warning: + enabled: true + metrics_include: + - regexp: ".*" + string.resource.attr_remove_warning: + enabled: true + metrics_include: + - regexp: ".*" + string.resource.attr_to_be_removed: + enabled: true + metrics_include: + - regexp: ".*" +filter_set_exclude: + resource_attributes: + map.resource.attr: + enabled: true + metrics_exclude: + - regexp: ".*" + optional.resource.attr: + enabled: true + metrics_exclude: + - strict: "optional.resource.attr-val" + slice.resource.attr: + enabled: true + metrics_exclude: + - regexp: ".*" + string.enum.resource.attr: + enabled: true + metrics_exclude: + - strict: "one" + string.resource.attr: + enabled: true + metrics_exclude: + - strict: "string.resource.attr-val" + string.resource.attr_disable_warning: + enabled: true + metrics_exclude: + - strict: "string.resource.attr_disable_warning-val" + string.resource.attr_remove_warning: + enabled: true + metrics_exclude: + - strict: "string.resource.attr_remove_warning-val" + string.resource.attr_to_be_removed: + enabled: true + metrics_exclude: + - strict: "string.resource.attr_to_be_removed-val" diff --git a/cmd/mdatagen/internal/samplereceiver/metadata_custom.yaml b/cmd/mdatagen/internal/samplereceiver/metadata_custom.yaml new file mode 100644 index 00000000000..1f2a7449ec7 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/metadata_custom.yaml @@ -0,0 +1,201 @@ +# Sample metadata file with all available configurations for a receiver. + +type: sample +scope_name: go.opentelemetry.io/collector/internal/receiver/samplereceiver +github_project: open-telemetry/opentelemetry-collector + +generated_package_name: custom + +sem_conv_version: 1.9.0 + +status: + class: receiver + stability: + development: [logs] + beta: [traces] + stable: [metrics] + distributions: [] + unsupported_platforms: [freebsd, illumos] + codeowners: + active: [dmitryax] + warnings: + - Any additional information that should be brought to the consumer's attention + +resource_attributes: + string.resource.attr: + description: Resource attribute with any string value. + type: string + enabled: true + + string.enum.resource.attr: + description: Resource attribute with a known set of string values. + type: string + enum: [one, two] + enabled: true + + optional.resource.attr: + description: Explicitly disabled ResourceAttribute. + type: string + enabled: false + + slice.resource.attr: + description: Resource attribute with a slice value. + type: slice + enabled: true + + map.resource.attr: + description: Resource attribute with a map value. + type: map + enabled: true + + string.resource.attr_disable_warning: + description: Resource attribute with any string value. + type: string + enabled: true + warnings: + if_enabled_not_set: This resource_attribute will be disabled by default soon. + + string.resource.attr_remove_warning: + description: Resource attribute with any string value. + type: string + enabled: false + warnings: + if_configured: This resource_attribute is deprecated and will be removed soon. + + string.resource.attr_to_be_removed: + description: Resource attribute with any string value. + type: string + enabled: true + warnings: + if_enabled: This resource_attribute is deprecated and will be removed soon. + +attributes: + string_attr: + description: Attribute with any string value. + type: string + + overridden_int_attr: + name_override: state + description: Integer attribute with overridden name. + type: int + + enum_attr: + description: Attribute with a known set of string values. + type: string + enum: [red, green, blue] + + boolean_attr: + description: Attribute with a boolean value. + type: bool + + # This 2nd boolean attribute allows us to test both values for boolean attributes, + # as test values are based on the parity of the attribute name length. + boolean_attr2: + description: Another attribute with a boolean value. + type: bool + + slice_attr: + description: Attribute with a slice value. + type: slice + + map_attr: + description: Attribute with a map value. + type: map + +metrics: + default.metric: + enabled: true + description: Monotonic cumulative sum int metric enabled by default. + extended_documentation: The metric will be become optional soon. + unit: s + sum: + value_type: int + monotonic: true + aggregation_temporality: cumulative + attributes: [string_attr, overridden_int_attr, enum_attr, slice_attr, map_attr] + warnings: + if_enabled_not_set: This metric will be disabled by default soon. + + optional.metric: + enabled: false + description: "[DEPRECATED] Gauge double metric disabled by default." + unit: "1" + gauge: + value_type: double + attributes: [string_attr, boolean_attr, boolean_attr2] + warnings: + if_configured: This metric is deprecated and will be removed soon. + + optional.metric.empty_unit: + enabled: false + description: "[DEPRECATED] Gauge double metric disabled by default." + unit: "" + gauge: + value_type: double + attributes: [string_attr, boolean_attr] + warnings: + if_configured: This metric is deprecated and will be removed soon. + + default.metric.to_be_removed: + enabled: true + description: "[DEPRECATED] Non-monotonic delta sum double metric enabled by default." + extended_documentation: The metric will be will be removed soon. + unit: s + sum: + value_type: double + monotonic: false + aggregation_temporality: delta + warnings: + if_enabled: This metric is deprecated and will be removed soon. + + metric.input_type: + enabled: true + description: Monotonic cumulative sum int metric with string input_type enabled by default. + unit: s + sum: + value_type: int + input_type: string + monotonic: true + aggregation_temporality: cumulative + attributes: [ string_attr, overridden_int_attr, enum_attr, slice_attr, map_attr ] + +telemetry: + metrics: + batch_size_trigger_send: + enabled: true + stability: + level: deprecated + from: v0.110.0 + description: Number of times the batch was sent due to a size trigger + unit: "{times}" + sum: + value_type: int + monotonic: true + request_duration: + enabled: true + stability: + level: alpha + description: Duration of request + unit: s + histogram: + value_type: double + bucket_boundaries: [1, 10, 100] + process_runtime_total_alloc_bytes: + enabled: true + stability: + level: stable + description: Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc') + unit: By + sum: + async: true + value_type: int + monotonic: true + queue_length: + enabled: true + description: This metric is optional and therefore not initialized in NewTelemetryBuilder. + extended_documentation: For example this metric only exists if feature A is enabled. + unit: "{items}" + optional: true + gauge: + async: true + value_type: int