From 85c6ca0e5f97ef744364892b42fc8cdb941af302 Mon Sep 17 00:00:00 2001 From: gillespi314 <73313222+gillespi314@users.noreply.github.com> Date: Wed, 25 May 2022 10:54:56 -0500 Subject: [PATCH] Improve precision in reporting of unseen hosts via host status webhook automations (#5889) --- changes/issue-5614-timestamp | 1 + server/datastore/mysql/hosts.go | 9 +++++++-- server/datastore/mysql/hosts_test.go | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 changes/issue-5614-timestamp diff --git a/changes/issue-5614-timestamp b/changes/issue-5614-timestamp new file mode 100644 index 0000000000..71cbe9f904 --- /dev/null +++ b/changes/issue-5614-timestamp @@ -0,0 +1 @@ +- Switched from `DATEDIFF` to `TIMESTAMPDIFF` to improve precision when calculating unseen hosts reported by host status webhook diff --git a/server/datastore/mysql/hosts.go b/server/datastore/mysql/hosts.go index eb53ed851b..124dc21c91 100644 --- a/server/datastore/mysql/hosts.go +++ b/server/datastore/mysql/hosts.go @@ -981,15 +981,20 @@ func (ds *Datastore) TotalAndUnseenHostsSince(ctx context.Context, daysCount int Total int `db:"total"` Unseen int `db:"unseen"` } + + // convert daysCount to integer number of seconds for more precision in sql query + unseenSeconds := daysCount * 24 * 60 * 60 + err = sqlx.GetContext(ctx, ds.reader, &counts, `SELECT COUNT(*) as total, - SUM(IF(DATEDIFF(CURRENT_DATE, COALESCE(hst.seen_time, h.created_at)) >= ?, 1, 0)) as unseen + SUM(IF(TIMESTAMPDIFF(SECOND, COALESCE(hst.seen_time, h.created_at), CURRENT_TIMESTAMP) >= ?, 1, 0)) as unseen FROM hosts h LEFT JOIN host_seen_times hst ON h.id = hst.host_id`, - daysCount, + unseenSeconds, ) + if err != nil { return 0, 0, ctxerr.Wrap(ctx, err, "getting total and unseen host counts") } diff --git a/server/datastore/mysql/hosts_test.go b/server/datastore/mysql/hosts_test.go index 06f691578f..ec236a5ea0 100644 --- a/server/datastore/mysql/hosts_test.go +++ b/server/datastore/mysql/hosts_test.go @@ -1815,6 +1815,24 @@ func testHostsTotalAndUnseenSince(t *testing.T, ds *Datastore) { require.NoError(t, err) assert.Equal(t, 3, total) assert.Equal(t, 2, unseen) + + // host not counted as unseen if less than a full 24 hours has passed + _, err = ds.writer.ExecContext(context.Background(), `UPDATE host_seen_times SET seen_time = ? WHERE host_id = 2`, time.Now().Add(-1*time.Duration(1)*86399*time.Second)) + require.NoError(t, err) + + total, unseen, err = ds.TotalAndUnseenHostsSince(context.Background(), 1) + require.NoError(t, err) + assert.Equal(t, 3, total) + assert.Equal(t, 1, unseen) + + // host counted as unseen if more than 24 hours has passed + _, err = ds.writer.ExecContext(context.Background(), `UPDATE host_seen_times SET seen_time = ? WHERE host_id = 2`, time.Now().Add(-1*time.Duration(1)*86401*time.Second)) + require.NoError(t, err) + + total, unseen, err = ds.TotalAndUnseenHostsSince(context.Background(), 1) + require.NoError(t, err) + assert.Equal(t, 3, total) + assert.Equal(t, 2, unseen) } func testHostsListByPolicy(t *testing.T, ds *Datastore) {