-
Notifications
You must be signed in to change notification settings - Fork 71
fix(daemon): aggregate packages throughout harvest #1103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
e562b95
abcc444
3ededac
27e397b
8884a54
26b84fd
4684408
c0ff297
e229340
7f33a51
9ed17ed
49fc970
711fbc6
e2755fb
7b55055
7e7ac38
5f51ac4
4c274d4
8a33114
8c09aed
7947e42
5ab8358
f7cd412
382843f
7b65210
76c2044
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -733,6 +733,9 @@ func (t *Test) comparePhpPackages(harvest *newrelic.Harvest) { | |
} | ||
} | ||
|
||
// we don't currently test multiple requests that could result in needing to track package history | ||
// or filter packages. An empty map here will allow all packages to be reported unfiltered. | ||
harvest.PhpPackages.Filter(make(map[newrelic.PhpPackagesKey]struct{})) | ||
audit, err := newrelic.IntegrationData(harvest.PhpPackages, newrelic.AgentRunID("?? agent run id"), time.Now()) | ||
if nil != err { | ||
t.Fatal(err) | ||
|
@@ -763,25 +766,15 @@ func (t *Test) comparePhpPackages(harvest *newrelic.Harvest) { | |
len(expectedPackages), len(actualPackages), expectedPackages, actualPackages)) | ||
return | ||
} | ||
for i, _ := range expectedPackages { | ||
bduranleau-nr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for i := range expectedPackages { | ||
var matchingIdx int = -1 | ||
for j, pkg := range actualPackages { | ||
//fmt.Printf("Comparing %s to %s\n", pkg.Name, expectedPackages[i].Name) | ||
if pkg.Name == expectedPackages[i].Name { | ||
//fmt.Printf("Match - index = %d\n", j) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Were all of these comments left in previously for ease of future debugging efforts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know the origin of these comments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did the autoformatter remove them? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did while I was debugging a problem with the tests There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
matchingIdx = j | ||
break | ||
} | ||
} | ||
|
||
//fmt.Printf("MatchingIdx: %d\n", matchingIdx) | ||
//fmt.Printf("expectedPatckages[%d]: %+v\n", i, expectedPackages[i]) | ||
// if -1 != matchingIdx { | ||
// fmt.Printf("actualPackages[%d]: %+v\n", matchingIdx, actualPackages[matchingIdx]) | ||
// } else { | ||
// fmt.Printf("no match in actualPackages!\n") | ||
// } | ||
|
||
if -1 != matchingIdx { | ||
testPackageNameOnly := false | ||
if nil != expectedPkgsCollection.config.packageNameOnly { | ||
|
@@ -823,7 +816,7 @@ func (t *Test) comparePhpPackages(harvest *newrelic.Harvest) { | |
} | ||
|
||
// create notes for all packages in the actual list not in the expected list | ||
for ii, _ := range actualPackages { | ||
bduranleau-nr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for ii := range actualPackages { | ||
zsistla marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var found bool = false | ||
for _, pkg := range expectedPackages { | ||
if pkg.Name == actualPackages[ii].Name { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,78 +7,146 @@ package newrelic | |
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/newrelic/newrelic-php-agent/daemon/internal/newrelic/log" | ||
) | ||
|
||
type PhpPackagesKey struct { | ||
Name string | ||
Version string | ||
} | ||
|
||
// phpPackages represents all detected packages reported by an agent. | ||
// PhpPackages represents all detected packages reported by an agent | ||
// for a harvest cycle, as well as the filtered list of packages not | ||
// yet seen by the daemon for the lifecycle of the current daemon | ||
// process to be reported to the backend. | ||
type PhpPackages struct { | ||
numSeen int | ||
data JSONString | ||
numSeen int | ||
data map[PhpPackagesKey]struct{} | ||
filteredPkgs []PhpPackagesKey | ||
} | ||
|
||
// NumSeen returns the total number PHP packages payloads stored. | ||
// Should always be 0 or 1. The agent reports all the PHP | ||
// packages as a single JSON string. | ||
// NumSaved returns whether PHP packages payloads are stored by | ||
// the daemon for the current harvest. Should always be 0 or 1. | ||
// The agent reports all the PHP packages as a single JSON string. | ||
func (packages *PhpPackages) NumSaved() float64 { | ||
return float64(packages.numSeen) | ||
} | ||
|
||
// newPhpPackages returns a new PhpPackages struct. | ||
// NewPhpPackages returns a new PhpPackages struct. | ||
func NewPhpPackages() *PhpPackages { | ||
p := &PhpPackages{ | ||
numSeen: 0, | ||
data: nil, | ||
numSeen: 0, | ||
data: make(map[PhpPackagesKey]struct{}), | ||
filteredPkgs: nil, | ||
} | ||
|
||
return p | ||
} | ||
|
||
// SetPhpPackages sets the observed package list. | ||
func (packages *PhpPackages) SetPhpPackages(data []byte) error { | ||
// Filter seen php packages data to avoid sending duplicates | ||
// | ||
// the `App` structure contains a map of PHP Packages the reporting | ||
// application has encountered. | ||
// | ||
// the map of packages should persist for the duration of the | ||
// current connection | ||
// | ||
// the JSON format received from the agent is: | ||
// | ||
// [["package_name","version",{}],...] | ||
// | ||
// for each entry, assign the package name and version to the `PhpPackagesKey` | ||
// struct and use the key to verify data does not exist in the map. If the | ||
// key does not exist, add it to the map and the slice of filteredPkgs to be | ||
zsistla marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// sent in the current harvest. | ||
func (packages *PhpPackages) Filter(pkgHistory map[PhpPackagesKey]struct{}) { | ||
if packages == nil || len(packages.data) == 0 { | ||
return | ||
} | ||
|
||
if nil == packages { | ||
return fmt.Errorf("packages is nil!") | ||
for pkgKey := range packages.data { | ||
_, ok := pkgHistory[pkgKey] | ||
if !ok { | ||
pkgHistory[pkgKey] = struct{}{} | ||
zsistla marked this conversation as resolved.
Show resolved
Hide resolved
zsistla marked this conversation as resolved.
Show resolved
Hide resolved
|
||
packages.filteredPkgs = append(packages.filteredPkgs, pkgKey) | ||
} | ||
} | ||
if nil != packages.data { | ||
log.Debugf("SetPhpPackages - data field was not nil |^%s| - overwriting data", packages.data) | ||
} | ||
|
||
// AddPhpPackagesFromData observes the PHP packages info from the agent. | ||
func (packages *PhpPackages) AddPhpPackagesFromData(data []byte) error { | ||
if packages == nil { | ||
return fmt.Errorf("packages is nil") | ||
} | ||
if nil == data { | ||
return fmt.Errorf("data is nil!") | ||
if len(data) == 0 { | ||
return fmt.Errorf("data is nil") | ||
} | ||
|
||
var x []any | ||
|
||
err := json.Unmarshal(data, &x) | ||
if err != nil { | ||
return fmt.Errorf("failed to unmarshal php package json: %s", err.Error()) | ||
} | ||
|
||
for _, pkgJSON := range x { | ||
pkg, _ := pkgJSON.([]any) | ||
if len(pkg) != 3 { | ||
return fmt.Errorf("invalid php package json structure: %+v", pkg) | ||
} | ||
|
||
name, ok := pkg[0].(string) | ||
if !ok || len(name) == 0 { | ||
return fmt.Errorf("unable to parse package name") | ||
} | ||
|
||
version, ok := pkg[1].(string) | ||
if !ok || len(version) == 0 { | ||
zsistla marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return fmt.Errorf("unable to parse package version") | ||
} | ||
|
||
pkgKey := PhpPackagesKey{name, version} | ||
_, ok = packages.data[pkgKey] | ||
if !ok { | ||
packages.data[pkgKey] = struct{}{} | ||
} | ||
} | ||
|
||
packages.numSeen = 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what this field does any more - but if we keep it should it be incremented by the number of packages created in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm also interested in how this gets resolved. See related comment: https://github.com/newrelic/newrelic-php-agent/pull/1103/files#r2261468915 |
||
packages.data = data | ||
|
||
return nil | ||
} | ||
|
||
// AddPhpPackagesFromData observes the PHP packages info from the agent. | ||
func (packages *PhpPackages) AddPhpPackagesFromData(data []byte) error { | ||
return packages.SetPhpPackages(data) | ||
} | ||
|
||
// CollectorJSON marshals events to JSON according to the schema expected | ||
// by the collector. | ||
func (packages *PhpPackages) CollectorJSON(id AgentRunID) ([]byte, error) { | ||
if packages.Empty() { | ||
return []byte(`["Jars",[]]`), nil | ||
} | ||
|
||
buf := &bytes.Buffer{} | ||
var buf bytes.Buffer | ||
|
||
estimate := 512 | ||
buf.Grow(estimate) | ||
buf.WriteByte('[') | ||
buf.WriteString("\"Jars\",") | ||
zsistla marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if 0 < packages.numSeen { | ||
buf.Write(packages.data) | ||
buf.WriteString(`"Jars",`) | ||
if len(packages.filteredPkgs) > 0 { | ||
buf.WriteByte('[') | ||
for _, pkg := range packages.filteredPkgs { | ||
buf.WriteString(`["`) | ||
buf.WriteString(pkg.Name) | ||
buf.WriteString(`","`) | ||
buf.WriteString(pkg.Version) | ||
buf.WriteString(`",{}],`) | ||
} | ||
|
||
// swap last ',' character with ']' | ||
buf.Truncate(buf.Len() - 1) | ||
buf.WriteByte(']') | ||
} else { | ||
buf.WriteString("[]") | ||
} | ||
buf.WriteByte(']') | ||
|
||
|
@@ -94,7 +162,7 @@ func (packages *PhpPackages) FailedHarvest(newHarvest *Harvest) { | |
|
||
// Empty returns true if the collection is empty. | ||
func (packages *PhpPackages) Empty() bool { | ||
return nil == packages || nil == packages.data || 0 == packages.numSeen | ||
return nil == packages || len(packages.data) == 0 || 0 == packages.numSeen | ||
} | ||
|
||
// Data marshals the collection to JSON according to the schema expected | ||
|
Uh oh!
There was an error while loading. Please reload this page.