Skip to content

Commit

Permalink
Update cmd/mdatagen/internal/sampleprocessor/metadata.yaml
Browse files Browse the repository at this point in the history
Co-authored-by: Pablo Baeyens <[email protected]>
  • Loading branch information
narcis96 and mx-psi committed Oct 24, 2024
1 parent bb3c744 commit 7daa444
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 457 deletions.
363 changes: 0 additions & 363 deletions cmd/mdatagen/internal/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,327 +5,14 @@ package internal // import "go.opentelemetry.io/collector/cmd/mdatagen/internal"

import (
"context"
"errors"
"fmt"
"os/exec"
"path/filepath"
"regexp"
"strings"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config/configtelemetry"
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/confmaptest"
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
"go.opentelemetry.io/collector/filter"
"go.opentelemetry.io/collector/pdata/pcommon"
)

var (
// idRegexp is used to validate the ID of a Gate.
// IDs' characters must be alphanumeric or dots.
idRegexp = regexp.MustCompile(`^[0-9a-zA-Z\.]*$`)
versionRegexp = regexp.MustCompile(`^v(\d+)\.(\d+)\.(\d+)$`)
referenceURLRegexp = regexp.MustCompile(`^(https?:\/\/)?([a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+)(\/[^\s]*)?$`)
validStages = map[string]bool{
"StageAlpha": true,
"StageBeta": true,
"StageStable": true,
"StageDeprecated": true,
}
)

type MetricName string

func (mn MetricName) Render() (string, error) {
return FormatIdentifier(string(mn), true)
}

func (mn MetricName) RenderUnexported() (string, error) {
return FormatIdentifier(string(mn), false)
}

type AttributeName string

func (mn AttributeName) Render() (string, error) {
return FormatIdentifier(string(mn), true)
}

func (mn AttributeName) RenderUnexported() (string, error) {
return FormatIdentifier(string(mn), false)
}

type featureGateName string

func (mn featureGateName) Render() (string, error) {
return FormatIdentifier(string(mn), true)
}

func (mn featureGateName) RenderUnexported() (string, error) {
return FormatIdentifier(string(mn), false)
}

