-
Notifications
You must be signed in to change notification settings - Fork 5.5k
/
resolver.go
149 lines (139 loc) · 4.15 KB
/
resolver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//go:build linux && amd64
package intel_pmu
import (
"errors"
"fmt"
"strings"
"github.com/influxdata/telegraf"
ia "github.com/intel/iaevents"
)
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 fmt.Errorf("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 fmt.Errorf("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 fmt.Errorf("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 fmt.Errorf("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 []*eventWithQuals, 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
}