1
0
Fork 0
telegraf/plugins/inputs/intel_pmu/resolver.go
Daniel Baumann 4978089aab
Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-05-24 07:26:29 +02:00

150 lines
4.1 KiB
Go

//go:build linux && amd64
package intel_pmu
import (
"errors"
"fmt"
"strings"
ia "github.com/intel/iaevents"
"github.com/influxdata/telegraf"
)
type entitiesResolver interface {
resolveEntities(coreEntities []*coreEventEntity, uncoreEntities []*uncoreEventEntity) error
}
type iaEntitiesResolver struct {
reader ia.Reader
transformer ia.Transformer
log telegraf.Logger
}
func (e *iaEntitiesResolver) resolveEntities(coreEntities []*coreEventEntity, uncoreEntities []*uncoreEventEntity) error {
for _, entity := range coreEntities {
if entity == nil {
return errors.New("core entity is nil")
}
if entity.allEvents {
newEvents, _, err := e.resolveAllEvents()
if err != nil {
return fmt.Errorf("failed to resolve all events: %w", err)
}
entity.parsedEvents = newEvents
continue
}
for _, event := range entity.parsedEvents {
if event == nil {
return errors.New("parsed core event is nil")
}
customEvent, err := e.resolveEvent(event.name, event.qualifiers)
if err != nil {
return fmt.Errorf("failed to resolve core event %q: %w", event.name, err)
}
if customEvent.Event.Uncore {
return fmt.Errorf("uncore event %q found in core entity", event.name)
}
event.custom = customEvent
}
}
for _, entity := range uncoreEntities {
if entity == nil {
return errors.New("uncore entity is nil")
}
if entity.allEvents {
_, newEvents, err := e.resolveAllEvents()
if err != nil {
return fmt.Errorf("failed to resolve all events: %w", err)
}
entity.parsedEvents = newEvents
continue
}
for _, event := range entity.parsedEvents {
if event == nil {
return errors.New("parsed uncore event is nil")
}
customEvent, err := e.resolveEvent(event.name, event.qualifiers)
if err != nil {
return fmt.Errorf("failed to resolve uncore event %q: %w", event.name, err)
}
if !customEvent.Event.Uncore {
return fmt.Errorf("core event %q found in uncore entity", event.name)
}
event.custom = customEvent
}
}
return nil
}
func (e *iaEntitiesResolver) resolveAllEvents() (coreEvents, uncoreEvents []*eventWithQuals, err error) {
if e.transformer == nil {
return nil, nil, errors.New("transformer is nil")
}
perfEvents, err := e.transformer.Transform(e.reader, ia.NewNameMatcher())
if err != nil {
var re *ia.TransformationError
if !errors.As(err, &re) {
return nil, nil, err
}
if e.log != nil && re != nil {
var eventErrs []string
for _, eventErr := range re.Errors() {
if eventErr == nil {
continue
}
eventErrs = append(eventErrs, eventErr.Error())
}
errorsStr := strings.Join(eventErrs, ",\n")
e.log.Warnf("Cannot resolve all of the events from provided files:\n%s.\nSome events may be omitted.", errorsStr)
}
}
for _, perfEvent := range perfEvents {
newEvent := &eventWithQuals{
name: perfEvent.Name,
custom: ia.CustomizableEvent{Event: perfEvent},
}
// build options for event
newEvent.custom.Options, err = ia.NewOptions().Build()
if err != nil {
return nil, nil, fmt.Errorf("failed to build options for event %q: %w", perfEvent.Name, err)
}
if perfEvent.Uncore {
uncoreEvents = append(uncoreEvents, newEvent)
continue
}
coreEvents = append(coreEvents, newEvent)
}
return coreEvents, uncoreEvents, nil
}
func (e *iaEntitiesResolver) resolveEvent(name string, qualifiers []string) (ia.CustomizableEvent, error) {
var custom ia.CustomizableEvent
if e.transformer == nil {
return custom, errors.New("events transformer is nil")
}
if name == "" {
return custom, errors.New("event name is empty")
}
matcher := ia.NewNameMatcher(name)
perfEvents, err := e.transformer.Transform(e.reader, matcher)
if err != nil {
return custom, fmt.Errorf("failed to transform perf events: %w", err)
}
if len(perfEvents) < 1 {
return custom, fmt.Errorf("failed to resolve unknown event %q", name)
}
// build options for event
options, err := ia.NewOptions().SetAttrModifiers(qualifiers).Build()
if err != nil {
return custom, fmt.Errorf("failed to build options for event %q: %w", name, err)
}
custom = ia.CustomizableEvent{
Event: perfEvents[0],
Options: options,
}
return custom, nil
}