// ValueType defines an attribute value type.
type ValueType struct {
// ValueType is type of the attribute value.
ValueType pcommon.ValueType
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (mvt *ValueType) UnmarshalText(text []byte) error {
switch vtStr := string(text); vtStr {
case "string":
mvt.ValueType = pcommon.ValueTypeStr
case "int":
mvt.ValueType = pcommon.ValueTypeInt
case "double":
mvt.ValueType = pcommon.ValueTypeDouble
case "bool":
mvt.ValueType = pcommon.ValueTypeBool
case "bytes":
mvt.ValueType = pcommon.ValueTypeBytes
case "slice":
mvt.ValueType = pcommon.ValueTypeSlice
case "map":
mvt.ValueType = pcommon.ValueTypeMap
default:
return fmt.Errorf("invalid type: %q", vtStr)
}
return nil
}

// String returns capitalized name of the ValueType.
func (mvt ValueType) String() string {
return strings.Title(strings.ToLower(mvt.ValueType.String())) // nolint SA1019
}

// Primitive returns name of primitive type for the ValueType.
func (mvt ValueType) Primitive() string {
switch mvt.ValueType {
case pcommon.ValueTypeStr:
return "string"
case pcommon.ValueTypeInt:
return "int64"
case pcommon.ValueTypeDouble:
return "float64"
case pcommon.ValueTypeBool:
return "bool"
case pcommon.ValueTypeBytes:
return "[]byte"
case pcommon.ValueTypeSlice:
return "[]any"
case pcommon.ValueTypeMap:
return "map[string]any"
case pcommon.ValueTypeEmpty:
return ""
default:
return ""
}
}

type stability struct {
Level string `mapstructure:"level"`
From string `mapstructure:"from"`
}

func (s stability) String() string {
if len(s.Level) == 0 || strings.EqualFold(s.Level, component.StabilityLevelStable.String()) {
return ""
}
if len(s.From) > 0 {
return fmt.Sprintf(" [%s since %s]", s.Level, s.From)
}
return fmt.Sprintf(" [%s]", s.Level)
}

type Metric struct {
// Enabled defines whether the metric is enabled by default.
Enabled bool `mapstructure:"enabled"`

// Warnings that will be shown to user under specified conditions.
Warnings warnings `mapstructure:"warnings"`

// Description of the metric.
Description string `mapstructure:"description"`

// The stability level of the metric.
Stability stability `mapstructure:"stability"`

// ExtendedDocumentation of the metric. If specified, this will
// be appended to the description used in generated documentation.
ExtendedDocumentation string `mapstructure:"extended_documentation"`

// Optional can be used to specify metrics that may
// or may not be present in all cases, depending on configuration.
Optional bool `mapstructure:"optional"`

// Unit of the metric.
Unit *string `mapstructure:"unit"`

// Sum stores metadata for sum metric type
Sum *sum `mapstructure:"sum,omitempty"`
// Gauge stores metadata for gauge metric type
Gauge *gauge `mapstructure:"gauge,omitempty"`
// Histogram stores metadata for histogram metric type
Histogram *histogram `mapstructure:"histogram,omitempty"`

// Attributes is the list of attributes that the metric emits.
Attributes []AttributeName `mapstructure:"attributes"`

// Level specifies the minimum `configtelemetry.Level` for which
// the metric will be emitted. This only applies to internal telemetry
// configuration.
Level configtelemetry.Level `mapstructure:"level"`
}

func (m *Metric) Unmarshal(parser *confmap.Conf) error {
if !parser.IsSet("enabled") {
return errors.New("missing required field: `enabled`")
}
return parser.Unmarshal(m)
}

func (m Metric) Data() MetricData {
if m.Sum != nil {
return m.Sum
}
if m.Gauge != nil {
return m.Gauge
}
if m.Histogram != nil {
return m.Histogram
}
return nil
}

type warnings struct {
// A warning that will be displayed if the field is enabled in user config.
IfEnabled string `mapstructure:"if_enabled"`
// A warning that will be displayed if `enabled` field is not set explicitly in user config.
IfEnabledNotSet string `mapstructure:"if_enabled_not_set"`
// A warning that will be displayed if the field is configured by user in any way.
IfConfigured string `mapstructure:"if_configured"`
}

type Attribute struct {
// Description describes the purpose of the attribute.
Description string `mapstructure:"description"`
// NameOverride can be used to override the attribute name.
NameOverride string `mapstructure:"name_override"`
// Enabled defines whether the attribute is enabled by default.
Enabled bool `mapstructure:"enabled"`
// Include can be used to filter attributes.
Include []filter.Config `mapstructure:"include"`
// Include can be used to filter attributes.
Exclude []filter.Config `mapstructure:"exclude"`
// Enum can optionally describe the set of values to which the attribute can belong.
Enum []string `mapstructure:"enum"`
// Type is an attribute type.
Type ValueType `mapstructure:"type"`
// FullName is the attribute name populated from the map key.
FullName AttributeName `mapstructure:"-"`
// Warnings that will be shown to user under specified conditions.
Warnings warnings `mapstructure:"warnings"`
}

// Name returns actual name of the attribute that is set on the metric after applying NameOverride.
func (a Attribute) Name() AttributeName {
if a.NameOverride != "" {
return AttributeName(a.NameOverride)
}
return a.FullName
}

func (a Attribute) TestValue() string {
if a.Enum != nil {
return fmt.Sprintf(`"%s"`, a.Enum[0])
}
switch a.Type.ValueType {
case pcommon.ValueTypeEmpty:
return ""
case pcommon.ValueTypeStr:
return fmt.Sprintf(`"%s-val"`, a.FullName)
case pcommon.ValueTypeInt:
return fmt.Sprintf("%d", len(a.FullName))
case pcommon.ValueTypeDouble:
return fmt.Sprintf("%f", 0.1+float64(len(a.FullName)))
case pcommon.ValueTypeBool:
return fmt.Sprintf("%t", len(a.FullName)%2 == 0)
case pcommon.ValueTypeMap:
return fmt.Sprintf(`map[string]any{"key1": "%s-val1", "key2": "%s-val2"}`, a.FullName, a.FullName)
case pcommon.ValueTypeSlice:
return fmt.Sprintf(`[]any{"%s-item1", "%s-item2"}`, a.FullName, a.FullName)
case pcommon.ValueTypeBytes:
return fmt.Sprintf(`[]byte("%s-val")`, a.FullName)
}
return ""
}

type ignore struct {
Top []string `mapstructure:"top"`
Any []string `mapstructure:"any"`
}

type goLeak struct {
Skip bool `mapstructure:"skip"`
Ignore ignore `mapstructure:"ignore"`
Setup string `mapstructure:"setup"`
Teardown string `mapstructure:"teardown"`
}

type tests struct {
Config any `mapstructure:"config"`
SkipLifecycle bool `mapstructure:"skip_lifecycle"`
SkipShutdown bool `mapstructure:"skip_shutdown"`
GoLeak goLeak `mapstructure:"goleak"`
ExpectConsumerError bool `mapstructure:"expect_consumer_error"`
Host string `mapstructure:"host"`
}

type telemetry struct {
Level configtelemetry.Level `mapstructure:"level"`
Metrics map[MetricName]Metric `mapstructure:"metrics"`
}

func (t telemetry) Levels() map[string]interface{} {
levels := map[string]interface{}{}
for _, m := range t.Metrics {
levels[m.Level.String()] = nil
}
return levels
}

type Metadata struct {
// Type of the component.
Type string `mapstructure:"type"`
// Type of the parent component (applicable to subcomponents).
Parent string `mapstructure:"parent"`
// Status information for the component.
Status *Status `mapstructure:"status"`
// The name of the package that will be generated.
GeneratedPackageName string `mapstructure:"generated_package_name"`
// Telemetry information for the component.
Telemetry telemetry `mapstructure:"telemetry"`
// SemConvVersion is a version number of OpenTelemetry semantic conventions applied to the scraped metrics.
SemConvVersion string `mapstructure:"sem_conv_version"`
// ResourceAttributes that can be emitted by the component.
ResourceAttributes map[AttributeName]Attribute `mapstructure:"resource_attributes"`
// Attributes emitted by one or more metrics.
Attributes map[AttributeName]Attribute `mapstructure:"attributes"`
// Metrics that can be emitted by the component.
Metrics map[MetricName]Metric `mapstructure:"metrics"`
// GithubProject is the project where the component README lives in the format of org/repo, defaults to open-telemetry/opentelemetry-collector-contrib
GithubProject string `mapstructure:"github_project"`
// ScopeName of the metrics emitted by the component.
ScopeName string `mapstructure:"scope_name"`
// ShortFolderName is the shortened folder name of the component, removing class if present
ShortFolderName string `mapstructure:"-"`
// Tests is the set of tests generated with the component
Tests tests `mapstructure:"tests"`
// FeatureGates that can be used for the component.
FeatureGates map[featureGateName]featureGate `mapstructure:"feature_gates"`
}

func setAttributesFullName(attrs map[AttributeName]Attribute) {
for k, v := range attrs {
v.FullName = k
Expand Down Expand Up @@ -401,53 +88,3 @@ func packageName() (string, error) {
}
return strings.TrimSpace(string(output)), nil
}

type featureGate struct {
// Required.
ID string `mapstructure:"id"`
// Description describes the purpose of the attribute.
Description string `mapstructure:"description"`
// Stage current stage at which the feature gate is in the development lifecyle
Stage string `mapstructure:"stage"`
// ReferenceURL can optionally give the url of the feature_gate
ReferenceURL string `mapstructure:"reference_url"`
// FromVersion optional field which gives the release version from which the gate has been given the current stage
FromVersion string `mapstructure:"from_version"`
// ToVersion optional field which gives the release version till which the gate the gate had the given lifecycle stage
ToVersion string `mapstructure:"to_version"`
// FeatureGateName name of the feature gate
FeatureGateName featureGateName `mapstructure:"-"`
}

func (f *featureGate) validate(parser *confmap.Conf) error {
var err []error
if !parser.IsSet("id") {
err = append(err, errors.New("missing required field: `id`"))
} else if !idRegexp.MatchString(fmt.Sprintf("%v", parser.Get("id"))) {
err = append(err, fmt.Errorf("invalid character(s) in ID"))
}

if !parser.IsSet("stage") {
err = append(err, errors.New("missing required field: `stage`"))
} else if _, ok := validStages[fmt.Sprintf("%v", parser.Get("stage"))]; !ok {
err = append(err, fmt.Errorf("invalid stage"))
}

if parser.IsSet("from_version") && !versionRegexp.MatchString(fmt.Sprintf("%v", parser.Get("from_version"))) {
err = append(err, fmt.Errorf("invalid character(s) in from_version"))
}
if parser.IsSet("to_version") && !versionRegexp.MatchString(fmt.Sprintf("%v", parser.Get("to_version"))) {
err = append(err, fmt.Errorf("invalid character(s) in to_version"))
}
if parser.IsSet("reference_url") && !referenceURLRegexp.MatchString(fmt.Sprintf("%v", parser.Get("reference_url"))) {
err = append(err, fmt.Errorf("invalid character(s) in reference_url"))
}
return errors.Join(err...)
}

func (f *featureGate) Unmarshal(parser *confmap.Conf) error {
if err := f.validate(parser); err != nil {
return err
}
return parser.Unmarshal(f)
}
Loading

0 comments on commit 7daa444

Please sign in to comment.