mirror of
https://github.com/hanzoai/telemetry.git
synced 2026-10-30 20:01:49 +00:00
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
#### Description
Make sure `flagValue.String()` can be called even when flagValue is
created by `reflect.New`
```go
import (
"flag"
"log"
"go.opentelemetry.io/collector/featuregate"
)
func main() {
fs := new(flag.FlagSet)
featuregate.GlobalRegistry().RegisterFlags(fs)
if err := fs.Parse([]string{"--help"}); err != nil {
log.Fatalf("failed to parse flags: %v", err)
}
}
```
Before this PR
```
Usage:
-feature-gates value
Comma-delimited list of feature gate identifiers. Prefix with '-' to disable the feature. '+' or no prefix will enable the feature.
panic calling String method on zero featuregate.flagValue for flag feature-gates: runtime error: invalid memory address or nil pointer dereference
failed to parse flags: flag: help requested
```
Note that there is a panic in the message.
After this PR
```
Usage:
-feature-gates value
Comma-delimited list of feature gate identifiers. Prefix with '-' to disable the feature. '+' or no prefix will enable the feature.
failed to parse flags: flag: help requested
```
---------
Co-authored-by: Yang Song <[email protected]>
72 lines
1.7 KiB
Go
72 lines
1.7 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package featuregate // import "go.opentelemetry.io/collector/featuregate"
|
|
|
|
import (
|
|
"flag"
|
|
"strings"
|
|
|
|
"go.uber.org/multierr"
|
|
)
|
|
|
|
const (
|
|
featureGatesFlag = "feature-gates"
|
|
featureGatesFlagDescription = "Comma-delimited list of feature gate identifiers. Prefix with '-' to disable the feature. '+' or no prefix will enable the feature."
|
|
)
|
|
|
|
// RegisterFlagsOption is an option for RegisterFlags.
|
|
type RegisterFlagsOption interface {
|
|
private()
|
|
}
|
|
|
|
// RegisterFlags that directly applies feature gate statuses to a Registry.
|
|
func (r *Registry) RegisterFlags(flagSet *flag.FlagSet, _ ...RegisterFlagsOption) {
|
|
flagSet.Var(&flagValue{reg: r}, featureGatesFlag, featureGatesFlagDescription)
|
|
}
|
|
|
|
// flagValue implements the flag.Value interface and directly applies feature gate statuses to a Registry.
|
|
type flagValue struct {
|
|
reg *Registry
|
|
}
|
|
|
|
func (f *flagValue) String() string {
|
|
// This function can be called by isZeroValue https://github.com/golang/go/blob/go1.23.3/src/flag/flag.go#L630
|
|
// which creates an instance of flagValue using reflect.New. In this case, the field `reg` is nil.
|
|
if f.reg == nil {
|
|
return ""
|
|
}
|
|
|
|
var ids []string
|
|
f.reg.VisitAll(func(g *Gate) {
|
|
id := g.ID()
|
|
if !g.IsEnabled() {
|
|
id = "-" + id
|
|
}
|
|
ids = append(ids, id)
|
|
})
|
|
return strings.Join(ids, ",")
|
|
}
|
|
|
|
func (f *flagValue) Set(s string) error {
|
|
if s == "" {
|
|
return nil
|
|
}
|
|
|
|
var errs error
|
|
ids := strings.Split(s, ",")
|
|
for i := range ids {
|
|
id := ids[i]
|
|
val := true
|
|
switch id[0] {
|
|
case '-':
|
|
id = id[1:]
|
|
val = false
|
|
case '+':
|
|
id = id[1:]
|
|
}
|
|
errs = multierr.Append(errs, f.reg.Set(id, val))
|
|
}
|
|
return errs
|
|
}
|