2016-05-24 22:01:46 -04:00
|
|
|
'use strict';
|
|
|
|
|
|
2025-04-03 12:52:02 -04:00
|
|
|
const nconf = require('nconf');
|
2019-07-23 22:20:39 -04:00
|
|
|
const winston = require('winston');
|
|
|
|
|
const validator = require('validator');
|
|
|
|
|
const cronJob = require('cron').CronJob;
|
2025-04-18 21:57:12 -04:00
|
|
|
const { setTimeout } = require('timers/promises');
|
2016-05-24 22:01:46 -04:00
|
|
|
|
2019-07-23 22:20:39 -04:00
|
|
|
const db = require('../database');
|
|
|
|
|
const analytics = require('../analytics');
|
2025-04-03 12:52:02 -04:00
|
|
|
const pubsub = require('../pubsub');
|
|
|
|
|
const utils = require('../utils');
|
2016-05-24 22:01:46 -04:00
|
|
|
|
2019-07-23 22:20:39 -04:00
|
|
|
const Errors = module.exports;
|
2016-05-24 22:01:46 -04:00
|
|
|
|
2025-04-03 12:52:02 -04:00
|
|
|
const runJobs = nconf.get('runJobs');
|
|
|
|
|
|
2019-07-23 22:20:39 -04:00
|
|
|
let counters = {};
|
2025-04-03 12:52:02 -04:00
|
|
|
let total = {};
|
|
|
|
|
|
|
|
|
|
Errors.init = async function () {
|
|
|
|
|
new cronJob('0 * * * * *', async () => {
|
|
|
|
|
publishLocalErrors();
|
|
|
|
|
if (runJobs) {
|
|
|
|
|
await setTimeout(2000);
|
|
|
|
|
await Errors.writeData();
|
|
|
|
|
}
|
|
|
|
|
}, null, true);
|
2017-04-30 16:32:14 -04:00
|
|
|
|
2025-04-03 12:52:02 -04:00
|
|
|
if (runJobs) {
|
|
|
|
|
pubsub.on('errors:publish', (data) => {
|
|
|
|
|
for (const [key, value] of Object.entries(data.local)) {
|
|
|
|
|
if (utils.isNumber(value)) {
|
|
|
|
|
total[key] = total[key] || 0;
|
|
|
|
|
total[key] += value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function publishLocalErrors() {
|
|
|
|
|
pubsub.publish('errors:publish', {
|
|
|
|
|
local: counters,
|
|
|
|
|
});
|
|
|
|
|
counters = {};
|
|
|
|
|
}
|
2017-04-30 16:32:14 -04:00
|
|
|
|
2019-07-23 22:20:39 -04:00
|
|
|
Errors.writeData = async function () {
|
|
|
|
|
try {
|
2025-04-03 12:52:02 -04:00
|
|
|
const _counters = { ...total };
|
|
|
|
|
total = {};
|
2019-07-23 22:20:39 -04:00
|
|
|
const keys = Object.keys(_counters);
|
|
|
|
|
if (!keys.length) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-03 11:53:48 -04:00
|
|
|
const bulkIncrement = [];
|
2019-07-23 22:20:39 -04:00
|
|
|
for (const key of keys) {
|
2025-04-03 11:53:48 -04:00
|
|
|
bulkIncrement.push(['errors:404', _counters[key], key ]);
|
2019-07-23 22:20:39 -04:00
|
|
|
}
|
2025-04-03 11:53:48 -04:00
|
|
|
await db.sortedSetIncrByBulk(bulkIncrement);
|
2019-07-23 22:20:39 -04:00
|
|
|
} catch (err) {
|
2020-06-20 23:32:12 -04:00
|
|
|
winston.error(err.stack);
|
2017-05-29 12:14:55 -06:00
|
|
|
}
|
|
|
|
|
};
|
2017-04-30 16:32:14 -04:00
|
|
|
|
2019-07-23 22:20:39 -04:00
|
|
|
Errors.log404 = function (route) {
|
2017-05-29 12:14:55 -06:00
|
|
|
if (!route) {
|
2019-07-23 22:20:39 -04:00
|
|
|
return;
|
2017-05-29 12:14:55 -06:00
|
|
|
}
|
2021-11-18 16:42:18 -05:00
|
|
|
route = route.slice(0, 512).replace(/\/$/, ''); // remove trailing slashes
|
2017-05-29 12:14:55 -06:00
|
|
|
analytics.increment('errors:404');
|
|
|
|
|
counters[route] = counters[route] || 0;
|
|
|
|
|
counters[route] += 1;
|
|
|
|
|
};
|
2016-05-24 22:01:46 -04:00
|
|
|
|
2019-07-23 22:20:39 -04:00
|
|
|
Errors.get = async function (escape) {
|
|
|
|
|
const data = await db.getSortedSetRevRangeWithScores('errors:404', 0, 199);
|
2021-02-04 00:01:39 -07:00
|
|
|
data.forEach((nfObject) => {
|
2019-07-23 22:20:39 -04:00
|
|
|
nfObject.value = escape ? validator.escape(String(nfObject.value || '')) : nfObject.value;
|
|
|
|
|
});
|
|
|
|
|
return data;
|
2017-05-29 12:14:55 -06:00
|
|
|
};
|
2016-05-24 22:01:46 -04:00
|
|
|
|
2019-07-23 22:20:39 -04:00
|
|
|
Errors.clear = async function () {
|
|
|
|
|
await db.delete('errors:404');
|
2016-05-24 22:01:46 -04:00
|
|
|
};
|