diff --git a/cmd/nfd-master/main.go b/cmd/nfd-master/main.go index bd7fcf51d..ae00b2d4a 100644 --- a/cmd/nfd-master/main.go +++ b/cmd/nfd-master/main.go @@ -54,7 +54,7 @@ func main() { flags.Visit(func(f *flag.Flag) { switch f.Name { case "featurerules-controller": - klog.Warningf("-featurerules-controller is deprecated, use '-crd-controller' flag instead") + klog.InfoS("-featurerules-controller is deprecated, use '-crd-controller' flag instead") case "extra-label-ns": args.Overrides.ExtraLabelNs = overrides.ExtraLabelNs case "deny-label-ns": @@ -62,7 +62,7 @@ func main() { case "label-whitelist": args.Overrides.LabelWhiteList = overrides.LabelWhiteList case "resource-labels": - klog.Warningf("-resource-labels is deprecated, extended resources should be managed with NodeFeatureRule objects") + klog.InfoS("-resource-labels is deprecated, extended resources should be managed with NodeFeatureRule objects") args.Overrides.ResourceLabels = overrides.ResourceLabels case "enable-taints": args.Overrides.EnableTaints = overrides.EnableTaints @@ -80,7 +80,7 @@ func main() { // Assert that the version is known if version.Undefined() { - klog.Warningf("version not set! Set -ldflags \"-X sigs.k8s.io/node-feature-discovery/pkg/version.version=`git describe --tags --dirty --always`\" during build or run.") + klog.InfoS("version not set! Set -ldflags \"-X sigs.k8s.io/node-feature-discovery/pkg/version.version=`git describe --tags --dirty --always`\" during build or run.") } // Plug klog into grpc logging infrastructure @@ -89,11 +89,13 @@ func main() { // Get new NfdMaster instance instance, err := master.NewNfdMaster(args) if err != nil { - klog.Exitf("failed to initialize NfdMaster instance: %v", err) + klog.ErrorS(err, "failed to initialize NfdMaster instance") + os.Exit(1) } if err = instance.Run(); err != nil { - klog.Exit(err) + klog.ErrorS(err, "error while running") + os.Exit(1) } } diff --git a/cmd/nfd-topology-gc/main.go b/cmd/nfd-topology-gc/main.go index ac66bb3b0..99626a489 100644 --- a/cmd/nfd-topology-gc/main.go +++ b/cmd/nfd-topology-gc/main.go @@ -47,17 +47,19 @@ func main() { // Assert that the version is known if version.Undefined() { - klog.Warningf("version not set! Set -ldflags \"-X sigs.k8s.io/node-feature-discovery/pkg/version.version=`git describe --tags --dirty --always`\" during build or run.") + klog.InfoS("version not set! Set -ldflags \"-X sigs.k8s.io/node-feature-discovery/pkg/version.version=`git describe --tags --dirty --always`\" during build or run.") } // Get new TopologyGC instance gc, err := nfdtopologygarbagecollector.New(args) if err != nil { - klog.Exit(err) + klog.ErrorS(err, "failed to initialize topology garbage collector instance") + os.Exit(1) } if err = gc.Run(); err != nil { - klog.Exit(err) + klog.ErrorS(err, "error while running") + os.Exit(1) } } diff --git a/cmd/nfd-topology-updater/main.go b/cmd/nfd-topology-updater/main.go index d9627e3de..b85732520 100644 --- a/cmd/nfd-topology-updater/main.go +++ b/cmd/nfd-topology-updater/main.go @@ -57,47 +57,28 @@ func main() { // Assert that the version is known if version.Undefined() { - klog.Warningf("version not set! Set -ldflags \"-X sigs.k8s.io/node-feature-discovery/pkg/version.version=`git describe --tags --dirty --always`\" during build or run.") + klog.InfoS("version not set! Set -ldflags \"-X sigs.k8s.io/node-feature-discovery/pkg/version.version=`git describe --tags --dirty --always`\" during build or run.") } // Plug klog into grpc logging infrastructure utils.ConfigureGrpcKlog() - u, err := url.ParseRequestURI(resourcemonitorArgs.KubeletConfigURI) + klConfig, err := getKubeletConfig(resourcemonitorArgs.KubeletConfigURI, resourcemonitorArgs.APIAuthTokenFile) if err != nil { - klog.Exitf("failed to parse args for kubelet-config-uri: %v", err) - } - - // init kubelet API client - var klConfig *kubeletconfigv1beta1.KubeletConfiguration - switch u.Scheme { - case "file": - klConfig, err = kubeconf.GetKubeletConfigFromLocalFile(u.Path) - if err != nil { - klog.Exitf("failed to read kubelet config: %v", err) - } - case "https": - restConfig, err := kubeconf.InsecureConfig(u.String(), resourcemonitorArgs.APIAuthTokenFile) - if err != nil { - klog.Exitf("failed to initialize rest config for kubelet config uri: %v", err) - } - - klConfig, err = kubeconf.GetKubeletConfiguration(restConfig) - if err != nil { - klog.Exitf("failed to get kubelet config from configz endpoint: %v", err) - } - default: - klog.Exitf("unsupported URI scheme: %v", u.Scheme) + klog.ErrorS(err, "failed to get kubelet configuration") + os.Exit(1) } // Get new TopologyUpdater instance instance, err := topology.NewTopologyUpdater(*args, *resourcemonitorArgs, klConfig.TopologyManagerPolicy, klConfig.TopologyManagerScope) if err != nil { - klog.Exit(err) + klog.ErrorS(err, "failed to initialize topology updater instance") + os.Exit(1) } if err = instance.Run(); err != nil { - klog.Exit(err) + klog.ErrorS(err, "error while running") + os.Exit(1) } } @@ -153,3 +134,34 @@ func initFlags(flagset *flag.FlagSet) (*topology.Args, *resourcemonitor.Args) { return args, resourcemonitorArgs } + +func getKubeletConfig(uri, apiAuthTokenFile string) (*kubeletconfigv1beta1.KubeletConfiguration, error) { + u, err := url.ParseRequestURI(uri) + if err != nil { + return nil, fmt.Errorf("failed to parse -kubelet-config-uri: %w", err) + } + + // init kubelet API client + var klConfig *kubeletconfigv1beta1.KubeletConfiguration + switch u.Scheme { + case "file": + klConfig, err = kubeconf.GetKubeletConfigFromLocalFile(u.Path) + if err != nil { + return nil, fmt.Errorf("failed to read kubelet config: %w", err) + } + return klConfig, err + case "https": + restConfig, err := kubeconf.InsecureConfig(u.String(), apiAuthTokenFile) + if err != nil { + return nil, fmt.Errorf("failed to initialize rest config for kubelet config uri: %w", err) + } + + klConfig, err = kubeconf.GetKubeletConfiguration(restConfig) + if err != nil { + return nil, fmt.Errorf("failed to get kubelet config from configz endpoint: %w", err) + } + return klConfig, nil + } + + return nil, fmt.Errorf("unsupported URI scheme: %v", u.Scheme) +} diff --git a/cmd/nfd-worker/main.go b/cmd/nfd-worker/main.go index 2e6675e22..02866257d 100644 --- a/cmd/nfd-worker/main.go +++ b/cmd/nfd-worker/main.go @@ -48,7 +48,7 @@ func main() { // Assert that the version is known if version.Undefined() { - klog.Warningf("version not set! Set -ldflags \"-X sigs.k8s.io/node-feature-discovery/pkg/version.version=`git describe --tags --dirty --always`\" during build or run.") + klog.InfoS("version not set! Set -ldflags \"-X sigs.k8s.io/node-feature-discovery/pkg/version.version=`git describe --tags --dirty --always`\" during build or run.") } // Plug klog into grpc logging infrastructure @@ -57,11 +57,13 @@ func main() { // Get new NfdWorker instance instance, err := worker.NewNfdWorker(args) if err != nil { - klog.Exitf("failed to initialize NfdWorker instance: %v", err) + klog.ErrorS(err, "failed to initialize NfdWorker instance") + os.Exit(1) } if err = instance.Run(); err != nil { - klog.Exit(err) + klog.ErrorS(err, "error while running") + os.Exit(1) } } diff --git a/pkg/apis/nfd/v1alpha1/expression.go b/pkg/apis/nfd/v1alpha1/expression.go index 47108ab22..febf5faa5 100644 --- a/pkg/apis/nfd/v1alpha1/expression.go +++ b/pkg/apis/nfd/v1alpha1/expression.go @@ -210,18 +210,15 @@ func (m *MatchExpression) MatchKeys(name string, keys map[string]Nil) (bool, err return false, fmt.Errorf("invalid Op %q when matching keys", m.Op) } - if klog.V(3).Enabled() { - mString := map[bool]string{false: "no match", true: "match found"}[matched] + if klogV := klog.V(3); klogV.Enabled() { + klogV.InfoS("matched keys", "matchResult", "matched", "matchKey", name, "matchOp", m.Op) + } else if klogV := klog.V(4); klogV.Enabled() { k := make([]string, 0, len(keys)) for n := range keys { k = append(k, n) } sort.Strings(k) - if len(keys) < 10 || klog.V(4).Enabled() { - klog.Infof("%s when matching %q %q against %s", mString, name, m.Op, strings.Join(k, " ")) - } else { - klog.Infof("%s when matching %q %q against %s... (list truncated)", mString, name, m.Op, strings.Join(k[0:10], ", ")) - } + klogV.InfoS("matched keys", "matchResult", "matched", "matchKey", name, "matchOp", m.Op, "inputKeys", k) } return matched, nil } @@ -234,25 +231,10 @@ func (m *MatchExpression) MatchValues(name string, values map[string]string) (bo return false, err } - if klog.V(3).Enabled() { - mString := map[bool]string{false: "no match", true: "match found"}[matched] - - keys := make([]string, 0, len(values)) - for k := range values { - keys = append(keys, k) - } - sort.Strings(keys) - - kv := make([]string, len(keys)) - for i, k := range keys { - kv[i] = k + ":" + values[k] - } - - if len(values) < 10 || klog.V(4).Enabled() { - klog.Infof("%s when matching %q %q %v against %s", mString, name, m.Op, m.Value, strings.Join(kv, " ")) - } else { - klog.Infof("%s when matching %q %q %v against %s... (list truncated)", mString, name, m.Op, m.Value, strings.Join(kv[0:10], " ")) - } + if klogV := klog.V(3); klogV.Enabled() { + klogV.InfoS("matched values", "matchResult", "matched", "matchKey", name, "matchOp", m.Op, "matchValue", m.Value) + } else if klogV := klog.V(4); klogV.Enabled() { + klogV.InfoS("matched values", "matchResult", "matched", "matchKey", name, "matchOp", m.Op, "matchValue", m.Value, "inputValues", values) } return matched, nil diff --git a/pkg/apis/nfd/v1alpha1/rule.go b/pkg/apis/nfd/v1alpha1/rule.go index 01535d7d3..6bea00dee 100644 --- a/pkg/apis/nfd/v1alpha1/rule.go +++ b/pkg/apis/nfd/v1alpha1/rule.go @@ -50,7 +50,7 @@ func (r *Rule) Execute(features *Features) (RuleOutput, error) { return RuleOutput{}, err } else if isMatch { matched = true - utils.KlogDump(4, "matches for matchAny "+r.Name, " ", matches) + klog.V(4).InfoS("matchAny matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(matches)) if r.LabelsTemplate == "" && r.VarsTemplate == "" { // there's no need to evaluate other matchers in MatchAny @@ -68,7 +68,7 @@ func (r *Rule) Execute(features *Features) (RuleOutput, error) { } } if !matched { - klog.V(2).Infof("rule %q did not match", r.Name) + klog.V(2).InfoS("rule did not match", "ruleName", r.Name) return RuleOutput{}, nil } } @@ -77,10 +77,10 @@ func (r *Rule) Execute(features *Features) (RuleOutput, error) { if isMatch, matches, err := r.MatchFeatures.match(features); err != nil { return RuleOutput{}, err } else if !isMatch { - klog.V(2).Infof("rule %q did not match", r.Name) + klog.V(2).InfoS("rule did not match", "ruleName", r.Name) return RuleOutput{}, nil } else { - utils.KlogDump(4, "matches for matchFeatures "+r.Name, " ", matches) + klog.V(4).InfoS("matchFeatures matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(matches)) if err := r.executeLabelsTemplate(matches, labels); err != nil { return RuleOutput{}, err } @@ -102,7 +102,7 @@ func (r *Rule) Execute(features *Features) (RuleOutput, error) { } ret := RuleOutput{ExtendedResources: extendedResources, Labels: labels, Vars: vars, Taints: r.Taints} - utils.KlogDump(2, fmt.Sprintf("rule %q matched with: ", r.Name), " ", ret) + klog.V(2).InfoS("rule matched", "ruleName", r.Name, "ruleOutput", utils.DelayedDumper(ret)) return ret, nil } @@ -169,7 +169,7 @@ func (m *FeatureMatcher) match(features *Features) (bool, matchedFeatures, error nameSplit := strings.SplitN(term.Feature, ".", 2) if len(nameSplit) != 2 { - klog.Warning("feature %q not of format ., cannot be used for templating", term.Feature) + klog.InfoS("invalid feature name (not .), cannot be used for templating", "featureName", term.Feature) nameSplit = []string{featureName, ""} } diff --git a/pkg/nfd-master/nfd-api-controller.go b/pkg/nfd-master/nfd-api-controller.go index 147afc430..00c606eee 100644 --- a/pkg/nfd-master/nfd-api-controller.go +++ b/pkg/nfd-master/nfd-api-controller.go @@ -57,7 +57,7 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC } nfdClient := nfdclientset.NewForConfigOrDie(config) - utils.KlogDump(2, "NFD API controller options:", " ", nfdApiControllerOptions) + klog.V(2).InfoS("initializing new NFD API controller", "options", utils.DelayedDumper(nfdApiControllerOptions)) informerFactory := nfdinformers.NewSharedInformerFactory(nfdClient, nfdApiControllerOptions.ResyncPeriod) @@ -67,17 +67,17 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC if _, err := featureInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { nfr := obj.(*nfdv1alpha1.NodeFeature) - klog.V(2).Infof("NodeFeature %s/%s added", nfr.Namespace, nfr.Name) + klog.V(2).InfoS("NodeFeature added", "nodefeature", klog.KObj(nfr)) c.updateOneNode("NodeFeature", nfr) }, UpdateFunc: func(oldObj, newObj interface{}) { nfr := newObj.(*nfdv1alpha1.NodeFeature) - klog.V(2).Infof("NodeFeature %s/%s updated", nfr.Namespace, nfr.Name) + klog.V(2).InfoS("NodeFeature updated", "nodefeature", klog.KObj(nfr)) c.updateOneNode("NodeFeature", nfr) }, DeleteFunc: func(obj interface{}) { nfr := obj.(*nfdv1alpha1.NodeFeature) - klog.V(2).Infof("NodeFeature %s/%s deleted", nfr.Namespace, nfr.Name) + klog.V(2).InfoS("NodeFeature deleted", "nodefeature", klog.KObj(nfr)) c.updateOneNode("NodeFeature", nfr) }, }); err != nil { @@ -90,24 +90,21 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC ruleInformer := informerFactory.Nfd().V1alpha1().NodeFeatureRules() if _, err := ruleInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(object interface{}) { - key, _ := cache.MetaNamespaceKeyFunc(object) - klog.V(2).Infof("NodeFeatureRule %v added", key) + klog.V(2).InfoS("NodeFeatureRule added", "nodefeaturerule", klog.KObj(object.(metav1.Object))) if !nfdApiControllerOptions.DisableNodeFeature { c.updateAllNodes() } // else: rules will be processed only when gRPC requests are received }, UpdateFunc: func(oldObject, newObject interface{}) { - key, _ := cache.MetaNamespaceKeyFunc(newObject) - klog.V(2).Infof("NodeFeatureRule %v updated", key) + klog.V(2).InfoS("NodeFeatureRule updated", "nodefeaturerule", klog.KObj(newObject.(metav1.Object))) if !nfdApiControllerOptions.DisableNodeFeature { c.updateAllNodes() } // else: rules will be processed only when gRPC requests are received }, DeleteFunc: func(object interface{}) { - key, _ := cache.MetaNamespaceKeyFunc(object) - klog.V(2).Infof("NodeFeatureRule %v deleted", key) + klog.V(2).InfoS("NodeFeatureRule deleted", "nodefeaturerule", klog.KObj(object.(metav1.Object))) if !nfdApiControllerOptions.DisableNodeFeature { c.updateAllNodes() } @@ -135,7 +132,7 @@ func (c *nfdController) stop() { func (c *nfdController) updateOneNode(typ string, obj metav1.Object) { nodeName, err := getNodeNameForObj(obj) if err != nil { - klog.Errorf("failed to determine node name for %s %s/%s: %v", typ, obj.GetNamespace(), obj.GetName(), err) + klog.ErrorS(err, "failed to determine node name for object", "type", typ, "object", klog.KObj(obj)) return } c.updateOneNodeChan <- nodeName diff --git a/pkg/nfd-master/nfd-master.go b/pkg/nfd-master/nfd-master.go index b5a31cbd5..bf6d09e9a 100644 --- a/pkg/nfd-master/nfd-master.go +++ b/pkg/nfd-master/nfd-master.go @@ -199,12 +199,10 @@ func newDefaultConfig() *NFDConfig { // Run NfdMaster server. The method returns in case of fatal errors or if Stop() // is called. func (m *nfdMaster) Run() error { - klog.Infof("Node Feature Discovery Master %s", version.Get()) + klog.InfoS("Node Feature Discovery Master", "version", version.Get(), "nodeName", m.nodeName, "namespace", m.namespace) if m.args.Instance != "" { - klog.Infof("Master instance: %q", m.args.Instance) + klog.InfoS("Master instance", "instance", m.args.Instance) } - klog.Infof("NodeName: %q", m.nodeName) - klog.Infof("Kubernetes namespace: %q", m.namespace) // Read initial configuration if err := m.configure(m.configFilePath, m.args.Options); err != nil { @@ -258,14 +256,14 @@ func (m *nfdMaster) Run() error { return fmt.Errorf("error in serving gRPC: %w", err) case <-configWatch.Events: - klog.Infof("reloading configuration") + klog.InfoS("reloading configuration") if err := m.configure(m.configFilePath, m.args.Options); err != nil { return err } // restart NFD API controller if m.nfdController != nil { - klog.Info("stopping the nfd api controller") + klog.InfoS("stopping the nfd api controller") m.nfdController.stop() } if m.args.CrdController { @@ -279,7 +277,7 @@ func (m *nfdMaster) Run() error { m.nfdController.updateAllNodesChan <- struct{}{} } case <-m.stop: - klog.Infof("shutting down nfd-master") + klog.InfoS("shutting down nfd-master") return nil } } @@ -321,7 +319,7 @@ func (m *nfdMaster) runGrpcServer(errChan chan<- error) { } grpc_health_v1.RegisterHealthServer(m.server, health.NewServer()) - klog.Infof("gRPC server serving on port: %d", m.args.Port) + klog.InfoS("gRPC server serving", "port", m.args.Port) // Run gRPC server grpcErr := make(chan error, 1) @@ -333,7 +331,7 @@ func (m *nfdMaster) runGrpcServer(errChan chan<- error) { for { select { case <-certWatch.Events: - klog.Infof("reloading TLS certificates") + klog.InfoS("reloading TLS certificates") if err := tlsConfig.UpdateConfig(m.args.CertFile, m.args.KeyFile, m.args.CaFile); err != nil { errChan <- err } @@ -342,7 +340,7 @@ func (m *nfdMaster) runGrpcServer(errChan chan<- error) { if err != nil { errChan <- fmt.Errorf("gRPC server exited with an error: %v", err) } - klog.Infof("gRPC server stopped") + klog.InfoS("gRPC server stopped") } } } @@ -367,13 +365,13 @@ func (m *nfdMaster) nfdAPIUpdateHandler() { errNodes := make(map[string]struct{}) if updateAll { if err := m.nfdAPIUpdateAllNodes(); err != nil { - klog.Error(err) + klog.ErrorS(err, "failed to update nodes") errUpdateAll = true } } else { for nodeName := range updateNodes { if err := m.nfdAPIUpdateOneNode(nodeName); err != nil { - klog.Error(err) + klog.ErrorS(err, "failed to update node", "nodeName", nodeName) errNodes[nodeName] = struct{}{} } } @@ -416,7 +414,7 @@ func (m *nfdMaster) WaitForReady(timeout time.Duration) bool { // Prune erases all NFD related properties from the node objects of the cluster. func (m *nfdMaster) prune() error { if m.config.NoPublish { - klog.Info("skipping pruning of nodes as noPublish config option is set") + klog.InfoS("skipping pruning of nodes as noPublish config option is set") return nil } @@ -431,7 +429,7 @@ func (m *nfdMaster) prune() error { } for _, node := range nodes.Items { - klog.Infof("pruning node %q...", node.Name) + klog.InfoS("pruning node...", "nodeName", node.Name) // Prune labels and extended resources err := m.updateNodeObject(cli, node.Name, Labels{}, Annotations{}, ExtendedResources{}, []corev1.Taint{}) @@ -492,7 +490,7 @@ func (m *nfdMaster) filterFeatureLabels(labels Labels) (Labels, ExtendedResource name := addNs(name, nfdv1alpha1.FeatureLabelNs) if err := m.filterFeatureLabel(name, value); err != nil { - klog.Errorf("ignoring label %s=%v: %v", name, value, err) + klog.ErrorS(err, "ignoring label", "labelKey", name, "labelValue", value) } else { outLabels[name] = value } @@ -505,7 +503,7 @@ func (m *nfdMaster) filterFeatureLabels(labels Labels) (Labels, ExtendedResource extendedResourceName = addNs(extendedResourceName, nfdv1alpha1.FeatureLabelNs) if value, ok := outLabels[extendedResourceName]; ok { if _, err := strconv.Atoi(value); err != nil { - klog.Errorf("bad label value (%s: %s) encountered for extended resource: %s", extendedResourceName, value, err.Error()) + klog.ErrorS(err, "bad label value encountered for extended resource", "labelKey", extendedResourceName, "labelValue", value) continue // non-numeric label can't be used } @@ -553,7 +551,7 @@ func filterTaints(taints []corev1.Taint) []corev1.Taint { for _, taint := range taints { if err := filterTaint(&taint); err != nil { - klog.Errorf("ignoring taint %q: %w", taint.ToString(), err) + klog.ErrorS(err, "ignoring taint", "taint", taint) } else { outTaints = append(outTaints, taint) } @@ -604,16 +602,17 @@ func isNamespaceDenied(labelNs string, wildcardDeniedNs map[string]struct{}, nor func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.SetLabelsReply, error) { err := authorizeClient(c, m.args.VerifyNodeName, r.NodeName) if err != nil { + klog.ErrorS(err, "gRPC client authorization failed", "nodeName", r.NodeName) return &pb.SetLabelsReply{}, err } switch { case klog.V(4).Enabled(): - utils.KlogDump(3, "REQUEST", " ", r) + klog.InfoS("gRPC SetLabels request received", "setLabelsRequest", utils.DelayedDumper(r)) case klog.V(1).Enabled(): - klog.Infof("REQUEST Node: %q NFD-version: %q Labels: %s", r.NodeName, r.NfdVersion, r.Labels) + klog.InfoS("gRPC SetLabels request received", "nodeName", r.NodeName, "nfdVersion", r.NfdVersion, "labels", r.Labels) default: - klog.Infof("received labeling request for node %q", r.NodeName) + klog.InfoS("gRPC SetLabels request received", "nodeName", r.NodeName) } if !m.config.NoPublish { cli, err := m.apihelper.GetClient() @@ -633,7 +632,7 @@ func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.Se } func (m *nfdMaster) nfdAPIUpdateAllNodes() error { - klog.Info("will process all nodes in the cluster") + klog.InfoS("will process all nodes in the cluster") cli, err := m.apihelper.GetClient() if err != nil { @@ -682,7 +681,7 @@ func (m *nfdMaster) nfdAPIUpdateOneNode(nodeName string) error { return nil } - klog.V(1).Infof("processing node %q, initiated by NodeFeature API", nodeName) + klog.V(1).InfoS("processing of node initiated by NodeFeature API", "nodeName", nodeName) features := nfdv1alpha1.NewNodeFeatureSpec() @@ -698,7 +697,7 @@ func (m *nfdMaster) nfdAPIUpdateOneNode(nodeName string) error { o.Spec.MergeInto(features) } - utils.KlogDump(4, "Composite NodeFeatureSpec after merge:", " ", features) + klog.V(4).InfoS("merged nodeFeatureSpecs", "newNodeFeatureSpec", utils.DelayedDumper(features)) if objs[0].Namespace == m.namespace && objs[0].Name == nodeName { // This is the one created by nfd-worker @@ -732,7 +731,7 @@ func filterExtendedResources(features *nfdv1alpha1.Features, extendedResources E capacity, err := filterExtendedResource(name, value, features) if err != nil { - klog.Errorf("failed to create extended resources %s=%s: %v", name, value, err) + klog.ErrorS(err, "failed to create extended resources", "extendedResourceName", name, "extendedResourceValue", value) } else { outExtendedResources[name] = capacity } @@ -810,7 +809,7 @@ func (m *nfdMaster) refreshNodeFeatures(cli *kubernetes.Clientset, nodeName stri err := m.updateNodeObject(cli, nodeName, labels, annotations, extendedResources, taints) if err != nil { - klog.Errorf("failed to update node %q: %v", nodeName, err) + klog.ErrorS(err, "failed to update node", "nodeName", nodeName) return err } @@ -847,7 +846,7 @@ func (m *nfdMaster) setTaints(cli *kubernetes.Clientset, taints []corev1.Taint, newTaints, removed := taintutils.DeleteTaint(newNode.Spec.Taints, &taintToRemove) if !removed { - klog.V(1).Infof("taint %q already deleted from node", taintToRemove.ToString()) + klog.V(1).InfoS("taint already deleted from node", "taint", taintToRemove) } taintsUpdated = taintsUpdated || removed newNode.Spec.Taints = newTaints @@ -868,7 +867,7 @@ func (m *nfdMaster) setTaints(cli *kubernetes.Clientset, taints []corev1.Taint, if err != nil { return fmt.Errorf("failed to patch the node %v", node.Name) } - klog.Infof("updated node %q taints", nodeName) + klog.InfoS("updated node taints", "nodeName", nodeName) } // Update node annotation that holds the taints managed by us @@ -889,7 +888,7 @@ func (m *nfdMaster) setTaints(cli *kubernetes.Clientset, taints []corev1.Taint, if err != nil { return fmt.Errorf("error while patching node object: %v", err) } - klog.V(1).Infof("patched node %q annotations for taints", nodeName) + klog.V(1).InfoS("patched node annotations for taints", "nodeName", nodeName) } return nil } @@ -900,22 +899,18 @@ func authorizeClient(c context.Context, checkNodeName bool, nodeName string) err // Check that the node name matches the CN from the TLS cert client, ok := peer.FromContext(c) if !ok { - klog.Errorf("gRPC request error: failed to get peer (client)") return fmt.Errorf("failed to get peer (client)") } tlsAuth, ok := client.AuthInfo.(credentials.TLSInfo) if !ok { - klog.Errorf("gRPC request error: incorrect client credentials from '%v'", client.Addr) return fmt.Errorf("incorrect client credentials") } if len(tlsAuth.State.VerifiedChains) == 0 || len(tlsAuth.State.VerifiedChains[0]) == 0 { - klog.Errorf("gRPC request error: client certificate verification for '%v' failed", client.Addr) return fmt.Errorf("client certificate verification failed") } err := verifyNodeName(tlsAuth.State.VerifiedChains[0][0], nodeName) if err != nil { - klog.Errorf("gRPC request error: authorization for %v failed: %v", client.Addr, err) return err } } @@ -936,7 +931,7 @@ func (m *nfdMaster) processNodeFeatureRule(nodeName string, features *nfdv1alpha }) if err != nil { - klog.Errorf("failed to list NodeFeatureRule resources: %v", err) + klog.ErrorS(err, "failed to list NodeFeatureRule resources") return nil, nil, nil } @@ -944,15 +939,14 @@ func (m *nfdMaster) processNodeFeatureRule(nodeName string, features *nfdv1alpha for _, spec := range ruleSpecs { switch { case klog.V(3).Enabled(): - h := fmt.Sprintf("executing NodeFeatureRule %q on node %q:", spec.Name, nodeName) - utils.KlogDump(3, h, " ", spec.Spec) + klog.InfoS("executing NodeFeatureRule", "nodefeaturerule", klog.KObj(spec), "nodeName", nodeName, "nodeFeatureRuleSpec", utils.DelayedDumper(spec.Spec)) case klog.V(1).Enabled(): - klog.Infof("executing NodeFeatureRule %q on node %q", spec.Name, nodeName) + klog.InfoS("executing NodeFeatureRule", "nodefeaturerule", klog.KObj(spec), "nodeName", nodeName) } for _, rule := range spec.Spec.Rules { ruleOut, err := rule.Execute(features) if err != nil { - klog.Errorf("failed to process Rule %q on node %q: %v", rule.Name, nodeName, err) + klog.ErrorS(err, "failed to process rule", "ruleName", rule.Name, "nodefeaturerule", klog.KObj(spec), "nodeName", nodeName) continue } taints = append(taints, ruleOut.Taints...) @@ -1032,9 +1026,9 @@ func (m *nfdMaster) updateNodeObject(cli *kubernetes.Clientset, nodeName string, } if len(patches) > 0 || len(statusPatches) > 0 { - klog.Infof("node %q updated", nodeName) + klog.InfoS("node updated", "nodeName", nodeName) } else { - klog.V(1).Infof("no updates to node %q", nodeName) + klog.V(1).InfoS("no updates to node", "nodeName", nodeName) } // Set taints @@ -1128,17 +1122,17 @@ func (m *nfdMaster) configure(filepath string, overrides string) error { data, err := os.ReadFile(filepath) if err != nil { if os.IsNotExist(err) { - klog.Infof("config file %q not found, using defaults", filepath) + klog.InfoS("config file not found, using defaults", "path", filepath) } else { - return fmt.Errorf("error reading config file: %s", err) + return fmt.Errorf("error reading config file: %w", err) } } else { err = yaml.Unmarshal(data, c) if err != nil { - return fmt.Errorf("failed to parse config file: %s", err) + return fmt.Errorf("failed to parse config file: %w", err) } - klog.Infof("configuration file %q parsed", filepath) + klog.InfoS("configuration file parsed", "path", filepath) } } @@ -1186,8 +1180,7 @@ func (m *nfdMaster) configure(filepath string, overrides string) error { m.deniedNs.normal["kubernetes.io"] = struct{}{} m.deniedNs.wildcard[".kubernetes.io"] = struct{}{} - utils.KlogDump(1, "effective configuration:", " ", m.config) - klog.Infof("master (re-)configuration successfully completed") + klog.InfoS("configuration successfully updated", "configuration", utils.DelayedDumper(m.config)) return nil } @@ -1251,7 +1244,7 @@ func (m *nfdMaster) startNfdApiController() error { if err != nil { return err } - klog.Info("starting nfd api controller") + klog.InfoS("starting the nfd api controller") m.nfdController, err = newNfdController(kubeconfig, nfdApiControllerOptions{ DisableNodeFeature: !m.args.EnableNodeFeatureApi, ResyncPeriod: m.config.ResyncPeriod.Duration, diff --git a/pkg/nfd-topology-gc/nfd-nrt-gc.go b/pkg/nfd-topology-gc/nfd-nrt-gc.go index 744d141d0..86fbc313a 100644 --- a/pkg/nfd-topology-gc/nfd-nrt-gc.go +++ b/pkg/nfd-topology-gc/nfd-nrt-gc.go @@ -85,27 +85,27 @@ func newTopologyGC(config *restclient.Config, stop chan struct{}, gcPeriod time. func (n *topologyGC) deleteNRT(nodeName string) { if err := n.topoClient.TopologyV1alpha2().NodeResourceTopologies().Delete(context.TODO(), nodeName, metav1.DeleteOptions{}); err != nil { if errors.IsNotFound(err) { - klog.V(2).Infof("NodeResourceTopology for node %s not found, omitting deletion", nodeName) + klog.V(2).InfoS("NodeResourceTopology not found, omitting deletion", "nodeName", nodeName) return } else { - klog.Warningf("failed to delete NodeResourceTopology for node %s: %s", nodeName, err.Error()) + klog.ErrorS(err, "failed to delete NodeResourceTopology object", "nodeName", nodeName) return } } - klog.Infof("NodeResourceTopology for node %s has been deleted", nodeName) + klog.InfoS("NodeResourceTopology object has been deleted", "nodeName", nodeName) } func (n *topologyGC) deleteNodeHandler(object interface{}) { // handle a case when we are starting up and need to clear stale NRT resources obj := object if deletedFinalStateUnknown, ok := object.(cache.DeletedFinalStateUnknown); ok { - klog.V(2).Infof("found stale NodeResourceTopology for node: %s ", object) + klog.V(2).InfoS("found stale NodeResourceTopology object", "object", object) obj = deletedFinalStateUnknown.Obj } node, ok := obj.(*corev1.Node) if !ok { - klog.Errorf("cannot convert %v to v1.Node", object) + klog.InfoS("cannot convert object to v1.Node", "object", object) return } @@ -113,13 +113,13 @@ func (n *topologyGC) deleteNodeHandler(object interface{}) { } func (n *topologyGC) runGC() { - klog.Infof("Running GC") + klog.InfoS("Running GC") objects := n.factory.Core().V1().Nodes().Informer().GetIndexer().List() nodes := sets.NewString() for _, object := range objects { key, err := cache.MetaNamespaceKeyFunc(object) if err != nil { - klog.Warningf("cannot create key for %v: %s", object, err.Error()) + klog.ErrorS(err, "failed to create key", "object", object) continue } nodes.Insert(key) @@ -127,14 +127,14 @@ func (n *topologyGC) runGC() { nrts, err := n.topoClient.TopologyV1alpha2().NodeResourceTopologies().List(context.TODO(), metav1.ListOptions{}) if err != nil { - klog.Warningf("cannot list NRTs %s", err.Error()) + klog.ErrorS(err, "failed to list NodeResourceTopology objects") return } for _, nrt := range nrts.Items { key, err := cache.MetaNamespaceKeyFunc(&nrt) if err != nil { - klog.Warningf("cannot create key for %v: %s", nrt, err.Error()) + klog.ErrorS(err, "failed to create key", "noderesourcetopology", klog.KObj(&nrt)) continue } if !nodes.Has(key) { @@ -151,7 +151,7 @@ func (n *topologyGC) periodicGC(gcPeriod time.Duration) { case <-gcTrigger.C: n.runGC() case <-n.stopChan: - klog.Infof("shutting down periodic Garbage Collector") + klog.InfoS("shutting down periodic Garbage Collector") return } } diff --git a/pkg/nfd-topology-updater/kubeletnotifier/kubeletnotifier.go b/pkg/nfd-topology-updater/kubeletnotifier/kubeletnotifier.go index 3d653b98b..a1b0bffad 100644 --- a/pkg/nfd-topology-updater/kubeletnotifier/kubeletnotifier.go +++ b/pkg/nfd-topology-updater/kubeletnotifier/kubeletnotifier.go @@ -76,13 +76,13 @@ func (n *Notifier) Run() { for { select { case <-timeEvents: - klog.V(5).Infof("timer update received") + klog.V(5).InfoS("timer update received") i := Info{Event: IntervalBased} n.dest <- i case e := <-n.fsEvent: basename := path.Base(e.Name) - klog.V(5).Infof("fsnotify event from file %q: %q received", basename, e.Op) + klog.V(5).InfoS("fsnotify event received", "filename", basename, "op", e.Op) if stateFiles.Has(basename) { i := Info{Event: FSUpdate} n.dest <- i diff --git a/pkg/nfd-topology-updater/nfd-topology-updater.go b/pkg/nfd-topology-updater/nfd-topology-updater.go index 5e9b10825..b810f7d4e 100644 --- a/pkg/nfd-topology-updater/nfd-topology-updater.go +++ b/pkg/nfd-topology-updater/nfd-topology-updater.go @@ -120,8 +120,7 @@ func NewTopologyUpdater(args Args, resourcemonitorArgs resourcemonitor.Args, pol // Run nfdTopologyUpdater. Returns if a fatal error is encountered, or, after // one request if OneShot is set to 'true' in the updater args. func (w *nfdTopologyUpdater) Run() error { - klog.Infof("Node Feature Discovery Topology Updater %s", version.Get()) - klog.Infof("NodeName: '%s'", w.nodeInfo.nodeName) + klog.InfoS("Node Feature Discovery Topology Updater", "version", version.Get(), "nodeName", w.nodeInfo.nodeName) podResClient, err := podres.GetPodResClient(w.resourcemonitorArgs.PodResourceSocketPath) if err != nil { @@ -158,20 +157,18 @@ func (w *nfdTopologyUpdater) Run() error { return fmt.Errorf("failed to obtain node resource information: %w", err) } - klog.V(2).Infof("resAggr is: %v\n", resAggr) - for { select { case info := <-w.eventSource: - klog.V(4).Infof("got %q event. scanning...", info.Event) + klog.V(4).InfoS("event received, scanning...", "event", info.Event) scanResponse, err := resScan.Scan() - utils.KlogDump(1, "podResources are", " ", scanResponse.PodResources) + klog.V(1).InfoS("received updated pod resources", "podResources", utils.DelayedDumper(scanResponse.PodResources)) if err != nil { - klog.Warningf("scan failed: %v", err) + klog.ErrorS(err, "scan failed") continue } zones = resAggr.Aggregate(scanResponse.PodResources) - utils.KlogDump(1, "after aggregating resources identified zones are", " ", zones) + klog.V(1).InfoS("aggregated resources identified", "resourceZones", utils.DelayedDumper(zones)) if !w.args.NoPublish { if err = w.updateNodeResourceTopology(zones, scanResponse); err != nil { return err @@ -183,7 +180,7 @@ func (w *nfdTopologyUpdater) Run() error { } case <-w.stop: - klog.Infof("shutting down nfd-topology-updater") + klog.InfoS("shutting down nfd-topology-updater") return nil } } @@ -234,13 +231,13 @@ func (w *nfdTopologyUpdater) updateNodeResourceTopology(zoneInfo v1alpha2.ZoneLi if err != nil { return fmt.Errorf("failed to update NodeResourceTopology: %w", err) } - utils.KlogDump(4, "CR instance updated resTopo:", " ", nrtUpdated) + klog.V(4).InfoS("NodeResourceTopology object updated", "nodeResourceTopology", utils.DelayedDumper(nrtUpdated)) return nil } func (w *nfdTopologyUpdater) configure() error { if w.configFilePath == "" { - klog.Warningf("file path for nfd-topology-updater conf file is empty") + klog.InfoS("no configuration file specified") return nil } @@ -248,7 +245,7 @@ func (w *nfdTopologyUpdater) configure() error { if err != nil { // config is optional if os.IsNotExist(err) { - klog.Warningf("couldn't find conf file under %v", w.configFilePath) + klog.InfoS("configuration file not found", "path", w.configFilePath) return nil } return err @@ -258,7 +255,7 @@ func (w *nfdTopologyUpdater) configure() error { if err != nil { return fmt.Errorf("failed to parse configuration file %q: %w", w.configFilePath, err) } - klog.Infof("configuration file %q parsed:\n %v", w.configFilePath, w.config) + klog.InfoS("configuration file parsed", "path", w.configFilePath, "config", w.config) return nil } diff --git a/pkg/nfd-worker/nfd-worker.go b/pkg/nfd-worker/nfd-worker.go index 0be8d0dae..5fe07370a 100644 --- a/pkg/nfd-worker/nfd-worker.go +++ b/pkg/nfd-worker/nfd-worker.go @@ -190,15 +190,15 @@ func (w *nfdWorker) runFeatureDiscovery() error { for _, s := range w.featureSources { currentSourceStart := time.Now() if err := s.Discover(); err != nil { - klog.Errorf("feature discovery of %q source failed: %v", s.Name(), err) + klog.ErrorS(err, "feature discovery failed", "source", s.Name()) } - klog.V(3).Infof("discovery duration for %q source: %v", s.Name(), time.Since(currentSourceStart)) + klog.V(3).InfoS("feature discovery completed", "featureSource", s.Name(), "duration", time.Since(currentSourceStart)) } discoveryDuration := time.Since(discoveryStart) - klog.V(2).Infof("feature discovery for %d sources lasted for: %v", len(w.featureSources), discoveryDuration) + klog.V(2).InfoS("feature discovery of all sources completed", "duration", discoveryDuration) if w.config.Core.SleepInterval.Duration > 0 && discoveryDuration > w.config.Core.SleepInterval.Duration/2 { - klog.Warningf("feature discovery sources took over half (%v) of sleep interval (%v)", discoveryDuration, w.config.Core.SleepInterval.Duration) + klog.InfoS("feature discovery sources took over half of sleep interval ", "duration", discoveryDuration, "sleepInterval", w.config.Core.SleepInterval.Duration) } // Get the set of feature labels. @@ -215,9 +215,7 @@ func (w *nfdWorker) runFeatureDiscovery() error { // Run NfdWorker client. Returns if a fatal error is encountered, or, after // one request if OneShot is set to 'true' in the worker args. func (w *nfdWorker) Run() error { - klog.Infof("Node Feature Discovery Worker %s", version.Get()) - klog.Infof("NodeName: '%s'", utils.NodeName()) - klog.Infof("Kubernetes namespace: '%s'", w.kubernetesNamespace) + klog.InfoS("Node Feature Discovery Worker", "version", version.Get(), "nodeName", utils.NodeName(), "namespace", w.kubernetesNamespace) // Create watcher for config file and read initial configuration configWatch, err := utils.CreateFsWatcher(time.Second, w.configFilePath) @@ -260,7 +258,7 @@ func (w *nfdWorker) Run() error { } case <-configWatch.Events: - klog.Infof("reloading configuration") + klog.InfoS("reloading configuration") if err := w.configure(w.configFilePath, w.args.Options); err != nil { return err } @@ -278,11 +276,11 @@ func (w *nfdWorker) Run() error { } case <-w.certWatch.Events: - klog.Infof("TLS certificate update, renewing connection to nfd-master") + klog.InfoS("TLS certificate update, renewing connection to nfd-master") w.grpcDisconnect() case <-w.stop: - klog.Infof("shutting down nfd-worker") + klog.InfoS("shutting down nfd-worker") configWatch.Close() w.certWatch.Close() return nil @@ -340,7 +338,7 @@ func (w *nfdWorker) getGrpcClient() (pb.LabelerClient, error) { } else { dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials())) } - klog.Infof("connecting to nfd-master at %s ...", w.args.Server) + klog.InfoS("connecting to nfd-master", "address", w.args.Server) conn, err := grpc.DialContext(dialCtx, w.args.Server, dialOpts...) if err != nil { return nil, err @@ -355,7 +353,7 @@ func (w *nfdWorker) getGrpcClient() (pb.LabelerClient, error) { // grpcDisconnect closes the gRPC connection to NFD master func (w *nfdWorker) grpcDisconnect() { if w.clientConn != nil { - klog.Infof("closing connection to nfd-master ...") + klog.InfoS("closing connection to nfd-master") w.clientConn.Close() } w.clientConn = nil @@ -363,8 +361,8 @@ func (w *nfdWorker) grpcDisconnect() { } func (c *coreConfig) sanitize() { if c.SleepInterval.Duration > 0 && c.SleepInterval.Duration < time.Second { - klog.Warningf("too short sleep interval specified (%s), forcing to 1s", - c.SleepInterval.Duration.String()) + klog.InfoS("too short sleep interval specified, forcing to 1s", + "sleepInterval", c.SleepInterval.Duration.String()) c.SleepInterval = utils.DurationVal{Duration: time.Second} } } @@ -384,7 +382,7 @@ func (w *nfdWorker) configureCore(c coreConfig) error { } for k := range c.Klog { if _, ok := w.args.Klog[k]; !ok { - klog.Warningf("unknown logger option in config: %q", k) + klog.InfoS("unknown logger option in config", "optionName", k) } } @@ -411,7 +409,7 @@ func (w *nfdWorker) configureCore(c coreConfig) error { delete(featureSources, strippedName) } } else { - klog.Warningf("skipping unknown feature source %q specified in core.featureSources", name) + klog.InfoS("skipping unknown source specified in core.featureSources", "featureSource", name) } } } @@ -446,7 +444,7 @@ func (w *nfdWorker) configureCore(c coreConfig) error { delete(labelSources, strippedName) } } else { - klog.Warningf("skipping unknown source %q specified in core.sources (or -sources)", name) + klog.InfoS("skipping unknown source specified in core.labelSources (or -label-sources)", "labelSource", name) } } } @@ -464,18 +462,18 @@ func (w *nfdWorker) configureCore(c coreConfig) error { return w.labelSources[i].Name() < w.labelSources[j].Name() }) - if klog.V(1).Enabled() { + if klogV := klog.V(1); klogV.Enabled() { n := make([]string, len(w.featureSources)) for i, s := range w.featureSources { n[i] = s.Name() } - klog.Infof("enabled feature sources: %s", strings.Join(n, ", ")) + klogV.InfoS("enabled feature sources", "featureSources", n) n = make([]string, len(w.labelSources)) for i, s := range w.labelSources { n[i] = s.Name() } - klog.Infof("enabled label sources: %s", strings.Join(n, ", ")) + klogV.InfoS("enabled label sources", "labelSources", n) } return nil @@ -496,7 +494,7 @@ func (w *nfdWorker) configure(filepath string, overrides string) error { data, err := os.ReadFile(filepath) if err != nil { if os.IsNotExist(err) { - klog.Infof("config file %q not found, using defaults", filepath) + klog.InfoS("config file not found, using defaults", "path", filepath) } else { return fmt.Errorf("error reading config file: %s", err) } @@ -507,11 +505,11 @@ func (w *nfdWorker) configure(filepath string, overrides string) error { } if c.Core.Sources != nil { - klog.Warningf("found deprecated 'core.sources' config file option, please use 'core.labelSources' instead") + klog.InfoS("usage of deprecated 'core.sources' config file option, please use 'core.labelSources' instead") c.Core.LabelSources = *c.Core.Sources } - klog.Infof("configuration file %q parsed", filepath) + klog.InfoS("configuration file parsed", "path", filepath) } } @@ -543,8 +541,7 @@ func (w *nfdWorker) configure(filepath string, overrides string) error { s.SetConfig(c.Sources[s.Name()]) } - klog.Infof("worker (re-)configuration successfully completed") - utils.KlogDump(1, "effective configuration:", " ", w.config) + klog.InfoS("configuration successfully updated", "configuration", w.config) return nil } @@ -554,11 +551,11 @@ func createFeatureLabels(sources []source.LabelSource, labelWhiteList regexp.Reg labels = Labels{} // Get labels from all enabled label sources - klog.Info("starting feature discovery...") + klog.InfoS("starting feature discovery...") for _, source := range sources { labelsFromSource, err := getFeatureLabels(source, labelWhiteList) if err != nil { - klog.Errorf("discovery failed for source %q: %v", source.Name(), err) + klog.ErrorS(err, "discovery failed", "source", source.Name()) continue } @@ -566,8 +563,11 @@ func createFeatureLabels(sources []source.LabelSource, labelWhiteList regexp.Reg labels[name] = value } } - klog.Info("feature discovery completed") - utils.KlogDump(1, "labels discovered by feature sources:", " ", labels) + if klogV := klog.V(1); klogV.Enabled() { + klogV.InfoS("feature discovery completed", "labels", utils.DelayedDumper(labels)) + } else { + klog.InfoS("feature discovery completed") + } return labels } @@ -607,7 +607,7 @@ func getFeatureLabels(source source.LabelSource, labelWhiteList regexp.Regexp) ( // Validate label name. errs := validation.IsQualifiedName(nameForValidation) if len(errs) > 0 { - klog.Warningf("ignoring invalid feature name '%s': %s", label, errs) + klog.InfoS("ignoring label with invalid name", "lableKey", label, "errors", errs) continue } @@ -615,13 +615,13 @@ func getFeatureLabels(source source.LabelSource, labelWhiteList regexp.Regexp) ( // Validate label value errs = validation.IsValidLabelValue(value) if len(errs) > 0 { - klog.Warningf("ignoring invalid feature value %s=%s: %s", label, value, errs) + klog.InfoS("ignoring label with invalide value", "labelKey", label, "labelValue", value, "errors", errs) continue } // Skip if label doesn't match labelWhiteList if !labelWhiteList.MatchString(nameForWhiteListing) { - klog.Infof("%q does not match the whitelist (%s) and will not be published.", nameForWhiteListing, labelWhiteList.String()) + klog.InfoS("label does not match the whitelist and will not be published.", "labelKey", nameForWhiteListing, "regexp", labelWhiteList.String()) continue } @@ -652,7 +652,7 @@ func (w *nfdWorker) advertiseFeatureLabels(labels Labels) error { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - klog.Infof("sending labeling request to nfd-master") + klog.InfoS("sending labeling request to nfd-master") labelReq := pb.SetLabelsRequest{Labels: labels, Features: source.GetAllFeatures(), @@ -666,7 +666,7 @@ func (w *nfdWorker) advertiseFeatureLabels(labels Labels) error { _, err = cli.SetLabels(ctx, &labelReq) if err != nil { - klog.Errorf("failed to set node labels: %v", err) + klog.ErrorS(err, "failed to label node") return err } @@ -687,7 +687,7 @@ func (m *nfdWorker) updateNodeFeatureObject(labels Labels) error { // TODO: we could implement some simple caching of the object, only get it // every 10 minutes or so because nobody else should really be modifying it if nfr, err := cli.NfdV1alpha1().NodeFeatures(namespace).Get(context.TODO(), nodename, metav1.GetOptions{}); errors.IsNotFound(err) { - klog.Infof("creating NodeFeature object %q", nodename) + klog.InfoS("creating NodeFeature object", "nodefeature", klog.KObj(nfr)) nfr = &nfdv1alpha1.NodeFeature{ ObjectMeta: metav1.ObjectMeta{ Name: nodename, @@ -705,11 +705,10 @@ func (m *nfdWorker) updateNodeFeatureObject(labels Labels) error { return fmt.Errorf("failed to create NodeFeature object %q: %w", nfr.Name, err) } - utils.KlogDump(4, "NodeFeature object created:", " ", nfrCreated) + klog.V(4).InfoS("NodeFeature object created", "nodeFeature", utils.DelayedDumper(nfrCreated)) } else if err != nil { return fmt.Errorf("failed to get NodeFeature object: %w", err) } else { - nfrUpdated := nfr.DeepCopy() nfrUpdated.Annotations = map[string]string{nfdv1alpha1.WorkerVersionAnnotation: version.Get()} nfrUpdated.Labels = map[string]string{nfdv1alpha1.NodeFeatureObjNodeNameLabel: nodename} @@ -719,14 +718,14 @@ func (m *nfdWorker) updateNodeFeatureObject(labels Labels) error { } if !apiequality.Semantic.DeepEqual(nfr, nfrUpdated) { - klog.Infof("updating NodeFeature object %q", nodename) + klog.InfoS("updating NodeFeature object", "nodefeature", klog.KObj(nfr)) nfrUpdated, err = cli.NfdV1alpha1().NodeFeatures(namespace).Update(context.TODO(), nfrUpdated, metav1.UpdateOptions{}) if err != nil { return fmt.Errorf("failed to update NodeFeature object %q: %w", nfr.Name, err) } - utils.KlogDump(4, "NodeFeature object updated:", " ", nfrUpdated) + klog.V(4).InfoS("NodeFeature object updated", "nodeFeature", utils.DelayedDumper(nfrUpdated)) } else { - klog.V(1).Info("no changes in NodeFeature object, not updating") + klog.V(1).InfoS("no changes in NodeFeature object, not updating", "nodefeature", klog.KObj(nfr)) } } return nil diff --git a/pkg/resourcemonitor/excludelist.go b/pkg/resourcemonitor/excludelist.go index 590d0bb8a..8411594a4 100644 --- a/pkg/resourcemonitor/excludelist.go +++ b/pkg/resourcemonitor/excludelist.go @@ -27,7 +27,7 @@ func NewExcludeResourceList(resMap map[string][]string, nodeName string) Exclude func (rl *ExcludeResourceList) IsExcluded(resource corev1.ResourceName) bool { if rl.excludeList.Has(string(resource)) { - klog.V(5).InfoS("resource excluded", "resource", resource) + klog.V(5).InfoS("resource excluded", "resourceName", resource) return true } return false diff --git a/pkg/resourcemonitor/noderesourcesaggregator.go b/pkg/resourcemonitor/noderesourcesaggregator.go index be3865a03..0b92ddf75 100644 --- a/pkg/resourcemonitor/noderesourcesaggregator.go +++ b/pkg/resourcemonitor/noderesourcesaggregator.go @@ -77,9 +77,9 @@ func NewResourcesAggregator(podResourceClient podresourcesapi.PodResourcesLister resp, err := podResourceClient.GetAllocatableResources(ctx, &podresourcesapi.AllocatableResourcesRequest{}) if err != nil { if strings.Contains(err.Error(), "API GetAllocatableResources disabled") { - klog.Error("Kubelet's pod resources 'GetAllocatableResources' functionality is disabled. " + - "Ensure feature flag 'KubeletPodResourcesGetAllocatable' is set to true. " + - "You can find more about the feature gates from the following URL - " + + klog.ErrorS(err, "Kubelet's pod resources 'GetAllocatableResources' functionality is disabled. "+ + "Ensure feature flag 'KubeletPodResourcesGetAllocatable' is set to true. "+ + "You can find more about the feature gates from the following URL - "+ "https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/") } @@ -178,7 +178,7 @@ func (noderesourceData *nodeResources) Aggregate(podResData []PodResources) topo costs, err := makeCostsPerNumaNode(noderesourceData.topo.Nodes, nodeID) if err != nil { - klog.Infof("cannot find costs for NUMA node %d: %v", nodeID, err) + klog.ErrorS(err, "failed to calculate costs for NUMA node", "nodeID", nodeID) } else { zone.Costs = costs } @@ -212,7 +212,7 @@ func getContainerDevicesFromAllocatableResources(availRes *podresourcesapi.Alloc for _, cpuID := range availRes.GetCpuIds() { nodeID, ok := cpuIDToNodeIDMap[int(cpuID)] if !ok { - klog.Infof("cannot find the NUMA node for CPU %d", cpuID) + klog.InfoS("failed to find the NUMA node for CPU", "cpuID", cpuID) continue } @@ -243,16 +243,16 @@ func (noderesourceData *nodeResources) updateAvailable(numaData map[int]map[core resName := string(ri.Name) resMap, ok := noderesourceData.resourceID2NUMAID[resName] if !ok { - klog.Infof("unknown resource %q", ri.Name) + klog.InfoS("unknown resource", "resourceName", ri.Name) continue } nodeID, ok := resMap[resID] if !ok { - klog.Infof("unknown resource %q: %q", resName, resID) + klog.InfoS("unknown resource", "resourceName", resName, "resourceID", resID) continue } if _, ok := numaData[nodeID]; !ok { - klog.Infof("unknown node id: %q", nodeID) + klog.InfoS("unknown NUMA node id", "numaID", nodeID) continue } @@ -409,18 +409,18 @@ func getCPUs(devices []*podresourcesapi.ContainerDevices) map[string]int { // This function assumes the available resources are initialized to be equal to the capacity. func (noderesourceData *nodeResources) updateMemoryAvailable(numaData map[int]map[corev1.ResourceName]*resourceData, ri ResourceInfo) { if len(ri.NumaNodeIds) == 0 { - klog.Warningf("no NUMA nodes information is available for device %q", ri.Name) + klog.InfoS("no NUMA nodes information is available", "resourceName", ri.Name) return } if len(ri.Data) != 1 { - klog.Warningf("no size information is available for the device %q", ri.Name) + klog.InfoS("no size information is available", "resourceName", ri.Name) return } requestedSize, err := strconv.ParseInt(ri.Data[0], 10, 64) if err != nil { - klog.Errorf("failed to parse resource requested size: %v", err) + klog.ErrorS(err, "failed to parse resource requested size") return } @@ -430,17 +430,17 @@ func (noderesourceData *nodeResources) updateMemoryAvailable(numaData map[int]ma } if _, ok := numaData[numaNodeID]; !ok { - klog.Warningf("failed to find NUMA node ID %d under the node topology", numaNodeID) + klog.InfoS("failed to find NUMA node ID under the node topology", "numaID", numaNodeID) continue } if _, ok := numaData[numaNodeID][ri.Name]; !ok { - klog.Warningf("failed to find resource %q under the node topology", ri.Name) + klog.InfoS("failed to find resource under the node topology", "resourceName", ri.Name) return } if numaData[numaNodeID][ri.Name].available == 0 { - klog.V(4).Infof("no available memory on the node %d for the resource %q", numaNodeID, ri.Name) + klog.V(4).InfoS("no available memory", "numaID", numaNodeID, "resourceName", ri.Name) continue } @@ -461,7 +461,7 @@ func (noderesourceData *nodeResources) updateMemoryAvailable(numaData map[int]ma } if requestedSize > 0 { - klog.Warningf("the resource %q requested size was not fully satisfied by NUMA nodes", ri.Name) + klog.InfoS("requested size was not fully satisfied by NUMA nodes", "resourceName", ri.Name) } } diff --git a/pkg/resourcemonitor/podresourcesscanner.go b/pkg/resourcemonitor/podresourcesscanner.go index 00775d9ba..5ff086463 100644 --- a/pkg/resourcemonitor/podresourcesscanner.go +++ b/pkg/resourcemonitor/podresourcesscanner.go @@ -48,9 +48,9 @@ func NewPodResourcesScanner(namespace string, podResourceClient podresourcesapi. podFingerprint: podFingerprint, } if resourcemonitorInstance.namespace != "*" { - klog.Infof("watching namespace %q", resourcemonitorInstance.namespace) + klog.InfoS("watching one namespace", "namespace", resourcemonitorInstance.namespace) } else { - klog.Infof("watching all namespaces") + klog.InfoS("watching all namespaces") } return resourcemonitorInstance, nil @@ -67,7 +67,6 @@ func (resMon *PodResourcesScanner) isWatchable(podNamespace string, podName stri return false, false, err } - klog.Infof("podresource: %s", podName) isIntegralGuaranteed := hasExclusiveCPUs(pod) if resMon.namespace == "*" && (isIntegralGuaranteed || hasDevice) { @@ -137,9 +136,9 @@ func (resMon *PodResourcesScanner) Scan() (ScanResponse, error) { var status podfingerprint.Status podFingerprintSign, err := computePodFingerprint(respPodResources, &status) if err != nil { - klog.Errorf("podFingerprint: Unable to compute fingerprint %v", err) + klog.ErrorS(err, "failed to calculate fingerprint") } else { - klog.Info("podFingerprint: " + status.Repr()) + klog.InfoS("podFingerprint calculated", "status", status.Repr()) retVal.Attributes = append(retVal.Attributes, v1alpha2.AttributeInfo{ Name: podfingerprint.Attribute, @@ -150,7 +149,7 @@ func (resMon *PodResourcesScanner) Scan() (ScanResponse, error) { var podResData []PodResources for _, podResource := range respPodResources { - klog.Infof("podresource iter: %s", podResource.GetName()) + klog.InfoS("scanning pod", "podName", podResource.GetName()) hasDevice := hasDevice(podResource) isWatchable, isIntegralGuaranteed, err := resMon.isWatchable(podResource.GetNamespace(), podResource.GetName(), hasDevice) if err != nil { @@ -233,7 +232,7 @@ func hasDevice(podResource *podresourcesapi.PodResources) bool { return true } } - klog.Infof("pod:%s doesn't have devices", podResource.GetName()) + klog.InfoS("pod doesn't have devices", "podName", podResource.GetName()) return false } diff --git a/pkg/utils/dump.go b/pkg/utils/dump.go index 68ee22df6..5b713ad61 100644 --- a/pkg/utils/dump.go +++ b/pkg/utils/dump.go @@ -18,24 +18,24 @@ package utils import ( "fmt" - "strings" - "k8s.io/klog/v2" "sigs.k8s.io/yaml" ) -func KlogDump(v klog.Level, heading, prefix string, obj interface{}) { - if klog.V(v).Enabled() { - if heading != "" { - klog.InfoDepth(1, heading) - } +type dumper struct { + obj interface{} +} - d := strings.Split(Dump(obj), "\n") - // Print all but the last empty line - for i := 0; i < len(d)-1; i++ { - klog.InfoDepth(1, prefix+d[i]) - } - } +// String implements the fmt.Stringer interface +func (d *dumper) String() string { + return Dump(d.obj) +} + +// DelayedDumper delays the dumping of an object. Useful in logging to delay +// the processing (JSON marshalling) until (or if) the object is actually +// evaluated. +func DelayedDumper(obj interface{}) fmt.Stringer { + return &dumper{obj: obj} } // Dump dumps an object into YAML textual format diff --git a/pkg/utils/fswatcher.go b/pkg/utils/fswatcher.go index 164381934..82bf58b06 100644 --- a/pkg/utils/fswatcher.go +++ b/pkg/utils/fswatcher.go @@ -94,9 +94,9 @@ func (w *FsWatcher) add(names ...string) error { for p := name; ; p = filepath.Dir(p) { if _, ok := w.paths[p]; !ok { if err := w.Add(p); err != nil { - klog.V(1).Infof("failed to add fsnotify watch for %q: %v", p, err) + klog.V(1).ErrorS(err, "failed to add fsnotify watch", "path", p) } else { - klog.V(1).Infof("added fsnotify watch %q", p) + klog.V(1).InfoS("added fsnotify watch", "path", p) added = true } @@ -124,14 +124,14 @@ func (w *FsWatcher) watch() { case e, ok := <-w.Watcher.Events: // Watcher has been closed if !ok { - klog.Infof("watcher closed") + klog.InfoS("watcher closed") return } // If any of our paths change name := filepath.Clean(e.Name) if _, ok := w.paths[filepath.Clean(name)]; ok { - klog.V(2).Infof("fsnotify %s event in %q detected", e, name) + klog.V(2).InfoS("fsnotify event detected", "path", name, "fsNotifyEvent", e) // Rate limiter. In certain filesystem operations we get // numerous events in quick succession @@ -141,15 +141,15 @@ func (w *FsWatcher) watch() { case e, ok := <-w.Watcher.Errors: // Watcher has been closed if !ok { - klog.Infof("watcher closed") + klog.InfoS("watcher closed") return } - klog.Warningf("fswatcher error event detected: %v", e) + klog.ErrorS(e, "fswatcher error event detected") case <-ratelimiter: // Blindly remove existing watch and add a new one if err := w.reset(w.names...); err != nil { - klog.Errorf("%v, re-trying in 60 seconds...", err) + klog.ErrorS(err, "re-trying in 60 seconds") ratelimiter = time.After(60 * time.Second) } diff --git a/pkg/utils/memory_resources.go b/pkg/utils/memory_resources.go index fa2eea0ca..c86ecb8eb 100644 --- a/pkg/utils/memory_resources.go +++ b/pkg/utils/memory_resources.go @@ -91,7 +91,7 @@ func getHugepagesBytes(path string) (MemoryResourceInfo, error) { for _, entry := range entries { split := strings.SplitN(entry.Name(), "-", 2) if len(split) != 2 || split[0] != "hugepages" { - klog.Warningf("malformed hugepages entry %q", entry.Name()) + klog.InfoS("malformed hugepages entry", "hugepagesEntry", entry.Name()) continue } diff --git a/source/cpu/coprocessor_ppc64le.go b/source/cpu/coprocessor_ppc64le.go index 0d1e859f9..fd01484fc 100644 --- a/source/cpu/coprocessor_ppc64le.go +++ b/source/cpu/coprocessor_ppc64le.go @@ -34,7 +34,7 @@ func discoverCoprocessor() map[string]string { _, err := os.Stat(nxGzipPath) if err != nil { - klog.V(5).Infof("Failed to detect nx_gzip for Nest Accelerator: %v", err) + klog.V(5).ErrorS(err, "Failed to detect nx_gzip for Nest Accelerator") } else { features["nx_gzip"] = strconv.FormatBool(true) } diff --git a/source/cpu/cpu.go b/source/cpu/cpu.go index 10dab2002..ae47bb266 100644 --- a/source/cpu/cpu.go +++ b/source/cpu/cpu.go @@ -17,6 +17,7 @@ limitations under the License. package cpu import ( + "fmt" "os" "strconv" @@ -130,7 +131,7 @@ func (s *cpuSource) SetConfig(conf source.Config) { s.config = v s.initCpuidFilter() default: - klog.Fatalf("invalid config type: %T", conf) + panic(fmt.Sprintf("invalid config type: %T", conf)) } } @@ -228,7 +229,7 @@ func (s *cpuSource) Discover() error { // Detect cstate configuration cstate, err := detectCstate() if err != nil { - klog.Errorf("failed to detect cstate: %v", err) + klog.ErrorS(err, "failed to detect cstate") } else { s.features.Attributes[CstateFeature] = nfdv1alpha1.NewAttributeFeatures(cstate) } @@ -236,7 +237,7 @@ func (s *cpuSource) Discover() error { // Detect pstate features pstate, err := detectPstate() if err != nil { - klog.Error(err) + klog.ErrorS(err, "failed to detect pstate") } s.features.Attributes[PstateFeature] = nfdv1alpha1.NewAttributeFeatures(pstate) @@ -269,7 +270,7 @@ func (s *cpuSource) Discover() error { // Detect Coprocessor features s.features.Attributes[CoprocessorFeature] = nfdv1alpha1.NewAttributeFeatures(discoverCoprocessor()) - utils.KlogDump(3, "discovered cpu features:", " ", s.features) + klog.V(3).InfoS("discovered features", "featureSource", s.Name(), "features", utils.DelayedDumper(s.features)) return nil } @@ -295,7 +296,7 @@ func discoverTopology() map[string]string { features := make(map[string]string) if ht, err := haveThreadSiblings(); err != nil { - klog.Errorf("failed to detect hyper-threading: %v", err) + klog.ErrorS(err, "failed to detect hyper-threading") } else { features["hardware_multithreading"] = strconv.FormatBool(ht) } diff --git a/source/cpu/cstate_amd64.go b/source/cpu/cstate_amd64.go index b587918ab..999914c82 100644 --- a/source/cpu/cstate_amd64.go +++ b/source/cpu/cstate_amd64.go @@ -39,7 +39,7 @@ func detectCstate() (map[string]string, error) { } cpuidleDir := filepath.Join(sysfsBase, "cpuidle") if _, err := os.Stat(cpuidleDir); os.IsNotExist(err) { - klog.V(1).Info("cpuidle disabled in the kernel") + klog.V(1).InfoS("cpuidle disabled in the kernel") return cstate, nil } @@ -51,7 +51,7 @@ func detectCstate() (map[string]string, error) { if d := strings.TrimSpace(string(driver)); d != "intel_idle" { // Currently only checking intel_idle driver for cstates - klog.V(1).Infof("intel_idle driver is not in use (%s is active)", d) + klog.V(1).InfoS("intel_idle driver is not in use", "currentIdleDriver", d) return cstate, nil } diff --git a/source/cpu/power_amd64.go b/source/cpu/power_amd64.go index 624edfd1d..931af5262 100644 --- a/source/cpu/power_amd64.go +++ b/source/cpu/power_amd64.go @@ -37,7 +37,7 @@ func discoverSST() map[string]string { features := make(map[string]string) if bf, err := discoverSSTBF(); err != nil { - klog.Errorf("failed to detect SST-BF: %v", err) + klog.ErrorS(err, "failed to detect SST-BF") } else if bf { features["bf.enabled"] = strconv.FormatBool(bf) } diff --git a/source/cpu/pstate_amd64.go b/source/cpu/pstate_amd64.go index b0e412856..fab4afe48 100644 --- a/source/cpu/pstate_amd64.go +++ b/source/cpu/pstate_amd64.go @@ -17,7 +17,6 @@ limitations under the License. package cpu import ( - "fmt" "os" "path/filepath" "strings" @@ -32,23 +31,23 @@ func detectPstate() (map[string]string, error) { // Check that sysfs is available sysfsBase := hostpath.SysfsDir.Path("devices/system/cpu") if _, err := os.Stat(sysfsBase); err != nil { - return nil, fmt.Errorf("unable to detect pstate status: %w", err) + return nil, err } pstateDir := filepath.Join(sysfsBase, "intel_pstate") if _, err := os.Stat(pstateDir); os.IsNotExist(err) { - klog.V(1).Info("intel pstate driver not enabled") + klog.V(1).InfoS("intel pstate driver not enabled") return nil, nil } // Get global pstate status data, err := os.ReadFile(filepath.Join(pstateDir, "status")) if err != nil { - return nil, fmt.Errorf("could not read pstate status: %w", err) + return nil, err } status := strings.TrimSpace(string(data)) if status == "off" { // No need to check other pstate features - klog.Infof("intel_pstate driver is not in use") + klog.InfoS("intel_pstate driver is not in use") return nil, nil } features := map[string]string{"status": status} @@ -56,7 +55,7 @@ func detectPstate() (map[string]string, error) { // Check turbo boost bytes, err := os.ReadFile(filepath.Join(pstateDir, "no_turbo")) if err != nil { - klog.Errorf("can't detect whether turbo boost is enabled: %s", err.Error()) + klog.ErrorS(err, "can't detect whether turbo boost is enabled") } else { features["turbo"] = "false" if bytes[0] == byte('0') { @@ -73,7 +72,7 @@ func detectPstate() (map[string]string, error) { cpufreqDir := filepath.Join(sysfsBase, "cpufreq") policies, err := os.ReadDir(cpufreqDir) if err != nil { - klog.Errorf("failed to read cpufreq directory: %s", err.Error()) + klog.ErrorS(err, "failed to read cpufreq directory") return features, nil } @@ -82,23 +81,23 @@ func detectPstate() (map[string]string, error) { // Ensure at least one cpu is using this policy cpus, err := os.ReadFile(filepath.Join(cpufreqDir, policy.Name(), "affected_cpus")) if err != nil { - klog.Errorf("could not read cpufreq policy %s affected_cpus", policy.Name()) + klog.InfoS("could not read cpufreq affected_cpus", "cpufreqPolicyName", policy.Name()) continue } if strings.TrimSpace(string(cpus)) == "" { - klog.Infof("policy %s has no associated cpus", policy.Name()) + klog.InfoS("cpufreq policy has no associated cpus", "cpufreqPolicyName", policy.Name()) continue } data, err := os.ReadFile(filepath.Join(cpufreqDir, policy.Name(), "scaling_governor")) if err != nil { - klog.Errorf("could not read cpufreq policy %s scaling_governor", policy.Name()) + klog.InfoS("could not read cpufreq scaling_governor", "cpufreqPolicyName", policy.Name()) continue } policy_scaling := strings.TrimSpace(string(data)) // Check that all of the policies have the same scaling governor, if not don't set feature if scaling != "" && scaling != policy_scaling { - klog.Infof("scaling_governor for policy %s doesn't match prior policy", policy.Name()) + klog.InfoS("scaling_governor for cpufreq policy doesn't match prior policy", "cpufreqPolicyName", policy.Name()) scaling = "" break } diff --git a/source/cpu/rdt_amd64.go b/source/cpu/rdt_amd64.go index 30143a37c..57c34017c 100644 --- a/source/cpu/rdt_amd64.go +++ b/source/cpu/rdt_amd64.go @@ -112,19 +112,19 @@ func getNumClosID(level string) int64 { closidFile := filepath.Join(resctrlRootDir, "info", level, "num_closids") if _, err := os.Stat(closidFile); err != nil { - klog.V(4).ErrorS(err, "failed to stat file", "fileName", closidFile) + klog.V(4).ErrorS(err, "failed to stat file", "path", closidFile) return -1 } closidsBytes, err := os.ReadFile(filepath.Join(resctrlRootDir, "info", level, "num_closids")) if err != nil { - klog.V(4).ErrorS(err, "failed to read file", "fileName", closidFile) + klog.V(4).ErrorS(err, "failed to read file", "path", closidFile) return -1 } numClosIDs, err := strconv.ParseInt(string(bytes.TrimSpace(closidsBytes)), 10, 64) if err != nil { - klog.V(4).ErrorS(err, "failed to ParseInt", "num_closids", string(bytes.TrimSpace(closidsBytes))) + klog.V(4).ErrorS(err, "failed to parse num_closids", "value", string(bytes.TrimSpace(closidsBytes))) return -1 } diff --git a/source/custom/custom.go b/source/custom/custom.go index c9f3c69c8..90ccdea4e 100644 --- a/source/custom/custom.go +++ b/source/custom/custom.go @@ -97,7 +97,7 @@ func (s *customSource) SetConfig(conf source.Config) { case *config: s.config = v default: - klog.Fatalf("invalid config type: %T", conf) + panic(fmt.Sprintf("invalid config type: %T", conf)) } } @@ -112,12 +112,12 @@ func (s *customSource) GetLabels() (source.FeatureLabels, error) { labels := source.FeatureLabels{} allFeatureConfig := append(getStaticFeatureConfig(), *s.config...) allFeatureConfig = append(allFeatureConfig, getDirectoryFeatureConfig()...) - utils.KlogDump(2, "custom features configuration:", " ", allFeatureConfig) + klog.V(2).InfoS("resolving custom features", "configuration", utils.DelayedDumper(allFeatureConfig)) // Iterate over features for _, rule := range allFeatureConfig { ruleOut, err := rule.execute(features) if err != nil { - klog.Error(err) + klog.ErrorS(err, "failed to execute rule") continue } @@ -128,6 +128,7 @@ func (s *customSource) GetLabels() (source.FeatureLabels, error) { features.InsertAttributeFeatures(nfdv1alpha1.RuleBackrefDomain, nfdv1alpha1.RuleBackrefFeature, ruleOut.Labels) features.InsertAttributeFeatures(nfdv1alpha1.RuleBackrefDomain, nfdv1alpha1.RuleBackrefFeature, ruleOut.Vars) } + return labels, nil } diff --git a/source/custom/directory_features.go b/source/custom/directory_features.go index 626dc4266..951c0e791 100644 --- a/source/custom/directory_features.go +++ b/source/custom/directory_features.go @@ -32,20 +32,20 @@ const Directory = "/etc/kubernetes/node-feature-discovery/custom.d" // host directory and its 1st level subdirectories, which can be populated e.g. by ConfigMaps func getDirectoryFeatureConfig() []CustomRule { features := readDir(Directory, true) - klog.V(1).Infof("all configmap based custom feature specs: %+v", features) + klog.V(3).InfoS("all custom feature specs from config dir", "featureSpecs", features) return features } func readDir(dirName string, recursive bool) []CustomRule { features := make([]CustomRule, 0) - klog.V(1).Infof("getting files in %s", dirName) + klog.V(4).InfoS("reading directory", "path", dirName) files, err := os.ReadDir(dirName) if err != nil { if os.IsNotExist(err) { - klog.V(1).Infof("custom config directory %q does not exist", dirName) + klog.V(4).InfoS("directory does not exist", "path", dirName) } else { - klog.Errorf("unable to access custom config directory %q, %v", dirName, err) + klog.ErrorS(err, "unable to access directory", "path", dirName) } return features } @@ -55,30 +55,29 @@ func readDir(dirName string, recursive bool) []CustomRule { if file.IsDir() { if recursive { - klog.V(1).Infof("processing dir %q", fileName) + klog.V(4).InfoS("processing directory", "path", fileName) features = append(features, readDir(fileName, false)...) } else { - klog.V(2).Infof("skipping dir %q", fileName) + klog.V(4).InfoS("skipping directory", "path", fileName) } continue } if strings.HasPrefix(file.Name(), ".") { - klog.V(2).Infof("skipping hidden file %q", fileName) + klog.V(4).InfoS("skipping hidden file", "path", fileName) continue } - klog.V(2).Infof("processing file %q", fileName) + klog.V(4).InfoS("processing file", "path", fileName) bytes, err := os.ReadFile(fileName) if err != nil { - klog.Errorf("could not read custom config file %q, %v", fileName, err) + klog.ErrorS(err, "could not read file", "path", fileName) continue } - klog.V(2).Infof("custom config rules raw: %s", string(bytes)) config := &[]CustomRule{} err = yaml.UnmarshalStrict(bytes, config) if err != nil { - klog.Errorf("could not parse custom config file %q, %v", fileName, err) + klog.ErrorS(err, "could not parse file", "path", fileName) continue } diff --git a/source/fake/fake.go b/source/fake/fake.go index d377ac6f6..92f205c0e 100644 --- a/source/fake/fake.go +++ b/source/fake/fake.go @@ -19,6 +19,7 @@ package fake import ( "fmt" + "k8s.io/klog/v2" nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1" "sigs.k8s.io/node-feature-discovery/pkg/utils" "sigs.k8s.io/node-feature-discovery/source" @@ -127,7 +128,7 @@ func (s *fakeSource) Discover() error { } s.features.Instances[InstanceFeature] = nfdv1alpha1.NewInstanceFeatures(instances) - utils.KlogDump(3, "discovered fake features:", " ", s.features) + klog.V(3).InfoS("discovered features", "featureSource", s.Name(), "features", utils.DelayedDumper(s.features)) return nil } diff --git a/source/kernel/kernel.go b/source/kernel/kernel.go index c4d6de553..82006fc71 100644 --- a/source/kernel/kernel.go +++ b/source/kernel/kernel.go @@ -17,6 +17,7 @@ limitations under the License. package kernel import ( + "fmt" "strconv" "k8s.io/klog/v2" @@ -87,7 +88,7 @@ func (s *kernelSource) SetConfig(conf source.Config) { case *Config: s.config = v default: - klog.Fatalf("invalid config type: %T", conf) + panic(fmt.Sprintf("invalid config type: %T", conf)) } } @@ -122,7 +123,7 @@ func (s *kernelSource) Discover() error { // Read kernel version if version, err := parseVersion(); err != nil { - klog.Errorf("failed to get kernel version: %s", err) + klog.ErrorS(err, "failed to get kernel version") } else { s.features.Attributes[VersionFeature] = nfdv1alpha1.NewAttributeFeatures(version) } @@ -130,7 +131,7 @@ func (s *kernelSource) Discover() error { // Read kconfig if realKconfig, legacyKconfig, err := parseKconfig(s.config.KconfigFile); err != nil { s.legacyKconfig = nil - klog.Errorf("failed to read kconfig: %s", err) + klog.ErrorS(err, "failed to read kconfig") } else { s.features.Attributes[ConfigFeature] = nfdv1alpha1.NewAttributeFeatures(realKconfig) s.legacyKconfig = legacyKconfig @@ -138,27 +139,27 @@ func (s *kernelSource) Discover() error { var enabledModules []string if kmods, err := getLoadedModules(); err != nil { - klog.Errorf("failed to get loaded kernel modules: %v", err) + klog.ErrorS(err, "failed to get loaded kernel modules") } else { enabledModules = append(enabledModules, kmods...) s.features.Flags[LoadedModuleFeature] = nfdv1alpha1.NewFlagFeatures(kmods...) } if builtinMods, err := getBuiltinModules(); err != nil { - klog.Errorf("failed to get builtin kernel modules: %v", err) + klog.ErrorS(err, "failed to get builtin kernel modules") } else { enabledModules = append(enabledModules, builtinMods...) s.features.Flags[EnabledModuleFeature] = nfdv1alpha1.NewFlagFeatures(enabledModules...) } if selinux, err := SelinuxEnabled(); err != nil { - klog.Warning(err) + klog.ErrorS(err, "failed to detect selinux status") } else { s.features.Attributes[SelinuxFeature] = nfdv1alpha1.NewAttributeFeatures(nil) s.features.Attributes[SelinuxFeature].Elements["enabled"] = strconv.FormatBool(selinux) } - utils.KlogDump(3, "discovered kernel features:", " ", s.features) + klog.V(3).InfoS("discovered features", "featureSource", s.Name(), "features", utils.DelayedDumper(s.features)) return nil } diff --git a/source/kernel/selinux.go b/source/kernel/selinux.go index 13b2c39c4..51ecd9a14 100644 --- a/source/kernel/selinux.go +++ b/source/kernel/selinux.go @@ -17,7 +17,6 @@ limitations under the License. package kernel import ( - "fmt" "os" "path/filepath" @@ -30,18 +29,18 @@ import ( func SelinuxEnabled() (bool, error) { sysfsBase := hostpath.SysfsDir.Path("fs") if _, err := os.Stat(sysfsBase); err != nil { - return false, fmt.Errorf("unable to detect selinux status: %w", err) + return false, err } selinuxBase := filepath.Join(sysfsBase, "selinux") if _, err := os.Stat(selinuxBase); os.IsNotExist(err) { - klog.V(1).Info("selinux not available on the system") + klog.V(1).InfoS("selinux not available on the system") return false, nil } status, err := os.ReadFile(filepath.Join(selinuxBase, "enforce")) if err != nil { - return false, fmt.Errorf("failed to detect the status of selinux: %w", err) + return false, err } if status[0] == byte('1') { // selinux is enabled. diff --git a/source/local/local.go b/source/local/local.go index 2bebfb0d0..e93885336 100644 --- a/source/local/local.go +++ b/source/local/local.go @@ -76,7 +76,7 @@ func (s *localSource) SetConfig(conf source.Config) { case *Config: s.config = v default: - klog.Fatalf("invalid config type: %T", conf) + panic(fmt.Sprintf("invalid config type: %T", conf)) } } @@ -107,23 +107,22 @@ func (s *localSource) Discover() error { featuresFromFiles, err := getFeaturesFromFiles() if err != nil { - klog.Error(err) + klog.ErrorS(err, "failed to read feature files") } if s.config.HooksEnabled { - klog.Info("starting hooks...") + klog.InfoS("starting hooks...") featuresFromHooks, err := getFeaturesFromHooks() if err != nil { - klog.Error(err) + klog.ErrorS(err, "failed to run hooks") } // Merge features from hooks and files for k, v := range featuresFromHooks { if old, ok := featuresFromFiles[k]; ok { - klog.Warningf("overriding '%s': value changed from '%s' to '%s'", - k, old, v) + klog.InfoS("overriding label value", "labelKey", k, "oldValue", old, "newValue", v) } featuresFromFiles[k] = v } @@ -131,7 +130,7 @@ func (s *localSource) Discover() error { s.features.Attributes[LabelFeature] = nfdv1alpha1.NewAttributeFeatures(featuresFromFiles) - utils.KlogDump(3, "discovered local features:", " ", s.features) + klog.V(3).InfoS("discovered features", "featureSource", s.Name(), "features", utils.DelayedDumper(s.features)) return nil } @@ -173,30 +172,29 @@ func getFeaturesFromHooks() (map[string]string, error) { files, err := os.ReadDir(hookDir) if err != nil { if os.IsNotExist(err) { - klog.Infof("hook directory %v does not exist", hookDir) + klog.InfoS("hook directory does not exist", "path", hookDir) return features, nil } return features, fmt.Errorf("unable to access %v: %v", hookDir, err) } if len(files) > 0 { - klog.Warning("hooks are DEPRECATED since v0.12.0 and support will be removed in a future release; use feature files instead") + klog.InfoS("hooks are DEPRECATED since v0.12.0 and support will be removed in a future release; use feature files instead") } for _, file := range files { fileName := file.Name() lines, err := runHook(fileName) if err != nil { - klog.Errorf("source local failed running hook '%v': %v", fileName, err) + klog.ErrorS(err, "failed to run hook", "fileName", fileName) continue } // Append features fileFeatures := parseFeatures(lines) - utils.KlogDump(4, fmt.Sprintf("features from hook %q:", fileName), " ", fileFeatures) + klog.V(4).InfoS("hook executed", "fileName", fileName, "features", utils.DelayedDumper(fileFeatures)) for k, v := range fileFeatures { if old, ok := features[k]; ok { - klog.Warningf("overriding label '%s' from another hook (%s): value changed from '%s' to '%s'", - k, fileName, old, v) + klog.InfoS("overriding label value from another hook", "labelKey", k, "oldValue", old, "newValue", v, "fileName", fileName) } features[k] = v } @@ -212,7 +210,7 @@ func runHook(file string) ([][]byte, error) { path := filepath.Join(hookDir, file) filestat, err := os.Stat(path) if err != nil { - klog.Errorf("skipping %v, failed to get stat: %v", path, err) + klog.ErrorS(err, "failed to get filestat, skipping hook", "path", path) return lines, err } @@ -233,7 +231,7 @@ func runHook(file string) ([][]byte, error) { // Don't print the last empty string break } - klog.Errorf("%v: %s", file, line) + klog.InfoS(fmt.Sprintf("%s: %s", file, line)) } // Do not return any lines if an error occurred @@ -253,7 +251,7 @@ func getFeaturesFromFiles() (map[string]string, error) { files, err := os.ReadDir(featureFilesDir) if err != nil { if os.IsNotExist(err) { - klog.Infof("features directory %v does not exist", featureFilesDir) + klog.InfoS("features directory does not exist", "path", featureFilesDir) return features, nil } return features, fmt.Errorf("unable to access %v: %v", featureFilesDir, err) @@ -263,17 +261,16 @@ func getFeaturesFromFiles() (map[string]string, error) { fileName := file.Name() lines, err := getFileContent(fileName) if err != nil { - klog.Errorf("source local failed reading file '%v': %v", fileName, err) + klog.ErrorS(err, "failed to read file", "fileName", fileName) continue } // Append features fileFeatures := parseFeatures(lines) - utils.KlogDump(4, fmt.Sprintf("features from feature file %q:", fileName), " ", fileFeatures) + klog.V(4).InfoS("feature file read", "fileName", fileName, "features", utils.DelayedDumper(fileFeatures)) for k, v := range fileFeatures { if old, ok := features[k]; ok { - klog.Warningf("overriding label '%s' from another features.d file (%s): value changed from '%s' to '%s'", - k, fileName, old, v) + klog.InfoS("overriding label value from another feature file", "labelKey", k, "oldValue", old, "newValue", v, "fileName", fileName) } features[k] = v } @@ -289,7 +286,7 @@ func getFileContent(fileName string) ([][]byte, error) { path := filepath.Join(featureFilesDir, fileName) filestat, err := os.Stat(path) if err != nil { - klog.Errorf("skipping %v, failed to get stat: %v", path, err) + klog.ErrorS(err, "failed to get filestat, skipping features file", "path", path) return lines, err } diff --git a/source/memory/memory.go b/source/memory/memory.go index a26abc122..dbeb6b0ee 100644 --- a/source/memory/memory.go +++ b/source/memory/memory.go @@ -88,19 +88,19 @@ func (s *memorySource) Discover() error { // Detect NUMA if numa, err := detectNuma(); err != nil { - klog.Errorf("failed to detect NUMA nodes: %v", err) + klog.ErrorS(err, "failed to detect NUMA nodes") } else { s.features.Attributes[NumaFeature] = nfdv1alpha1.AttributeFeatureSet{Elements: numa} } // Detect NVDIMM if nv, err := detectNv(); err != nil { - klog.Errorf("failed to detect nvdimm devices: %v", err) + klog.ErrorS(err, "failed to detect nvdimm devices") } else { s.features.Instances[NvFeature] = nfdv1alpha1.InstanceFeatureSet{Elements: nv} } - utils.KlogDump(3, "discovered memory features:", " ", s.features) + klog.V(3).InfoS("discovered features", "featureSource", s.Name(), "features", utils.DelayedDumper(s.features)) return nil } @@ -135,7 +135,7 @@ func detectNv() ([]nfdv1alpha1.InstanceFeature, error) { devices, err := os.ReadDir(sysfsBasePath) if os.IsNotExist(err) { - klog.V(1).Info("No NVDIMM devices present") + klog.V(1).InfoS("No NVDIMM devices present") return info, nil } else if err != nil { return nil, fmt.Errorf("failed to list nvdimm devices: %w", err) @@ -158,7 +158,7 @@ func readNdDeviceInfo(path string) nfdv1alpha1.InstanceFeature { for _, attrName := range ndDevAttrs { data, err := os.ReadFile(filepath.Join(path, attrName)) if err != nil { - klog.V(3).Infof("failed to read nd device attribute %s: %w", attrName, err) + klog.V(3).ErrorS(err, "failed to read nd device attribute", "attributeName", attrName) continue } attrs[attrName] = strings.TrimSpace(string(data)) diff --git a/source/network/network.go b/source/network/network.go index 4b9d3b2dc..bdde160f2 100644 --- a/source/network/network.go +++ b/source/network/network.go @@ -77,7 +77,7 @@ func (s *networkSource) GetLabels() (source.FeatureLabels, error) { if v, ok := attrs[attr]; ok { t, err := strconv.Atoi(v) if err != nil { - klog.Errorf("failed to parse %s of %s: %v", attr, attrs["name"]) + klog.ErrorS(err, "failed to parse sriov attribute", "attributeName", attr, "deviceName", attrs["name"]) continue } if t > 0 { @@ -99,7 +99,7 @@ func (s *networkSource) Discover() error { } s.features.Instances[DeviceFeature] = nfdv1alpha1.InstanceFeatureSet{Elements: devs} - utils.KlogDump(3, "discovered network features:", " ", s.features) + klog.V(3).InfoS("discovered features", "featureSource", s.Name(), "features", utils.DelayedDumper(s.features)) return nil } @@ -126,8 +126,8 @@ func detectNetDevices() ([]nfdv1alpha1.InstanceFeature, error) { name := iface.Name() if _, err := os.Stat(filepath.Join(sysfsBasePath, name, "device")); err == nil { info = append(info, readIfaceInfo(filepath.Join(sysfsBasePath, name))) - } else if klog.V(3).Enabled() { - klog.Infof("skipping non-device iface %q", name) + } else if klogV := klog.V(3); klogV.Enabled() { + klogV.InfoS("skipping non-device iface", "interfaceName", name) } } @@ -140,7 +140,7 @@ func readIfaceInfo(path string) nfdv1alpha1.InstanceFeature { data, err := os.ReadFile(filepath.Join(path, attrName)) if err != nil { if !os.IsNotExist(err) { - klog.Errorf("failed to read net iface attribute %s: %v", attrName, err) + klog.ErrorS(err, "failed to read net iface attribute", "attributeName", attrName) } continue } @@ -151,7 +151,7 @@ func readIfaceInfo(path string) nfdv1alpha1.InstanceFeature { data, err := os.ReadFile(filepath.Join(path, "device", attrName)) if err != nil { if !os.IsNotExist(err) { - klog.Errorf("failed to read net device attribute %s: %v", attrName, err) + klog.ErrorS(err, "failed to read net device attribute", "attributeName", attrName) } continue } diff --git a/source/pci/pci.go b/source/pci/pci.go index d09850ff8..d2c7be92d 100644 --- a/source/pci/pci.go +++ b/source/pci/pci.go @@ -76,7 +76,7 @@ func (s *pciSource) SetConfig(conf source.Config) { case *Config: s.config = v default: - klog.Fatalf("invalid config type: %T", conf) + panic(fmt.Sprintf("invalid config type: %T", conf)) } } @@ -106,11 +106,11 @@ func (s *pciSource) GetLabels() (source.FeatureLabels, error) { for key := range configLabelFields { keys = append(keys, key) } - klog.Warningf("invalid fields (%s) in deviceLabelFields, ignoring...", strings.Join(keys, ", ")) + klog.InfoS("ignoring invalid fields in deviceLabelFields", "invalidFieldNames", keys) } if len(deviceLabelFields) == 0 { - klog.Warningf("no valid fields in deviceLabelFields defined, using the defaults") deviceLabelFields = []string{"class", "vendor"} + klog.InfoS("no valid fields in deviceLabelFields defined, using the defaults", "defaultFieldNames", deviceLabelFields) } // Iterate over all device classes @@ -148,7 +148,7 @@ func (s *pciSource) Discover() error { } s.features.Instances[DeviceFeature] = nfdv1alpha1.NewInstanceFeatures(devs) - utils.KlogDump(3, "discovered pci features:", " ", s.features) + klog.V(3).InfoS("discovered features", "featureSource", s.Name(), "features", utils.DelayedDumper(s.features)) return nil } diff --git a/source/pci/utils.go b/source/pci/utils.go index d9a370217..ac16b90e4 100644 --- a/source/pci/utils.go +++ b/source/pci/utils.go @@ -83,7 +83,7 @@ func detectPci() ([]nfdv1alpha1.InstanceFeature, error) { for _, device := range devices { info, err := readPciDevInfo(filepath.Join(sysfsBasePath, device.Name())) if err != nil { - klog.Error(err) + klog.ErrorS(err, "failed to read PCI device info") continue } devInfo = append(devInfo, *info) diff --git a/source/source.go b/source/source.go index 413aca719..053ea69f0 100644 --- a/source/source.go +++ b/source/source.go @@ -21,8 +21,6 @@ package source import ( "fmt" - "k8s.io/klog/v2" - nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1" ) @@ -167,7 +165,7 @@ func GetAllFeatures() *nfdv1alpha1.Features { // Prefix feature with the name of the source k = n + "." + k if typ := features.Exists(k); typ != "" { - klog.Exitf("feature source %q returned flag feature %q which already exists (type %q)", n, k, typ) + panic(fmt.Sprintf("feature source %q returned flag feature %q which already exists (type %q)", n, k, typ)) } features.Flags[k] = v } @@ -175,7 +173,7 @@ func GetAllFeatures() *nfdv1alpha1.Features { // Prefix feature with the name of the source k = n + "." + k if typ := features.Exists(k); typ != "" { - klog.Exitf("feature source %q returned attribute feature %q which already exists (type %q)", n, k, typ) + panic(fmt.Sprintf("feature source %q returned attribute feature %q which already exists (type %q)", n, k, typ)) } features.Attributes[k] = v } @@ -183,7 +181,7 @@ func GetAllFeatures() *nfdv1alpha1.Features { // Prefix feature with the name of the source k = n + "." + k if typ := features.Exists(k); typ != "" { - klog.Exitf("feature source %q returned instance feature %q which already exists (type %q)", n, k, typ) + panic(fmt.Sprintf("feature source %q returned instance feature %q which already exists (type %q)", n, k, typ)) } features.Instances[k] = v } diff --git a/source/storage/storage.go b/source/storage/storage.go index 64db926f8..b7534ae40 100644 --- a/source/storage/storage.go +++ b/source/storage/storage.go @@ -81,7 +81,7 @@ func (s *storageSource) Discover() error { } s.features.Instances[BlockFeature] = nfdv1alpha1.InstanceFeatureSet{Elements: devs} - utils.KlogDump(3, "discovered storage features:", " ", s.features) + klog.V(3).InfoS("discovered features", "featureSource", s.Name(), "features", utils.DelayedDumper(s.features)) return nil } @@ -116,7 +116,7 @@ func readBlockDevQueueInfo(path string) *nfdv1alpha1.InstanceFeature { for _, attrName := range queueAttrs { data, err := os.ReadFile(filepath.Join(path, "queue", attrName)) if err != nil { - klog.V(3).Infof("failed to read block device queue attribute %s: %w", attrName, err) + klog.V(3).ErrorS(err, "failed to read block device queue attribute", "attributeName", attrName) continue } attrs[attrName] = strings.TrimSpace(string(data)) diff --git a/source/system/system.go b/source/system/system.go index 9399bd1d9..1a5c5aa7e 100644 --- a/source/system/system.go +++ b/source/system/system.go @@ -87,7 +87,7 @@ func (s *systemSource) Discover() error { // Get os-release information release, err := parseOSRelease() if err != nil { - klog.Errorf("failed to get os-release: %s", err) + klog.ErrorS(err, "failed to get os-release") } else { s.features.Attributes[OsReleaseFeature] = nfdv1alpha1.NewAttributeFeatures(release) @@ -101,7 +101,7 @@ func (s *systemSource) Discover() error { } } - utils.KlogDump(3, "discovered system features:", " ", s.features) + klog.V(3).InfoS("discovered features", "featureSource", s.Name(), "features", utils.DelayedDumper(s.features)) return nil } diff --git a/source/usb/usb.go b/source/usb/usb.go index a2fce7d2f..198c9d817 100644 --- a/source/usb/usb.go +++ b/source/usb/usb.go @@ -79,7 +79,7 @@ func (s *usbSource) SetConfig(conf source.Config) { case *Config: s.config = v default: - klog.Fatalf("invalid config type: %T", conf) + panic(fmt.Sprintf("invalid config type: %T", conf)) } } @@ -109,11 +109,11 @@ func (s *usbSource) GetLabels() (source.FeatureLabels, error) { for key := range configLabelFields { keys = append(keys, key) } - klog.Warningf("invalid fields (%s) in deviceLabelFields, ignoring...", strings.Join(keys, ", ")) + klog.InfoS("ignoring invalid fields in deviceLabelFields", "invalidFieldNames", keys) } if len(deviceLabelFields) == 0 { - klog.Warningf("no valid fields in deviceLabelFields defined, using the defaults") deviceLabelFields = defaultDeviceLabelFields() + klog.InfoS("no valid fields in deviceLabelFields defined, using the defaults", "defaultFieldNames", deviceLabelFields) } // Iterate over all device classes @@ -147,7 +147,7 @@ func (s *usbSource) Discover() error { } s.features.Instances[DeviceFeature] = nfdv1alpha1.NewInstanceFeatures(devs) - utils.KlogDump(3, "discovered usb features:", " ", s.features) + klog.V(3).InfoS("discovered features", "featureSource", s.Name(), "features", utils.DelayedDumper(s.features)) return nil } diff --git a/source/usb/utils.go b/source/usb/utils.go index 3f705fca6..3215a5b1c 100644 --- a/source/usb/utils.go +++ b/source/usb/utils.go @@ -118,7 +118,7 @@ func detectUsb() ([]nfdv1alpha1.InstanceFeature, error) { for _, devPath := range devPaths { devs, err := readUsbDevInfo(filepath.Dir(devPath)) if err != nil { - klog.Error(err) + klog.ErrorS(err, "failed to read USB device info") continue }