@@ -66,6 +66,32 @@ type Desc struct {
66
66
err error
67
67
}
68
68
69
+ type descriptorOptions struct {
70
+ validationScheme model.ValidationScheme
71
+ }
72
+
73
+ // newDescriptorOptions creates default descriptor options and applies opts.
74
+ func newDescriptorOptions (opts ... DescOption ) * descriptorOptions {
75
+ d := & descriptorOptions {
76
+ validationScheme : model .UTF8Validation ,
77
+ }
78
+ for _ , o := range opts {
79
+ o (d )
80
+ }
81
+ return d
82
+ }
83
+
84
+ // WithValidationScheme ensures descriptor's label and metric names adhere to scheme.
85
+ // Default is UTF-8 validation.
86
+ func WithValidationScheme (scheme model.ValidationScheme ) DescOption {
87
+ return func (o * descriptorOptions ) {
88
+ o .validationScheme = scheme
89
+ }
90
+ }
91
+
92
+ // DescOption are options that can be passed to NewDesc
93
+ type DescOption func (* descriptorOptions )
94
+
69
95
// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc
70
96
// and will be reported on registration time. variableLabels and constLabels can
71
97
// be nil if no such labels should be set. fqName must not be empty.
@@ -75,8 +101,8 @@ type Desc struct {
75
101
//
76
102
// For constLabels, the label values are constant. Therefore, they are fully
77
103
// specified in the Desc. See the Collector example for a usage pattern.
78
- func NewDesc (fqName , help string , variableLabels []string , constLabels Labels ) * Desc {
79
- return V2 .NewDesc (fqName , help , UnconstrainedLabels (variableLabels ), constLabels )
104
+ func NewDesc (fqName , help string , variableLabels []string , constLabels Labels , opts ... DescOption ) * Desc {
105
+ return V2 .NewDesc (fqName , help , UnconstrainedLabels (variableLabels ), constLabels , opts ... )
80
106
}
81
107
82
108
// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc
@@ -89,13 +115,14 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
89
115
//
90
116
// For constLabels, the label values are constant. Therefore, they are fully
91
117
// specified in the Desc. See the Collector example for a usage pattern.
92
- func (v2 ) NewDesc (fqName , help string , variableLabels ConstrainableLabels , constLabels Labels ) * Desc {
118
+ func (v2 ) NewDesc (fqName , help string , variableLabels ConstrainableLabels , constLabels Labels , opts ... DescOption ) * Desc {
93
119
d := & Desc {
94
120
fqName : fqName ,
95
121
help : help ,
96
122
variableLabels : variableLabels .compile (),
97
123
}
98
- if ! model .IsValidMetricName (model .LabelValue (fqName )) {
124
+ descOpts := newDescriptorOptions (opts ... )
125
+ if ! model .IsValidMetricName (model .LabelValue (fqName ), descOpts .validationScheme ) {
99
126
d .err = fmt .Errorf ("%q is not a valid metric name" , fqName )
100
127
return d
101
128
}
@@ -107,7 +134,7 @@ func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, const
107
134
labelNameSet := map [string ]struct {}{}
108
135
// First add only the const label names and sort them...
109
136
for labelName := range constLabels {
110
- if ! checkLabelName (labelName ) {
137
+ if ! checkLabelName (labelName , descOpts . validationScheme ) {
111
138
d .err = fmt .Errorf ("%q is not a valid label name for metric %q" , labelName , fqName )
112
139
return d
113
140
}
@@ -129,7 +156,7 @@ func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, const
129
156
// cannot be in a regular label name. That prevents matching the label
130
157
// dimension with a different mix between preset and variable labels.
131
158
for _ , label := range d .variableLabels .names {
132
- if ! checkLabelName (label ) {
159
+ if ! checkLabelName (label , descOpts . validationScheme ) {
133
160
d .err = fmt .Errorf ("%q is not a valid label name for metric %q" , label , fqName )
134
161
return d
135
162
}
0 commit comments