github.com/google/cadvisor@v0.49.1/perf/config.go (about)

     1  // Copyright 2020 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Configuration for perf event manager.
    16  package perf
    17  
    18  import (
    19  	"encoding/json"
    20  	"fmt"
    21  	"os"
    22  	"strconv"
    23  
    24  	"k8s.io/klog/v2"
    25  )
    26  
    27  type PerfEvents struct {
    28  	// Core perf events to be measured.
    29  	Core Events `json:"core,omitempty"`
    30  
    31  	// Uncore perf events to be measured.
    32  	Uncore Events `json:"uncore,omitempty"`
    33  }
    34  
    35  type Events struct {
    36  	// List of perf events' names to be measured.
    37  	Events []Group `json:"events"`
    38  
    39  	// List of custom perf events' to be measured. It is impossible to
    40  	// specify some events using their names and in such case you have
    41  	// to provide lower level configuration.
    42  	CustomEvents []CustomEvent `json:"custom_events"`
    43  }
    44  
    45  type Event string
    46  
    47  type CustomEvent struct {
    48  	// Type of the event. See perf_event_attr documentation
    49  	// at man perf_event_open.
    50  	Type uint32 `json:"type,omitempty"`
    51  
    52  	// Symbolically formed event like:
    53  	// pmu/config=PerfEvent.Config[0],config1=PerfEvent.Config[1],config2=PerfEvent.Config[2]
    54  	// as described in man perf-stat.
    55  	Config Config `json:"config"`
    56  
    57  	// Human readable name of metric that will be created from the event.
    58  	Name Event `json:"name"`
    59  }
    60  
    61  type Config []uint64
    62  
    63  func (c *Config) UnmarshalJSON(b []byte) error {
    64  	config := []string{}
    65  	err := json.Unmarshal(b, &config)
    66  	if err != nil {
    67  		klog.Errorf("Unmarshalling %s into slice of strings failed: %q", b, err)
    68  		return fmt.Errorf("unmarshalling %s into slice of strings failed: %q", b, err)
    69  	}
    70  	intermediate := []uint64{}
    71  	for _, v := range config {
    72  		uintValue, err := strconv.ParseUint(v, 0, 64)
    73  		if err != nil {
    74  			klog.Errorf("Parsing %#v into uint64 failed: %q", v, err)
    75  			return fmt.Errorf("parsing %#v into uint64 failed: %q", v, err)
    76  		}
    77  		intermediate = append(intermediate, uintValue)
    78  	}
    79  	*c = intermediate
    80  	return nil
    81  }
    82  
    83  func parseConfig(file *os.File) (events PerfEvents, err error) {
    84  	decoder := json.NewDecoder(file)
    85  	err = decoder.Decode(&events)
    86  	if err != nil {
    87  		err = fmt.Errorf("unable to load perf events configuration from %q: %q", file.Name(), err)
    88  		return
    89  	}
    90  	return
    91  }
    92  
    93  type Group struct {
    94  	events []Event
    95  	array  bool
    96  }
    97  
    98  func (g *Group) UnmarshalJSON(b []byte) error {
    99  	var jsonObj interface{}
   100  	err := json.Unmarshal(b, &jsonObj)
   101  	if err != nil {
   102  		return err
   103  	}
   104  	switch obj := jsonObj.(type) {
   105  	case string:
   106  		*g = Group{
   107  			events: []Event{Event(obj)},
   108  			array:  false,
   109  		}
   110  		return nil
   111  	case []interface{}:
   112  		group := Group{
   113  			events: make([]Event, 0, len(obj)),
   114  			array:  true,
   115  		}
   116  		for _, v := range obj {
   117  			value, ok := v.(string)
   118  			if !ok {
   119  				return fmt.Errorf("cannot unmarshal %v", value)
   120  			}
   121  			group.events = append(group.events, Event(value))
   122  		}
   123  		*g = group
   124  		return nil
   125  	}
   126  	return fmt.Errorf("unsupported type")
   127  }