diff --git a/lib/model/query/analytics.js b/lib/model/query/analytics.js index f980c7d9a..38e90390f 100644 --- a/lib/model/query/analytics.js +++ b/lib/model/query/analytics.js @@ -603,13 +603,18 @@ const previewMetrics = () => (({ Analytics }) => Promise.all([ return metrics; })); -// Get most recent 'analytics' audit from the past N days -const AUDIT_SCHEDULE = config.has('default.taskSchedule.analytics') +// Usage reports are sent on a fixed interval: a usage report is sent a fixed +// number of days after the previous report. The default is to send a report +// every 31 days. However, that number is configurable so that usage reporting +// can be verified during regression testing. +const ANALYTICS_SCHEDULE = config.has('default.taskSchedule.analytics') ? config.get('default.taskSchedule.analytics') - : 30; // Default is 30 days + : 31; // Default is 31 days +// Returns the latest recent attempt to send a usage report. If there is no +// recent attempt, then it is time for a new report to be sent. const getLatestAudit = () => ({ maybeOne }) => maybeOne(sql`select * from audits - where action='analytics' and "loggedAt" >= current_date - cast(${AUDIT_SCHEDULE} as int) + where action='analytics' and current_date - "loggedAt"::date < ${ANALYTICS_SCHEDULE} order by "loggedAt" desc limit 1`); module.exports = { diff --git a/test/integration/other/analytics-queries.js b/test/integration/other/analytics-queries.js index 6b6944ad0..96ce57534 100644 --- a/test/integration/other/analytics-queries.js +++ b/test/integration/other/analytics-queries.js @@ -1205,24 +1205,26 @@ describe('analytics task queries', () => { describe('latest analytics audit log utility', () => { it('should find recently created analytics audit log', testService(async (service, container) => { - // eslint-disable-next-line object-curly-spacing await container.Audits.log(null, 'analytics', null, { test: 'foo', success: true }); const res = await container.Analytics.getLatestAudit().then((o) => o.get()); res.details.test.should.equal('foo'); })); - it('should find nothing if no recent analytics audit log', testService(async (service, container) => { - // make all submissions so far in the distant past - //await container.all(sql`update submissions set "createdAt" = '1999-1-1' where true`); + it('should find nothing if no analytics audit log', testService(async (service, container) => { const res = await container.Analytics.getLatestAudit(); res.isEmpty().should.equal(true); })); + it('should find analytics audit log created 30 days ago', testService(async (service, container) => { + await container.Audits.log(null, 'analytics', null, { test: 'foo', success: true }); + await container.all(sql`update audits set "loggedAt" = current_timestamp - interval '30 days' where action = 'analytics'`); + const res = await container.Analytics.getLatestAudit(); + res.isDefined().should.equal(true); + })); + it('should not return analytics audit log more than 30 days prior', testService(async (service, container) => { - // eslint-disable-next-line object-curly-spacing await container.Audits.log(null, 'analytics', null, { test: 'foo', success: true }); - // make all analytics audits so far in the distant past - await container.all(sql`update audits set "loggedAt" = '1999-1-1' where action = 'analytics'`); + await container.all(sql`update audits set "loggedAt" = current_timestamp - interval '31 days' where action = 'analytics'`); const res = await container.Analytics.getLatestAudit(); res.isEmpty().should.equal(true); }));