mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-04-15 00:36:23 +00:00
nfd-worker: dynamic configuration of klog
Make it possible to dynamically (at run-time) alter most of the logging configuration from the config file.
This commit is contained in:
parent
7da7fde8f6
commit
3f18e880b4
11 changed files with 311 additions and 3 deletions
|
@ -20,6 +20,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
|
@ -112,6 +113,8 @@ func initFlags(flagset *flag.FlagSet) (*worker.Args, *worker.ConfigOverrideArgs)
|
|||
flagset.StringVar(&args.ServerNameOverride, "server-name-override", "",
|
||||
"Hostname expected from server certificate, useful in testing")
|
||||
|
||||
initKlogFlags(flagset, args)
|
||||
|
||||
// Flags overlapping with config file options
|
||||
overrides := &worker.ConfigOverrideArgs{
|
||||
LabelWhiteList: &utils.RegexpVal{},
|
||||
|
@ -132,3 +135,24 @@ func initFlags(flagset *flag.FlagSet) (*worker.Args, *worker.ConfigOverrideArgs)
|
|||
|
||||
return args, overrides
|
||||
}
|
||||
|
||||
func initKlogFlags(flagset *flag.FlagSet, args *worker.Args) {
|
||||
args.Klog = make(map[string]*utils.KlogFlagVal)
|
||||
|
||||
flags := flag.NewFlagSet("klog flags", flag.ContinueOnError)
|
||||
//flags.SetOutput(ioutil.Discard)
|
||||
klog.InitFlags(flags)
|
||||
flags.VisitAll(func(f *flag.Flag) {
|
||||
name := klogConfigOptName(f.Name)
|
||||
args.Klog[name] = utils.NewKlogFlagVal(f)
|
||||
flagset.Var(args.Klog[name], f.Name, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
func klogConfigOptName(flagName string) string {
|
||||
split := strings.Split(flagName, "_")
|
||||
for i, v := range split[1:] {
|
||||
split[i+1] = strings.Title(v)
|
||||
}
|
||||
return strings.Join(split, "")
|
||||
}
|
||||
|
|
|
@ -59,3 +59,19 @@ func TestParseArgs(t *testing.T) {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestKlogConfigOptName(t *testing.T) {
|
||||
Convey("When converting names of klog command line flags", t, func() {
|
||||
tcs := map[string]string{
|
||||
"": "",
|
||||
"a": "a",
|
||||
"an_arg": "anArg",
|
||||
"arg_with_many_parts": "argWithManyParts",
|
||||
}
|
||||
Convey("resulting config option names should be as expected", func() {
|
||||
for input, expected := range tcs {
|
||||
So(klogConfigOptName(input), ShouldEqual, expected)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -77,6 +77,21 @@ worker:
|
|||
# noPublish: false
|
||||
# sleepInterval: 60s
|
||||
# sources: [all]
|
||||
# klog:
|
||||
# addDirHeader: false
|
||||
# alsologtostderr: false
|
||||
# logBacktraceAt:
|
||||
# logtostderr: true
|
||||
# skipHeaders: false
|
||||
# stderrthreshold: 2
|
||||
# v: 0
|
||||
# vmodule:
|
||||
## NOTE: the following options are not dynamically run-time configurable
|
||||
## and require a nfd-worker restart to take effect after being changed
|
||||
# logDir:
|
||||
# logFile:
|
||||
# logFileMaxSize: 1800
|
||||
# skipLogHeaders: false
|
||||
#sources:
|
||||
# cpu:
|
||||
# cpuid:
|
||||
|
|
|
@ -232,6 +232,10 @@ configuration file, instead.
|
|||
The following logging-related flags are inherited from the
|
||||
[klog](https://pkg.go.dev/k8s.io/klog/v2) package.
|
||||
|
||||
Note: The logger setup can also be specified via the `core.klog` configuration
|
||||
file options. However, the command line flags take precedence over any
|
||||
corresponding config file options specified.
|
||||
|
||||
#### -add_dir_header
|
||||
|
||||
If true, adds the file directory to the header of the log messages.
|
||||
|
|
|
@ -104,6 +104,109 @@ core:
|
|||
noPublish: true
|
||||
```
|
||||
|
||||
### core.klog
|
||||
|
||||
The following options specify the logger configuration. Most of which can be
|
||||
dynamically adjusted at run-time.
|
||||
|
||||
Note: The logger options can also be specified via command line flags which
|
||||
take precedence over any corresponding config file options.
|
||||
|
||||
#### core.klog.addDirHeader
|
||||
|
||||
If true, adds the file directory to the header of the log messages.
|
||||
|
||||
Default: false
|
||||
|
||||
Run-time configurable: yes
|
||||
|
||||
#### core.klog.alsologtostderr
|
||||
|
||||
Log to standard error as well as files.
|
||||
|
||||
Default: false
|
||||
|
||||
Run-time configurable: yes
|
||||
|
||||
#### core.klog.logBacktraceAt
|
||||
|
||||
When logging hits line file:N, emit a stack trace.
|
||||
|
||||
Default: *empty*
|
||||
|
||||
Run-time configurable: yes
|
||||
|
||||
#### core.klog.logDir
|
||||
|
||||
If non-empty, write log files in this directory.
|
||||
|
||||
Default: *empty*
|
||||
|
||||
Run-time configurable: no
|
||||
|
||||
#### core.klog.logFile
|
||||
|
||||
If non-empty, use this log file.
|
||||
|
||||
Default: *empty*
|
||||
|
||||
Run-time configurable: no
|
||||
|
||||
#### core.klog.logFileMaxSize
|
||||
|
||||
Defines the maximum size a log file can grow to. Unit is megabytes. If the
|
||||
value is 0, the maximum file size is unlimited.
|
||||
|
||||
Default: 1800
|
||||
|
||||
Run-time configurable: no
|
||||
|
||||
#### core.klog.logtostderr
|
||||
|
||||
Log to standard error instead of files
|
||||
|
||||
Default: true
|
||||
|
||||
Run-time configurable: yes
|
||||
|
||||
#### core.klog.skipHeaders
|
||||
|
||||
If true, avoid header prefixes in the log messages.
|
||||
|
||||
Default: false
|
||||
|
||||
Run-time configurable: yes
|
||||
|
||||
#### core.klog.skipLogHeaders
|
||||
|
||||
If true, avoid headers when opening log files.
|
||||
|
||||
Default: false
|
||||
|
||||
Run-time configurable: no
|
||||
|
||||
#### core.klog.stderrthreshold
|
||||
|
||||
Logs at or above this threshold go to stderr (default 2)
|
||||
|
||||
Run-time configurable: yes
|
||||
|
||||
#### core.klog.v
|
||||
|
||||
Number for the log level verbosity.
|
||||
|
||||
Default: 0
|
||||
|
||||
Run-time configurable: yes
|
||||
|
||||
#### core.klog.vmodule
|
||||
|
||||
Comma-separated list of `pattern=N` settings for file-filtered logging.
|
||||
|
||||
Default: *empty*
|
||||
|
||||
Run-time configurable: yes
|
||||
|
||||
## sources
|
||||
|
||||
The `sources` section contains feature source specific configuration parameters.
|
||||
|
|
|
@ -156,6 +156,21 @@ data:
|
|||
# noPublish: false
|
||||
# sleepInterval: 60s
|
||||
# sources: [all]
|
||||
# klog:
|
||||
# addDirHeader: false
|
||||
# alsologtostderr: false
|
||||
# logBacktraceAt:
|
||||
# logtostderr: true
|
||||
# skipHeaders: false
|
||||
# stderrthreshold: 2
|
||||
# v: 0
|
||||
# vmodule:
|
||||
## NOTE: the following options are not dynamically run-time configurable
|
||||
## and require a nfd-worker restart to take effect after being changed
|
||||
# logDir:
|
||||
# logFile:
|
||||
# logFileMaxSize: 1800
|
||||
# skipLogHeaders: false
|
||||
#sources:
|
||||
# cpu:
|
||||
# cpuid:
|
||||
|
|
|
@ -118,6 +118,21 @@ data:
|
|||
# noPublish: false
|
||||
# sleepInterval: 60s
|
||||
# sources: [all]
|
||||
# klog:
|
||||
# addDirHeader: false
|
||||
# alsologtostderr: false
|
||||
# logBacktraceAt:
|
||||
# logtostderr: true
|
||||
# skipHeaders: false
|
||||
# stderrthreshold: 2
|
||||
# v: 0
|
||||
# vmodule:
|
||||
## NOTE: the following options are not dynamically run-time configurable
|
||||
## and require a nfd-worker restart to take effect after being changed
|
||||
# logDir:
|
||||
# logFile:
|
||||
# logFileMaxSize: 1800
|
||||
# skipLogHeaders: false
|
||||
#sources:
|
||||
# cpu:
|
||||
# cpuid:
|
||||
|
|
|
@ -128,6 +128,21 @@ data:
|
|||
# noPublish: false
|
||||
# sleepInterval: 60s
|
||||
# sources: [all]
|
||||
# klog:
|
||||
# addDirHeader: false
|
||||
# alsologtostderr: false
|
||||
# logBacktraceAt:
|
||||
# logtostderr: true
|
||||
# skipHeaders: false
|
||||
# stderrthreshold: 2
|
||||
# v: 0
|
||||
# vmodule:
|
||||
## NOTE: the following options are not dynamically run-time configurable
|
||||
## and require a nfd-worker restart to take effect after being changed
|
||||
# logDir:
|
||||
# logFile:
|
||||
# logFileMaxSize: 1800
|
||||
# skipLogHeaders: false
|
||||
#sources:
|
||||
# cpu:
|
||||
# cpuid:
|
||||
|
|
|
@ -3,6 +3,21 @@
|
|||
# noPublish: false
|
||||
# sleepInterval: 60s
|
||||
# sources: [all]
|
||||
# klog:
|
||||
# addDirHeader: false
|
||||
# alsologtostderr: false
|
||||
# logBacktraceAt:
|
||||
# logtostderr: true
|
||||
# skipHeaders: false
|
||||
# stderrthreshold: 2
|
||||
# v: 0
|
||||
# vmodule:
|
||||
## NOTE: the following options are not dynamically run-time configurable
|
||||
## and require a nfd-worker restart to take effect after being changed
|
||||
# logDir:
|
||||
# logFile:
|
||||
# logFileMaxSize: 1800
|
||||
# skipLogHeaders: false
|
||||
#sources:
|
||||
# cpu:
|
||||
# cpuid:
|
||||
|
|
|
@ -66,6 +66,7 @@ type NFDConfig struct {
|
|||
}
|
||||
|
||||
type coreConfig struct {
|
||||
Klog map[string]string
|
||||
LabelWhiteList utils.RegexpVal
|
||||
NoPublish bool
|
||||
Sources []string
|
||||
|
@ -88,6 +89,7 @@ type Args struct {
|
|||
Server string
|
||||
ServerNameOverride string
|
||||
|
||||
Klog map[string]*utils.KlogFlagVal
|
||||
Overrides ConfigOverrideArgs
|
||||
}
|
||||
|
||||
|
@ -209,6 +211,7 @@ func newDefaultConfig() *NFDConfig {
|
|||
LabelWhiteList: utils.RegexpVal{Regexp: *regexp.MustCompile("")},
|
||||
SleepInterval: duration{60 * time.Second},
|
||||
Sources: []string{"all"},
|
||||
Klog: make(map[string]string),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -384,8 +387,26 @@ func (c *coreConfig) sanitize() {
|
|||
}
|
||||
}
|
||||
|
||||
func (w *nfdWorker) configureCore(c coreConfig) {
|
||||
// Determine enabled feature sourcds
|
||||
func (w *nfdWorker) configureCore(c coreConfig) error {
|
||||
// Handle klog
|
||||
for k, a := range w.args.Klog {
|
||||
if !a.IsSetFromCmdline() {
|
||||
v, ok := c.Klog[k]
|
||||
if !ok {
|
||||
v = a.DefValue()
|
||||
}
|
||||
if err := a.SetFromConfig(v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for k := range c.Klog {
|
||||
if _, ok := w.args.Klog[k]; !ok {
|
||||
klog.Warningf("unknown logger option in config: %q", k)
|
||||
}
|
||||
}
|
||||
|
||||
// Determine enabled feature sources
|
||||
sourceList := map[string]struct{}{}
|
||||
all := false
|
||||
for _, s := range c.Sources {
|
||||
|
@ -416,6 +437,7 @@ func (w *nfdWorker) configureCore(c coreConfig) {
|
|||
}
|
||||
klog.Warningf("skipping unknown source(s) %q specified in core.sources (or --sources)", strings.Join(names, ", "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parse configuration options
|
||||
|
@ -468,7 +490,9 @@ func (w *nfdWorker) configure(filepath string, overrides string) error {
|
|||
|
||||
w.config = c
|
||||
|
||||
w.configureCore(c.Core)
|
||||
if err := w.configureCore(c.Core); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// (Re-)configure all "real" sources, test sources are not configurable
|
||||
for _, s := range allSources {
|
||||
|
|
|
@ -18,6 +18,7 @@ package utils
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
|
@ -98,3 +99,64 @@ func (a *StringSliceVal) String() string {
|
|||
}
|
||||
return strings.Join(*a, ",")
|
||||
}
|
||||
|
||||
// KlogFlagVal is a wrapper to allow dynamic control of klog from the config file
|
||||
type KlogFlagVal struct {
|
||||
flag *flag.Flag
|
||||
isSetFromCmdLine bool
|
||||
}
|
||||
|
||||
// Set implements flag.Value interface
|
||||
func (k *KlogFlagVal) Set(value string) error {
|
||||
k.isSetFromCmdLine = true
|
||||
return k.flag.Value.Set(value)
|
||||
}
|
||||
|
||||
// String implements flag.Value interface
|
||||
func (k *KlogFlagVal) String() string {
|
||||
if k.flag == nil {
|
||||
return ""
|
||||
}
|
||||
// Need to handle "log_backtrace_at" in a special way
|
||||
s := k.flag.Value.String()
|
||||
if k.flag.Name == "log_backtrace_at" && s == ":0" {
|
||||
s = ""
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// DefValue returns the default value of KlogFlagVal as string
|
||||
func (k *KlogFlagVal) DefValue() string {
|
||||
// Need to handle "log_backtrace_at" in a special way
|
||||
d := k.flag.DefValue
|
||||
if k.flag.Name == "log_backtrace_at" && d == ":0" {
|
||||
d = ""
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// SetFromConfig sets the value without marking it as set from the cmdline
|
||||
func (k *KlogFlagVal) SetFromConfig(value string) error {
|
||||
return k.flag.Value.Set(value)
|
||||
}
|
||||
|
||||
// IsSetFromCmdline returns true if the value has been set via Set()
|
||||
func (k *KlogFlagVal) IsSetFromCmdline() bool { return k.isSetFromCmdLine }
|
||||
|
||||
// IsBoolFlag implements flag.boolFlag.IsBoolFlag() for wrapped klog flags.
|
||||
func (k *KlogFlagVal) IsBoolFlag() bool {
|
||||
if ba, ok := k.flag.Value.(boolFlag); ok {
|
||||
return ba.IsBoolFlag()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// NewKlogFlagVal wraps a klog flag into KlogFlagVal type
|
||||
func NewKlogFlagVal(f *flag.Flag) *KlogFlagVal {
|
||||
return &KlogFlagVal{flag: f}
|
||||
}
|
||||
|
||||
// boolFlag replicates boolFlag interface internal to the flag package
|
||||
type boolFlag interface {
|
||||
IsBoolFlag() bool
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue