Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
240
plugins/inputs/intel_pmu/reader.go
Normal file
240
plugins/inputs/intel_pmu/reader.go
Normal file
|
@ -0,0 +1,240 @@
|
|||
//go:build linux && amd64
|
||||
|
||||
package intel_pmu
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
ia "github.com/intel/iaevents"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type coreMetric struct {
|
||||
values ia.CounterValue
|
||||
scaled uint64
|
||||
|
||||
name string
|
||||
tag string
|
||||
cpu int
|
||||
|
||||
time time.Time
|
||||
}
|
||||
|
||||
type uncoreMetric struct {
|
||||
values ia.CounterValue
|
||||
scaled uint64
|
||||
|
||||
name string
|
||||
unitType string
|
||||
unit string
|
||||
tag string
|
||||
socket int
|
||||
|
||||
agg bool
|
||||
|
||||
time time.Time
|
||||
}
|
||||
|
||||
type valuesReader interface {
|
||||
readValue(event *ia.ActiveEvent) (ia.CounterValue, error)
|
||||
}
|
||||
|
||||
type iaValuesReader struct{}
|
||||
|
||||
func (iaValuesReader) readValue(event *ia.ActiveEvent) (ia.CounterValue, error) {
|
||||
return event.ReadValue()
|
||||
}
|
||||
|
||||
type entitiesValuesReader interface {
|
||||
readEntities([]*coreEventEntity, []*uncoreEventEntity) ([]coreMetric, []uncoreMetric, error)
|
||||
}
|
||||
|
||||
type iaEntitiesValuesReader struct {
|
||||
eventReader valuesReader
|
||||
timer clock
|
||||
}
|
||||
|
||||
type clock interface {
|
||||
now() time.Time
|
||||
}
|
||||
|
||||
type realClock struct{}
|
||||
|
||||
func (realClock) now() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
func (ie *iaEntitiesValuesReader) readEntities(coreEntities []*coreEventEntity, uncoreEntities []*uncoreEventEntity) ([]coreMetric, []uncoreMetric, error) {
|
||||
var coreMetrics []coreMetric
|
||||
var uncoreMetrics []uncoreMetric
|
||||
|
||||
for _, entity := range coreEntities {
|
||||
newMetrics, err := ie.readCoreEvents(entity)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
coreMetrics = append(coreMetrics, newMetrics...)
|
||||
}
|
||||
for _, entity := range uncoreEntities {
|
||||
newMetrics, err := ie.readUncoreEvents(entity)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
uncoreMetrics = append(uncoreMetrics, newMetrics...)
|
||||
}
|
||||
return coreMetrics, uncoreMetrics, nil
|
||||
}
|
||||
|
||||
func (ie *iaEntitiesValuesReader) readCoreEvents(entity *coreEventEntity) ([]coreMetric, error) {
|
||||
if ie.eventReader == nil || ie.timer == nil {
|
||||
return nil, errors.New("event values reader or timer is nil")
|
||||
}
|
||||
if entity == nil {
|
||||
return nil, errors.New("entity is nil")
|
||||
}
|
||||
metrics := make([]coreMetric, len(entity.activeEvents))
|
||||
errGroup := errgroup.Group{}
|
||||
|
||||
for id, actualEvent := range entity.activeEvents {
|
||||
if actualEvent == nil || actualEvent.PerfEvent == nil {
|
||||
return nil, errors.New("active event or corresponding perf event is nil")
|
||||
}
|
||||
|
||||
errGroup.Go(func() error {
|
||||
values, err := ie.eventReader.readValue(actualEvent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read core event %q values: %w", actualEvent, err)
|
||||
}
|
||||
cpu, _ := actualEvent.PMUPlacement()
|
||||
newMetric := coreMetric{
|
||||
values: values,
|
||||
tag: entity.EventsTag,
|
||||
cpu: cpu,
|
||||
name: actualEvent.PerfEvent.Name,
|
||||
time: ie.timer.now(),
|
||||
}
|
||||
metrics[id] = newMetric
|
||||
return nil
|
||||
})
|
||||
}
|
||||
err := errGroup.Wait()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return metrics, nil
|
||||
}
|
||||
|
||||
func (ie *iaEntitiesValuesReader) readUncoreEvents(entity *uncoreEventEntity) ([]uncoreMetric, error) {
|
||||
if entity == nil {
|
||||
return nil, errors.New("entity is nil")
|
||||
}
|
||||
var uncoreMetrics []uncoreMetric
|
||||
|
||||
for _, event := range entity.activeMultiEvents {
|
||||
if entity.Aggregate {
|
||||
newMetric, err := ie.readMultiEventAgg(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newMetric.tag = entity.EventsTag
|
||||
uncoreMetrics = append(uncoreMetrics, newMetric)
|
||||
} else {
|
||||
newMetrics, err := ie.readMultiEventSeparately(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range newMetrics {
|
||||
newMetrics[i].tag = entity.EventsTag
|
||||
}
|
||||
uncoreMetrics = append(uncoreMetrics, newMetrics...)
|
||||
}
|
||||
}
|
||||
return uncoreMetrics, nil
|
||||
}
|
||||
|
||||
func (ie *iaEntitiesValuesReader) readMultiEventSeparately(multiEvent multiEvent) ([]uncoreMetric, error) {
|
||||
if ie.eventReader == nil || ie.timer == nil {
|
||||
return nil, errors.New("event values reader or timer is nil")
|
||||
}
|
||||
if len(multiEvent.activeEvents) < 1 || multiEvent.perfEvent == nil {
|
||||
return nil, errors.New("no active events or perf event is nil")
|
||||
}
|
||||
activeEvents := multiEvent.activeEvents
|
||||
perfEvent := multiEvent.perfEvent
|
||||
|
||||
metrics := make([]uncoreMetric, len(activeEvents))
|
||||
group := errgroup.Group{}
|
||||
|
||||
for id, actualEvent := range activeEvents {
|
||||
group.Go(func() error {
|
||||
values, err := ie.eventReader.readValue(actualEvent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read uncore event %q values: %w", actualEvent, err)
|
||||
}
|
||||
newMetric := uncoreMetric{
|
||||
values: values,
|
||||
socket: multiEvent.socket,
|
||||
unitType: perfEvent.PMUName,
|
||||
name: perfEvent.Name,
|
||||
unit: actualEvent.PMUName(),
|
||||
time: ie.timer.now(),
|
||||
}
|
||||
metrics[id] = newMetric
|
||||
return nil
|
||||
})
|
||||
err := group.Wait()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return metrics, nil
|
||||
}
|
||||
|
||||
func (ie *iaEntitiesValuesReader) readMultiEventAgg(multiEvent multiEvent) (uncoreMetric, error) {
|
||||
if ie.eventReader == nil || ie.timer == nil {
|
||||
return uncoreMetric{}, errors.New("event values reader or timer is nil")
|
||||
}
|
||||
if len(multiEvent.activeEvents) < 1 || multiEvent.perfEvent == nil {
|
||||
return uncoreMetric{}, errors.New("no active events or perf event is nil")
|
||||
}
|
||||
activeEvents := multiEvent.activeEvents
|
||||
perfEvent := multiEvent.perfEvent
|
||||
|
||||
values := make([]ia.CounterValue, len(activeEvents))
|
||||
group := errgroup.Group{}
|
||||
|
||||
for id, actualEvent := range activeEvents {
|
||||
group.Go(func() error {
|
||||
value, err := ie.eventReader.readValue(actualEvent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read uncore event %q values: %w", actualEvent, err)
|
||||
}
|
||||
values[id] = value
|
||||
return nil
|
||||
})
|
||||
}
|
||||
err := group.Wait()
|
||||
if err != nil {
|
||||
return uncoreMetric{}, err
|
||||
}
|
||||
|
||||
bRaw, bEnabled, bRunning := ia.AggregateValues(values)
|
||||
if !bRaw.IsUint64() || !bEnabled.IsUint64() || !bRunning.IsUint64() {
|
||||
return uncoreMetric{}, fmt.Errorf("cannot aggregate %q values, uint64 exceeding", perfEvent)
|
||||
}
|
||||
aggValues := ia.CounterValue{
|
||||
Raw: bRaw.Uint64(),
|
||||
Enabled: bEnabled.Uint64(),
|
||||
Running: bRunning.Uint64(),
|
||||
}
|
||||
newMetric := uncoreMetric{
|
||||
values: aggValues,
|
||||
socket: multiEvent.socket,
|
||||
unitType: perfEvent.PMUName,
|
||||
name: perfEvent.Name,
|
||||
time: ie.timer.now(),
|
||||
}
|
||||
return newMetric, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue