forked from influxdata/flux
-
Notifications
You must be signed in to change notification settings - Fork 1
/
flag.go
180 lines (154 loc) · 4.24 KB
/
flag.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package feature
import (
"context"
"fmt"
)
// Flag represents a generic feature flag with a key and a default.
type Flag interface {
// Key returns the programmatic backend identifier for the flag.
Key() string
// Default returns the type-agnostic zero value for the flag.
// Type-specific flag implementations may expose a typed default
// (e.g. BoolFlag includes a boolean Default field).
Default() interface{}
}
// MakeFlag constructs a Flag. The concrete implementation is inferred from the provided default.
func MakeFlag(name, key, owner string, defaultValue interface{}) Flag {
b := MakeBase(name, key, owner, defaultValue)
switch v := defaultValue.(type) {
case bool:
return BoolFlag{b, v}
case float64:
return FloatFlag{b, v}
case int32:
return IntFlag{b, int(v)}
case int:
return IntFlag{b, v}
case string:
return StringFlag{b, v}
default:
return StringFlag{b, fmt.Sprintf("%v", v)}
}
}
// Base implements the base of the Flag type.
type Base struct {
// name of the flag.
name string
// key is the programmatic backend identifier for the flag.
key string
// defaultValue for the flag.
defaultValue interface{}
// owner is an individual or team responsible for the flag.
owner string
}
var _ Flag = Base{}
// MakeBase constructs a flag.
func MakeBase(name, key, owner string, defaultValue interface{}) Base {
return Base{
name: name,
key: key,
owner: owner,
defaultValue: defaultValue,
}
}
// Key returns the programmatic backend identifier for the flag.
func (f Base) Key() string {
return f.key
}
// Default returns the type-agnostic zero value for the flag.
func (f Base) Default() interface{} {
return f.defaultValue
}
func (f Base) value(ctx context.Context) interface{} {
flagger := GetFlagger(ctx)
return flagger.FlagValue(ctx, f)
}
func (f Base) inc(v interface{}) {
metrics.Inc(f.key, v)
}
// StringFlag implements Flag for string values.
type StringFlag struct {
Base
defaultString string
}
var _ Flag = StringFlag{}
// MakeStringFlag returns a string flag with the given Base and default.
func MakeStringFlag(name, key, owner string, defaultValue string) StringFlag {
b := MakeBase(name, key, owner, defaultValue)
return StringFlag{b, defaultValue}
}
// String value of the flag on the request context.
func (f StringFlag) String(ctx context.Context) (v string) {
defer func() { f.inc(v) }()
s, ok := f.value(ctx).(string)
if !ok {
return f.defaultString
}
return s
}
// FloatFlag implements Flag for float values.
type FloatFlag struct {
Base
defaultFloat float64
}
var _ Flag = FloatFlag{}
// MakeFloatFlag returns a string flag with the given Base and default.
func MakeFloatFlag(name, key, owner string, defaultValue float64) FloatFlag {
b := MakeBase(name, key, owner, defaultValue)
return FloatFlag{b, defaultValue}
}
// Float value of the flag on the request context.
func (f FloatFlag) Float(ctx context.Context) (v float64) {
defer func() { f.inc(v) }()
v, ok := f.value(ctx).(float64)
if !ok {
return f.defaultFloat
}
return v
}
// IntFlag implements Flag for integer values.
type IntFlag struct {
Base
defaultInt int
}
var _ Flag = IntFlag{}
// MakeIntFlag returns a string flag with the given Base and default.
func MakeIntFlag(name, key, owner string, defaultValue int) IntFlag {
b := MakeBase(name, key, owner, defaultValue)
return IntFlag{b, defaultValue}
}
// Int value of the flag on the request context.
func (f IntFlag) Int(ctx context.Context) (v int) {
defer func() { f.inc(v) }()
// Ints sometimes get returned as floats.
switch i := f.value(ctx).(type) {
case float64:
return int(i)
case int32:
return int(i)
case int:
return i
default:
return f.defaultInt
}
}
// BoolFlag implements Flag for boolean values.
type BoolFlag struct {
Base
defaultBool bool
}
var _ Flag = BoolFlag{}
// MakeBoolFlag returns a string flag with the given Base and default.
func MakeBoolFlag(name, key, owner string, defaultValue bool) BoolFlag {
b := MakeBase(name, key, owner, defaultValue)
return BoolFlag{b, defaultValue}
}
// Enabled indicates whether flag is true or false on the request context.
func (f BoolFlag) Enabled(ctx context.Context) (v bool) {
defer func() { f.inc(v) }()
i, ok := f.value(ctx).(bool)
if !ok {
return f.defaultBool
}
return i
}