Update new sched query stats if there's already some (#1918)

* Update new sched query stats if there's already some

* IGNORE if the sched query is not present

* Make tests less flaky
This commit is contained in:
Tomas Touceda
2021-09-02 17:39:08 -03:00
committed by GitHub
parent df135f57a9
commit db2e04a7c3
4 changed files with 164 additions and 4 deletions
+1
View File
@@ -0,0 +1 @@
* Properly record scheduled query statistics after the first recording.
+12 -1
View File
@@ -209,7 +209,18 @@ func (d *Datastore) saveHostPackStats(host *fleet.Host) error {
user_time,
wall_time
)
VALUES %s
VALUES %s ON DUPLICATE KEY UPDATE
scheduled_query_id = VALUES(scheduled_query_id),
host_id = VALUES(host_id),
average_memory = VALUES(average_memory),
denylisted = VALUES(denylisted),
executions = VALUES(executions),
schedule_interval = VALUES(schedule_interval),
last_executed = VALUES(last_executed),
output_size = VALUES(output_size),
system_time = VALUES(system_time),
user_time = VALUES(user_time),
wall_time = VALUES(wall_time)
`, values)
if _, err := tx.Exec(sql, args...); err != nil {
return errors.Wrap(err, "insert pack stats")
+146
View File
@@ -249,6 +249,152 @@ func TestSaveHostPackStats(t *testing.T) {
require.Len(t, host.PackStats, 2)
}
func TestSaveHostPackStatsOverwrites(t *testing.T) {
ds := CreateMySQLDS(t)
defer ds.Close()
host, err := ds.NewHost(&fleet.Host{
DetailUpdatedAt: time.Now(),
LabelUpdatedAt: time.Now(),
SeenTime: time.Now(),
NodeKey: "1",
UUID: "1",
Hostname: "foo.local",
PrimaryIP: "192.168.1.1",
PrimaryMac: "30-65-EC-6F-C4-58",
})
require.NoError(t, err)
require.NotNil(t, host)
// Pack and query must exist for stats to save successfully
pack1 := test.NewPack(t, ds, "test1")
query1 := test.NewQuery(t, ds, "time", "select * from time", 0, true)
squery1 := test.NewScheduledQuery(t, ds, pack1.ID, query1.ID, 30, true, true, "time-scheduled")
pack2 := test.NewPack(t, ds, "test2")
squery2 := test.NewScheduledQuery(t, ds, pack2.ID, query1.ID, 30, true, true, "time-scheduled")
query2 := test.NewQuery(t, ds, "processes", "select * from processes", 0, true)
execTime1 := time.Unix(1620325191, 0).UTC()
host.PackStats = []fleet.PackStats{
{
PackName: "test1",
QueryStats: []fleet.ScheduledQueryStats{
{
ScheduledQueryName: squery1.Name,
ScheduledQueryID: squery1.ID,
QueryName: query1.Name,
PackName: pack1.Name,
PackID: pack1.ID,
AverageMemory: 8000,
Denylisted: false,
Executions: 164,
Interval: 30,
LastExecuted: execTime1,
OutputSize: 1337,
SystemTime: 150,
UserTime: 180,
WallTime: 0,
},
},
},
{
PackName: "test2",
QueryStats: []fleet.ScheduledQueryStats{
{
ScheduledQueryName: squery2.Name,
ScheduledQueryID: squery2.ID,
QueryName: query2.Name,
PackName: pack2.Name,
PackID: pack2.ID,
AverageMemory: 431,
Denylisted: true,
Executions: 1,
Interval: 30,
LastExecuted: execTime1,
OutputSize: 134,
SystemTime: 1656,
UserTime: 18453,
WallTime: 10,
},
},
},
}
require.NoError(t, ds.SaveHost(host))
host, err = ds.Host(host.ID)
require.NoError(t, err)
sort.Slice(host.PackStats, func(i, j int) bool {
return host.PackStats[i].PackName < host.PackStats[j].PackName
})
require.Len(t, host.PackStats, 2)
assert.Equal(t, host.PackStats[0].PackName, "test1")
assert.Equal(t, execTime1, host.PackStats[0].QueryStats[0].LastExecuted)
execTime2 := execTime1.Add(24 * time.Hour)
host.PackStats = []fleet.PackStats{
{
PackName: "test1",
QueryStats: []fleet.ScheduledQueryStats{
{
ScheduledQueryName: squery1.Name,
ScheduledQueryID: squery1.ID,
QueryName: query1.Name,
PackName: pack1.Name,
PackID: pack1.ID,
AverageMemory: 8000,
Denylisted: false,
Executions: 164,
Interval: 30,
LastExecuted: execTime2,
OutputSize: 1337,
SystemTime: 150,
UserTime: 180,
WallTime: 0,
},
},
},
{
PackName: "test2",
QueryStats: []fleet.ScheduledQueryStats{
{
ScheduledQueryName: squery2.Name,
ScheduledQueryID: squery2.ID,
QueryName: query2.Name,
PackName: pack2.Name,
PackID: pack2.ID,
AverageMemory: 431,
Denylisted: true,
Executions: 1,
Interval: 30,
LastExecuted: execTime1,
OutputSize: 134,
SystemTime: 1656,
UserTime: 18453,
WallTime: 10,
},
},
},
}
require.NoError(t, ds.SaveHost(host))
gotHost, err := ds.Host(host.ID)
require.NoError(t, err)
sort.Slice(gotHost.PackStats, func(i, j int) bool {
return gotHost.PackStats[i].PackName < gotHost.PackStats[j].PackName
})
require.Len(t, gotHost.PackStats, 2)
assert.Equal(t, gotHost.PackStats[0].PackName, "test1")
assert.Equal(t, execTime2, gotHost.PackStats[0].QueryStats[0].LastExecuted)
}
func TestIgnoresTeamPackStats(t *testing.T) {
ds := CreateMySQLDS(t)
defer ds.Close()
+5 -3
View File
@@ -3,6 +3,7 @@ package mysql
import (
"fmt"
"math/rand"
"sort"
"strings"
"testing"
"time"
@@ -310,6 +311,7 @@ func TestLoadSupportsTonsOfCVEs(t *testing.T) {
require.NoError(t, ds.SaveHostSoftware(host))
require.NoError(t, ds.LoadHostSoftware(host))
sort.Slice(host.Software, func(i, j int) bool { return host.Software[i].Name < host.Software[j].Name })
require.NoError(t, ds.AddCPEForSoftware(host.Software[0], "somecpe"))
require.NoError(t, ds.AddCPEForSoftware(host.Software[1], "someothercpewithoutvulns"))
for i := 0; i < 1000; i++ {
@@ -324,7 +326,7 @@ func TestLoadSupportsTonsOfCVEs(t *testing.T) {
for _, software := range host.Software {
switch software.Name {
case "foo":
case "bar":
assert.Equal(t, "somecpe", software.GenerateCPE)
require.Len(t, software.Vulnerabilities, 1000)
assert.True(t, strings.HasPrefix(software.Vulnerabilities[0].CVE, "cve-"))
@@ -332,10 +334,10 @@ func TestLoadSupportsTonsOfCVEs(t *testing.T) {
"https://nvd.nist.gov/vuln/detail/"+software.Vulnerabilities[0].CVE,
software.Vulnerabilities[0].DetailsLink,
)
case "bar":
case "blah":
assert.Len(t, software.Vulnerabilities, 0)
assert.Equal(t, "someothercpewithoutvulns", software.GenerateCPE)
case "blah":
case "foo":
assert.Len(t, software.Vulnerabilities, 0)
}
}