openvibers/openvibe.report Commits
The shadow leaves today's still-counting day rows out (REP-2) (#92)
Changes
@@@ -7,6 +7,10 @@* The two sides are normalized with the same function the ingest uses (metricRowsFromStats), so an equal answer* compares equal; a changed number, a missing one or an extra stale one is a difference. Billing is not in the* shadow: Report quotes Billing directly and never keeps a second copy of money.++ *++ * Today's day rows are not compared: the day is still counting, and Network answers each window from its own cache,++ * so its 7-day and 90-day answers name different numbers for today, minutes apart; the one Report kept last is not++ * a difference (11-03: the only three left, today's pageviews, 340 against 346). Every finished day is compared.*/const crypto = require('crypto');const { metricRowsFromStats } = require('./ingest');@@@ -73,10 +77,12 @@ function createShadow({ store, network, now = () => Date.now(), log = console })network_json: networkJson, report_json: reportJson ? reportJson.value : null,});}++ const today = new Date(now()).toISOString().slice(0, 10);for (const key of keys) {const net = networkRows.find((r) => keyOf(r) === key) || null;const rep = reportByKey.get(key) || null;if (!net && !rep) continue;++ if ((net || rep).kind === 'day' && (net || rep).day === today) continue; // still counting (see above)// Only compare a stored number whose metric Network actually reports in this window; an unrelated// stored scope is not a shadow difference.if (!net && !netKeys.has(key) && !networkRows.some((r) => r.metric === (rep && rep.metric))) continue;@@@ -55,6 +55,20 @@ const { stats, NOW } = require('./fixtures/analytics');assert.strictEqual(await t.ctx.store.db.value(`SELECT value::int AS v FROM report_metric_windows WHERE metric = 'pageviews' AND scope = 'network' AND window_days = 7`), 307, 'and Report took it in');});++ await check('today is still counting: its day rows are not compared; a finished day still is', async () => {++ const days = stats.pageviews_daily.map((p) => p.day);++ const today = new Date(NOW).toISOString().slice(0, 10);++ assert.strictEqual(days[days.length - 1], today, 'the fixture ends today');++ const moved = JSON.parse(JSON.stringify(stats));++ moved.pageviews_daily[moved.pageviews_daily.length - 1].n += 6; // another window's later snapshot of today++ const same = await t.ctx.shadow.compare({ days: 7, stats: moved });++ assert.ok(!same.diffs.some((d) => d.day === today), JSON.stringify(same.diffs));++ const old = JSON.parse(JSON.stringify(stats));++ old.pageviews_daily[0].n += 1;++ const past = await t.ctx.shadow.compare({ days: 7, stats: old });++ assert.ok(past.diffs.some((d) => d.metric === 'pageviews' && d.day === days[0]), 'a finished day that differs is a difference');++ });++await check('a Network that does not answer is a run with no differences, never a clean claim', async () => {const down = await t.ctx.shadow.compare({ days: 7, stats: null });assert.strictEqual(down.status, 'network_unavailable');
@@ -7,6 +7,10 @@
@@ -7,6 +7,10 @@
* The two sides are normalized with the same function the ingest uses (metricRowsFromStats), so an equal answer
* The two sides are normalized with the same function the ingest uses (metricRowsFromStats), so an equal answer
* compares equal; a changed number, a missing one or an extra stale one is a difference. Billing is not in the
* compares equal; a changed number, a missing one or an extra stale one is a difference. Billing is not in the
* shadow: Report quotes Billing directly and never keeps a second copy of money.
* shadow: Report quotes Billing directly and never keeps a second copy of money.
+ *
+ * Today's day rows are not compared: the day is still counting, and Network answers each window from its own cache,
+ * so its 7-day and 90-day answers name different numbers for today, minutes apart; the one Report kept last is not
+ * a difference (11-03: the only three left, today's pageviews, 340 against 346). Every finished day is compared.
*/
*/
const crypto = require('crypto');
const crypto = require('crypto');
const { metricRowsFromStats } = require('./ingest');
const { metricRowsFromStats } = require('./ingest');
@@ -73,10 +77,12 @@ function createShadow({ store, network, now = () => Date.now(), log = console })
@@ -73,10 +77,12 @@ function createShadow({ store, network, now = () => Date.now(), log = console })
network_json: networkJson, report_json: reportJson ? reportJson.value : null,
network_json: networkJson, report_json: reportJson ? reportJson.value : null,
});
});
}
}
+ const today = new Date(now()).toISOString().slice(0, 10);
for (const key of keys) {
for (const key of keys) {
const net = networkRows.find((r) => keyOf(r) === key) || null;
const net = networkRows.find((r) => keyOf(r) === key) || null;
const rep = reportByKey.get(key) || null;
const rep = reportByKey.get(key) || null;
if (!net && !rep) continue;
if (!net && !rep) continue;
+ if ((net || rep).kind === 'day' && (net || rep).day === today) continue; // still counting (see above)
// Only compare a stored number whose metric Network actually reports in this window; an unrelated
// Only compare a stored number whose metric Network actually reports in this window; an unrelated
// stored scope is not a shadow difference.
// stored scope is not a shadow difference.
if (!net && !netKeys.has(key) && !networkRows.some((r) => r.metric === (rep && rep.metric))) continue;
if (!net && !netKeys.has(key) && !networkRows.some((r) => r.metric === (rep && rep.metric))) continue;
@@ -55,6 +55,20 @@ const { stats, NOW } = require('./fixtures/analytics');
@@ -55,6 +55,20 @@ const { stats, NOW } = require('./fixtures/analytics');
assert.strictEqual(await t.ctx.store.db.value(`SELECT value::int AS v FROM report_metric_windows WHERE metric = 'pageviews' AND scope = 'network' AND window_days = 7`), 307, 'and Report took it in');
assert.strictEqual(await t.ctx.store.db.value(`SELECT value::int AS v FROM report_metric_windows WHERE metric = 'pageviews' AND scope = 'network' AND window_days = 7`), 307, 'and Report took it in');
});
});
+ await check('today is still counting: its day rows are not compared; a finished day still is', async () => {
+ const days = stats.pageviews_daily.map((p) => p.day);
+ const today = new Date(NOW).toISOString().slice(0, 10);
+ assert.strictEqual(days[days.length - 1], today, 'the fixture ends today');
+ const moved = JSON.parse(JSON.stringify(stats));
+ moved.pageviews_daily[moved.pageviews_daily.length - 1].n += 6; // another window's later snapshot of today
+ const same = await t.ctx.shadow.compare({ days: 7, stats: moved });
+ assert.ok(!same.diffs.some((d) => d.day === today), JSON.stringify(same.diffs));
+ const old = JSON.parse(JSON.stringify(stats));
+ old.pageviews_daily[0].n += 1;
+ const past = await t.ctx.shadow.compare({ days: 7, stats: old });
+ assert.ok(past.diffs.some((d) => d.metric === 'pageviews' && d.day === days[0]), 'a finished day that differs is a difference');
+ });
+
await check('a Network that does not answer is a run with no differences, never a clean claim', async () => {
await check('a Network that does not answer is a run with no differences, never a clean claim', async () => {
const down = await t.ctx.shadow.compare({ days: 7, stats: null });
const down = await t.ctx.shadow.compare({ days: 7, stats: null });
assert.strictEqual(down.status, 'network_unavailable');
assert.strictEqual(down.status, 'network_unavailable');