| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- // Copyright 2020 Google Inc. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- // Configuration for perf event manager.
- package perf
- import (
- "encoding/json"
- "fmt"
- "os"
- "strconv"
- "k8s.io/klog/v2"
- )
- type PerfEvents struct {
- // Core perf events to be measured.
- Core Events `json:"core,omitempty"`
- // Uncore perf events to be measured.
- Uncore Events `json:"uncore,omitempty"`
- }
- type Events struct {
- // List of perf events' names to be measured.
- Events []Group `json:"events"`
- // List of custom perf events' to be measured. It is impossible to
- // specify some events using their names and in such case you have
- // to provide lower level configuration.
- CustomEvents []CustomEvent `json:"custom_events"`
- }
- type Event string
- type CustomEvent struct {
- // Type of the event. See perf_event_attr documentation
- // at man perf_event_open.
- Type uint32 `json:"type,omitempty"`
- // Symbolically formed event like:
- // pmu/config=PerfEvent.Config[0],config1=PerfEvent.Config[1],config2=PerfEvent.Config[2]
- // as described in man perf-stat.
- Config Config `json:"config"`
- // Human readable name of metric that will be created from the event.
- Name Event `json:"name"`
- }
- type Config []uint64
- func (c *Config) UnmarshalJSON(b []byte) error {
- config := []string{}
- err := json.Unmarshal(b, &config)
- if err != nil {
- klog.Errorf("Unmarshalling %s into slice of strings failed: %q", b, err)
- return fmt.Errorf("unmarshalling %s into slice of strings failed: %q", b, err)
- }
- intermediate := []uint64{}
- for _, v := range config {
- uintValue, err := strconv.ParseUint(v, 0, 64)
- if err != nil {
- klog.Errorf("Parsing %#v into uint64 failed: %q", v, err)
- return fmt.Errorf("parsing %#v into uint64 failed: %q", v, err)
- }
- intermediate = append(intermediate, uintValue)
- }
- *c = intermediate
- return nil
- }
- func parseConfig(file *os.File) (events PerfEvents, err error) {
- decoder := json.NewDecoder(file)
- err = decoder.Decode(&events)
- if err != nil {
- err = fmt.Errorf("unable to load perf events configuration from %q: %q", file.Name(), err)
- return
- }
- return
- }
- type Group struct {
- events []Event
- array bool
- }
- func (g *Group) UnmarshalJSON(b []byte) error {
- var jsonObj interface{}
- err := json.Unmarshal(b, &jsonObj)
- if err != nil {
- return err
- }
- switch obj := jsonObj.(type) {
- case string:
- *g = Group{
- events: []Event{Event(obj)},
- array: false,
- }
- return nil
- case []interface{}:
- group := Group{
- events: make([]Event, 0, len(obj)),
- array: true,
- }
- for _, v := range obj {
- value, ok := v.(string)
- if !ok {
- return fmt.Errorf("cannot unmarshal %v", value)
- }
- group.events = append(group.events, Event(value))
- }
- *g = group
- return nil
- }
- return fmt.Errorf("unsupported type")
- }
|