2020-08-10 17:43:49 +00:00
/ *
Copyright 2019 The Kubernetes Authors .
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
package metrics
import (
"fmt"
2021-03-18 22:40:29 +00:00
"regexp"
2020-08-10 17:43:49 +00:00
"github.com/blang/semver"
"github.com/spf13/pflag"
"k8s.io/component-base/version"
)
// Options has all parameters needed for exposing metrics from components
type Options struct {
ShowHiddenMetricsForVersion string
2021-03-18 22:40:29 +00:00
DisabledMetrics [ ] string
AllowListMapping map [ string ] string
2020-08-10 17:43:49 +00:00
}
// NewOptions returns default metrics options
func NewOptions ( ) * Options {
return & Options { }
}
// Validate validates metrics flags options.
func ( o * Options ) Validate ( ) [ ] error {
2021-03-18 22:40:29 +00:00
var errs [ ] error
2020-08-10 17:43:49 +00:00
err := validateShowHiddenMetricsVersion ( parseVersion ( version . Get ( ) ) , o . ShowHiddenMetricsForVersion )
if err != nil {
2021-03-18 22:40:29 +00:00
errs = append ( errs , err )
2020-08-10 17:43:49 +00:00
}
2021-03-18 22:40:29 +00:00
if err := validateAllowMetricLabel ( o . AllowListMapping ) ; err != nil {
errs = append ( errs , err )
}
if len ( errs ) == 0 {
return nil
}
return errs
2020-08-10 17:43:49 +00:00
}
// AddFlags adds flags for exposing component metrics.
func ( o * Options ) AddFlags ( fs * pflag . FlagSet ) {
if o != nil {
o = NewOptions ( )
}
fs . StringVar ( & o . ShowHiddenMetricsForVersion , "show-hidden-metrics-for-version" , o . ShowHiddenMetricsForVersion ,
"The previous version for which you want to show hidden metrics. " +
"Only the previous minor version is meaningful, other values will not be allowed. " +
"The format is <major>.<minor>, e.g.: '1.16'. " +
"The purpose of this format is make sure you have the opportunity to notice if the next release hides additional metrics, " +
"rather than being surprised when they are permanently removed in the release after that." )
2021-03-18 22:40:29 +00:00
fs . StringSliceVar ( & o . DisabledMetrics ,
"disabled-metrics" ,
o . DisabledMetrics ,
"This flag provides an escape hatch for misbehaving metrics. " +
"You must provide the fully qualified metric name in order to disable it. " +
"Disclaimer: disabling metrics is higher in precedence than showing hidden metrics." )
fs . StringToStringVar ( & o . AllowListMapping , "allow-metric-labels" , o . AllowListMapping ,
"The map from metric-label to value allow-list of this label. The key's format is <MetricName>,<LabelName>. " +
"The value's format is <allowed_value>,<allowed_value>..." +
"e.g. metric1,label1='v1,v2,v3', metric1,label2='v1,v2,v3' metric2,label1='v1,v2,v3'." )
2020-08-10 17:43:49 +00:00
}
// Apply applies parameters into global configuration of metrics.
func ( o * Options ) Apply ( ) {
2021-03-18 22:40:29 +00:00
if o == nil {
return
}
if len ( o . ShowHiddenMetricsForVersion ) > 0 {
2020-08-10 17:43:49 +00:00
SetShowHidden ( )
}
2021-03-18 22:40:29 +00:00
// set disabled metrics
for _ , metricName := range o . DisabledMetrics {
SetDisabledMetric ( metricName )
}
if o . AllowListMapping != nil {
SetLabelAllowListFromCLI ( o . AllowListMapping )
}
2020-08-10 17:43:49 +00:00
}
func validateShowHiddenMetricsVersion ( currentVersion semver . Version , targetVersionStr string ) error {
if targetVersionStr == "" {
return nil
}
validVersionStr := fmt . Sprintf ( "%d.%d" , currentVersion . Major , currentVersion . Minor - 1 )
if targetVersionStr != validVersionStr {
return fmt . Errorf ( "--show-hidden-metrics-for-version must be omitted or have the value '%v'. Only the previous minor version is allowed" , validVersionStr )
}
return nil
}
2021-03-18 22:40:29 +00:00
func validateAllowMetricLabel ( allowListMapping map [ string ] string ) error {
if allowListMapping == nil {
return nil
}
metricNameRegex := ` [a-zA-Z_:][a-zA-Z0-9_:]* `
labelRegex := ` [a-zA-Z_][a-zA-Z0-9_]* `
for k := range allowListMapping {
reg := regexp . MustCompile ( metricNameRegex + ` , ` + labelRegex )
if reg . FindString ( k ) != k {
return fmt . Errorf ( "--allow-metric-labels must has a list of kv pair with format `metricName:labelName=labelValue, labelValue,...`" )
}
}
return nil
}