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
274
plugins/inputs/intel_pmt/xml_parser.go
Normal file
274
plugins/inputs/intel_pmt/xml_parser.go
Normal file
|
@ -0,0 +1,274 @@
|
|||
//go:build linux && amd64
|
||||
|
||||
package intel_pmt
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type pmt struct {
|
||||
XMLName xml.Name `xml:"pmt"`
|
||||
Mappings mappings `xml:"mappings"`
|
||||
}
|
||||
type mappings struct {
|
||||
XMLName xml.Name `xml:"mappings"`
|
||||
Mapping []mapping `xml:"mapping"`
|
||||
}
|
||||
|
||||
type mapping struct {
|
||||
XMLName xml.Name `xml:"mapping"`
|
||||
GUID string `xml:"guid,attr"`
|
||||
XMLSet xmlset `xml:"xmlset"`
|
||||
}
|
||||
|
||||
type xmlset struct {
|
||||
XMLName xml.Name `xml:"xmlset"`
|
||||
Basedir string `xml:"basedir"`
|
||||
Aggregator string `xml:"aggregator"`
|
||||
AggregatorInterface string `xml:"aggregatorinterface"`
|
||||
}
|
||||
|
||||
type aggregator struct {
|
||||
XMLName xml.Name `xml:"Aggregator"`
|
||||
Name string `xml:"name"`
|
||||
SampleGroup []sampleGroup `xml:"SampleGroup"`
|
||||
}
|
||||
|
||||
type sampleGroup struct {
|
||||
XMLName xml.Name `xml:"SampleGroup"`
|
||||
SampleID uint64 `xml:"sampleID,attr"`
|
||||
Sample []sample `xml:"sample"`
|
||||
}
|
||||
|
||||
type sample struct {
|
||||
XMLName xml.Name `xml:"sample"`
|
||||
SampleName string `xml:"name,attr"`
|
||||
DatatypeIDRef string `xml:"datatypeIDREF,attr"`
|
||||
SampleID string `xml:"sampleID,attr"`
|
||||
Lsb uint64 `xml:"lsb"`
|
||||
Msb uint64 `xml:"msb"`
|
||||
|
||||
mask uint64
|
||||
}
|
||||
|
||||
type aggregatorInterface struct {
|
||||
XMLName xml.Name `xml:"AggregatorInterface"`
|
||||
Transformations transformations `xml:"TransFormations"`
|
||||
AggregatorSamples aggregatorSamples `xml:"AggregatorSamples"`
|
||||
}
|
||||
|
||||
type transformations struct {
|
||||
XMLName xml.Name `xml:"TransFormations"`
|
||||
Transformation []transformation `xml:"TransFormation"`
|
||||
}
|
||||
|
||||
type transformation struct {
|
||||
XMLName xml.Name `xml:"TransFormation"`
|
||||
Name string `xml:"name,attr"`
|
||||
TransformID string `xml:"transformID,attr"`
|
||||
Transform string `xml:"transform"`
|
||||
}
|
||||
|
||||
type aggregatorSamples struct {
|
||||
XMLName xml.Name `xml:"AggregatorSamples"`
|
||||
AggregatorSample []aggregatorSample `xml:"T_AggregatorSample"`
|
||||
}
|
||||
|
||||
type aggregatorSample struct {
|
||||
XMLName xml.Name `xml:"T_AggregatorSample"`
|
||||
SampleName string `xml:"sampleName,attr"`
|
||||
SampleGroup string `xml:"sampleGroup,attr"`
|
||||
DatatypeIDRef string `xml:"datatypeIDREF,attr"`
|
||||
TransformInputs transformInputs `xml:"TransFormInputs"`
|
||||
TransformREF string `xml:"transformREF"`
|
||||
|
||||
core string
|
||||
cha string
|
||||
}
|
||||
|
||||
type transformInputs struct {
|
||||
XMLName xml.Name `xml:"TransFormInputs"`
|
||||
TransformInput []transformInput `xml:"TransFormInput"`
|
||||
}
|
||||
|
||||
type transformInput struct {
|
||||
XMLName xml.Name `xml:"TransFormInput"`
|
||||
VarName string `xml:"varName,attr"`
|
||||
SampleIDREF string `xml:"sampleIDREF"`
|
||||
}
|
||||
|
||||
type sourceReader interface {
|
||||
getReadCloser(source string) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
type fileReader struct{}
|
||||
|
||||
func (fileReader) getReadCloser(source string) (io.ReadCloser, error) {
|
||||
return os.Open(source)
|
||||
}
|
||||
|
||||
// parseXMLs reads and parses PMT XMLs.
|
||||
//
|
||||
// This method retrieves all metadata about known GUIDs from PmtSpec.
|
||||
// Then, it explores PMT sysfs to find all readable "telem" files and their GUIDs.
|
||||
// It then matches found (readable) system GUIDs with GUIDs from metadata and
|
||||
// reads corresponding sets of XMLs.
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// error - if PMT spec is empty, if exploring PMT sysfs fails, or if reading XMLs fails.
|
||||
func (p *IntelPMT) parseXMLs() error {
|
||||
err := parseXML(p.PmtSpec, p.reader, &p.pmtMetadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(p.pmtMetadata.Mappings.Mapping) == 0 {
|
||||
return errors.New("pmt XML provided contains no mappings")
|
||||
}
|
||||
|
||||
err = p.readXMLs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.pmtTransformations = make(map[string]map[string]transformation)
|
||||
for guid := range p.pmtTelemetryFiles {
|
||||
p.pmtTransformations[guid] = make(map[string]transformation)
|
||||
for _, transform := range p.pmtAggregatorInterface[guid].Transformations.Transformation {
|
||||
p.pmtTransformations[guid][transform.TransformID] = transform
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readXMLs function reads all XMLs for found GUIDs.
|
||||
//
|
||||
// This method reads two required XMLs for each found GUID,
|
||||
// checks if any of the provided filtering metrics were not found,
|
||||
// and checks if there is at least one non-empty XML set.
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// error - error if reading operation failed or if all XMLs are empty.
|
||||
func (p *IntelPMT) readXMLs() error {
|
||||
p.pmtAggregator = make(map[string]aggregator)
|
||||
p.pmtAggregatorInterface = make(map[string]aggregatorInterface)
|
||||
dtMetricsFound := make(map[string]bool)
|
||||
sampleFilterFound := make(map[string]bool)
|
||||
for guid := range p.pmtTelemetryFiles {
|
||||
err := p.getAllXMLData(guid, dtMetricsFound, sampleFilterFound)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed reading XMLs: %w", err)
|
||||
}
|
||||
}
|
||||
for _, dt := range p.DatatypeFilter {
|
||||
if _, ok := dtMetricsFound[dt]; !ok {
|
||||
p.Log.Warnf("Configured datatype metric %q has not been found", dt)
|
||||
}
|
||||
}
|
||||
for _, sm := range p.SampleFilter {
|
||||
if _, ok := sampleFilterFound[sm]; !ok {
|
||||
p.Log.Warnf("Configured sample metric %q has not been found", sm)
|
||||
}
|
||||
}
|
||||
|
||||
return p.verifyNoEmpty()
|
||||
}
|
||||
|
||||
// getAllXMLData retrieves two XMLs for given GUID.
|
||||
//
|
||||
// This method reads where to find the Aggregator and Aggregator interface XMLs
|
||||
// from pmt metadata and reads found XMLs.
|
||||
// This method also filters read XMLs before saving them
|
||||
// and extracts additional tags from the data.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// guid - GUID saying which XMLs should be read.
|
||||
// dtMetricsFound - a map of found datatype metrics for all GUIDs.
|
||||
// smFound - a map of found sample names for all GUIDs.
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// error - if reading XML has failed.
|
||||
func (p *IntelPMT) getAllXMLData(guid string, dtMetricsFound, smFound map[string]bool) error {
|
||||
for _, mapping := range p.pmtMetadata.Mappings.Mapping {
|
||||
if mapping.GUID == guid {
|
||||
basedir := mapping.XMLSet.Basedir
|
||||
guid := mapping.GUID
|
||||
var aggSource, aggInterfaceSource string
|
||||
|
||||
aggSource = filepath.Join(p.pmtBasePath, basedir, mapping.XMLSet.Aggregator)
|
||||
aggInterfaceSource = filepath.Join(p.pmtBasePath, basedir, mapping.XMLSet.AggregatorInterface)
|
||||
|
||||
tAgg := aggregator{}
|
||||
tAggInterface := aggregatorInterface{}
|
||||
|
||||
err := parseXML(aggSource, p.reader, &tAgg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed reading aggregator XML: %w", err)
|
||||
}
|
||||
err = parseXML(aggInterfaceSource, p.reader, &tAggInterface)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed reading aggregator interface XML: %w", err)
|
||||
}
|
||||
if len(p.DatatypeFilter) > 0 {
|
||||
tAgg.filterAggregatorByDatatype(p.DatatypeFilter)
|
||||
tAggInterface.filterAggInterfaceByDatatype(p.DatatypeFilter, dtMetricsFound)
|
||||
}
|
||||
if len(p.SampleFilter) > 0 {
|
||||
tAgg.filterAggregatorBySampleName(p.SampleFilter)
|
||||
tAggInterface.filterAggInterfaceBySampleName(p.SampleFilter, smFound)
|
||||
}
|
||||
tAgg.calculateMasks()
|
||||
p.pmtAggregator[guid] = tAgg
|
||||
tAggInterface.extractTagsFromSample()
|
||||
p.pmtAggregatorInterface[guid] = tAggInterface
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *aggregator) calculateMasks() {
|
||||
for i := range a.SampleGroup {
|
||||
for j, sample := range a.SampleGroup[i].Sample {
|
||||
mask := computeMask(sample.Msb, sample.Lsb)
|
||||
a.SampleGroup[i].Sample[j].mask = mask
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func computeMask(msb, lsb uint64) uint64 {
|
||||
msbMask := uint64(0xffffffffffffffff) & ((1 << (msb + 1)) - 1)
|
||||
lsbMask := uint64(0xffffffffffffffff) & (1<<lsb - 1)
|
||||
return msbMask & (^lsbMask)
|
||||
}
|
||||
|
||||
func parseXML(source string, sr sourceReader, v interface{}) error {
|
||||
if sr == nil {
|
||||
return errors.New("xml reader has not been initialized")
|
||||
}
|
||||
reader, err := sr.getReadCloser(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading source %q: %w", source, err)
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
parser := xml.NewDecoder(reader)
|
||||
parser.AutoClose = xml.HTMLAutoClose
|
||||
parser.Entity = xml.HTMLEntity
|
||||
// There are "&" in XMLs in entity references.
|
||||
// Parser sees it as not allowed characters.
|
||||
// Strict mode disabled to handle that.
|
||||
parser.Strict = false
|
||||
err = parser.Decode(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding an XML %q: %w", source, err)
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue