API route for returning tracked analytics keys (#10019)

* feat: track metrics saved by NodeBB (and assoc. plugins), #9949

* feat: route to retrieve analytics keys, closes #9949
isekai-main
Julian Lam 3 years ago committed by GitHub
parent 449366ca83
commit 5b42b6b369
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -142,6 +142,8 @@ paths:
$ref: 'write/flags/flagId/notes/datetime.yaml'
/admin/settings/{setting}:
$ref: 'write/admin/settings/setting.yaml'
/admin/analytics:
$ref: 'write/admin/analytics.yaml'
/admin/analytics/{set}:
$ref: 'write/admin/analytics/set.yaml'
/files/:

@ -0,0 +1,20 @@
get:
tags:
- admin
summary: get analytics keys
description: This operation returns the list metrics tracked by NodeBB. It is only accessible to administrators.
responses:
'200':
description: Analytics keys retrieved
content:
application/json:
schema:
type: object
properties:
status:
$ref: ../../components/schemas/Status.yaml#/Status
response:
type: object
properties:
keys:
type: array

@ -53,6 +53,8 @@ Analytics.increment = function (keys, callback) {
}
};
Analytics.getKeys = async () => db.getSortedSetRange('analyticsKeys', 0, -1);
Analytics.pageView = async function (payload) {
pageViews += 1;
@ -90,6 +92,17 @@ Analytics.writeData = async function () {
const month = new Date();
const dbQueue = [];
// Build list of metrics that were updated
let metrics = [
'pageviews',
'pageviews:month',
];
metrics.forEach((metric) => {
const toAdd = ['registered', 'guest', 'bot'].map(type => `${metric}:${type}`);
metrics = [...metrics, ...toAdd];
});
metrics.push('uniquevisitors');
today.setHours(today.getHours(), 0, 0, 0);
month.setMonth(month.getMonth(), 1);
month.setHours(0, 0, 0, 0);
@ -130,8 +143,13 @@ Analytics.writeData = async function () {
for (const [key, value] of Object.entries(counters)) {
dbQueue.push(db.sortedSetIncrBy(`analytics:${key}`, value, today.getTime()));
metrics.push(key);
delete counters[key];
}
// Update list of tracked metrics
dbQueue.push(db.sortedSetAdd('analyticsKeys', metrics.map(() => +Date.now()), metrics));
try {
await Promise.all(dbQueue);
} catch (err) {

@ -1,6 +1,5 @@
'use strict';
const user = require('../../user');
const meta = require('../../meta');
const privileges = require('../../privileges');
const analytics = require('../../analytics');
@ -20,13 +19,16 @@ Admin.updateSetting = async (req, res) => {
helpers.formatApiResponse(200, res);
};
Admin.getAnalytics = async (req, res) => {
const ok = await user.isAdministrator(req.uid);
Admin.getAnalyticsKeys = async (req, res) => {
let keys = await analytics.getKeys();
if (!ok) {
return helpers.formatApiResponse(403, res);
}
// Sort keys alphabetically
keys = keys.sort((a, b) => (a < b ? -1 : 1));
helpers.formatApiResponse(200, res, { keys });
};
Admin.getAnalyticsData = async (req, res) => {
// Default returns views from past 24 hours, by hour
if (!req.query.amount) {
if (req.query.units === 'days') {

@ -8,11 +8,12 @@ const routeHelpers = require('../helpers');
const { setupApiRoute } = routeHelpers;
module.exports = function () {
const middlewares = [middleware.ensureLoggedIn];
const middlewares = [middleware.ensureLoggedIn, middleware.admin.checkPrivileges];
setupApiRoute(router, 'put', '/settings/:setting', [...middlewares, middleware.checkRequired.bind(null, ['value'])], controllers.write.admin.updateSetting);
setupApiRoute(router, 'get', '/analytics/:set', [...middlewares], controllers.write.admin.getAnalytics);
setupApiRoute(router, 'get', '/analytics', [...middlewares], controllers.write.admin.getAnalyticsKeys);
setupApiRoute(router, 'get', '/analytics/:set', [...middlewares], controllers.write.admin.getAnalyticsData);
return router;
};

Loading…
Cancel
Save