From 0336860a9d62ef42a813dd669f0e3ad3605d45a5 Mon Sep 17 00:00:00 2001 From: mrfry Date: Thu, 25 Feb 2021 10:19:35 +0100 Subject: [PATCH] server stats in javascript --- scripts/serverStats.js | 286 ++++++++++++++++++++++++++++++++++------- 1 file changed, 237 insertions(+), 49 deletions(-) diff --git a/scripts/serverStats.js b/scripts/serverStats.js index f1b1e1f..afeeed9 100644 --- a/scripts/serverStats.js +++ b/scripts/serverStats.js @@ -2,15 +2,61 @@ // CONFIG // ----------------------------------------------------------------- -const maxStatLength = 15 +const cols = process.stdout.columns +// const rows = process.stdout.rows +const maxStatLength = Math.floor(cols / 4) const statNameSpacing = 5 +const beforeRowSpace = 13 const coloredWords = { - red: ['lred'], + red: ['lred', 'thanks'], + cyan: [ + 'getveteranpw', + 'pwrequest', + 'getpw', + 'availablepws', + 'login', + 'logout', + ], + green: [ + 'manual', + 'todos', + 'allquestions', + 'subjectbrowser', + 'contribute', + 'feedback', + 'ranklist', + 'allqr', + 'possibleAnswers', + ], + blue: ['isadding', 'ask'], + magenta: [ + 'donate', + 'tiszai', + 'install', + 'irc', + 'discord', + 'postfeedback', + 'votetodo', + 'registerscript', + 'quickvote', + ], } +const filterFromDailyStats = [ + 'savedQuestions', + 'sio/f', + 'sound/', + '/img/', + '.php', + 'favicon', + 'robots.txt', + 'ads.txt', + '/f/', + '.git', +] // ----------------------------------------------------------------- -const fs = require('fs') +const fs = require('fs') // eslint-disable-line const dir = process.argv[2] if (!dir) { @@ -23,19 +69,29 @@ function getDayIndex(offset) { offset = 0 } - let date = new Date() + const date = new Date() if (offset) { date.setDate(date.getDate() + offset) } return ( date.getFullYear() + - '/' + + '-' + ('0' + (date.getMonth() + 1)).slice(-2) + - '/' + + '-' + ('0' + date.getDate()).slice(-2) ) } +function hr(char) { + console.log(C('blue') + getLetterNTimes(char || '-', cols) + C()) +} + +function printHeader(text) { + hr() + console.log(C('green') + text + C()) + hr() +} + function C(color) { if (color !== undefined) { color = color.toLowerCase() @@ -73,7 +129,7 @@ function readJSON(name) { } function tail(text, number) { - let splitedText = text.split('\n') + const splitedText = text.split('\n') return splitedText.slice(Math.max(splitedText.length - number, 1)).join('\n') } @@ -84,6 +140,16 @@ function head(text, number) { .join('\n') } +function countLinesMatching(text, toMatch) { + let count = 0 + text.split('\n').forEach((line) => { + if (line.includes(toMatch.toLowerCase())) { + count++ + } + }) + return count +} + function readFile(name) { return fs.readFileSync(name, 'utf8') } @@ -96,99 +162,196 @@ function getLetterNTimes(letter, number) { return res } -function pCols() { - // console.log(arguments) +function pCols(cols, rowTitles, colorNames, firstRowColor, showDiff) { + // console.log(cols) let maxLength = 0 - Object.keys(arguments).forEach((key) => { - if (arguments[key].length > maxLength) { - maxLength = arguments[key].length + Object.keys(cols).forEach((key) => { + if (cols[key].length > maxLength) { + maxLength = cols[key].length } }) for (let i = 0; i < maxLength; i++) { - let row = [] - Object.keys(arguments) + const row = [] + const lastItems = [] + Object.keys(cols) .reverse() .forEach((key) => { - const val = arguments[key] + const val = cols[key] if (!val[i]) { return } - const keyName = val[i].name || '' + lastItems.push(val[i]) + const keyName = val[i].name || val[i] let slicedName = keyName.slice(0, maxStatLength) - let toColor = Object.keys(coloredWords).reduce((acc, key) => { - const colorArray = coloredWords[key] + const toColor = colorNames + ? Object.keys(coloredWords).reduce((acc, key) => { + const colorArray = coloredWords[key] - const includes = colorArray.some((colorableIdName) => { - return keyName.includes(colorableIdName) - }) + const includes = colorArray.some((colorableIdName) => { + return keyName + .toLowerCase() + .includes(colorableIdName.toLowerCase()) + }) - if (includes) { - return key - } + if (includes) { + return key + } - return acc - }, '') + return acc + }, '') + : false + + const sep = (i + 1) % 5 === 0 ? '.' : ' ' while (slicedName.length < maxStatLength) { - slicedName = ' ' + slicedName + slicedName = slicedName + sep } - let ammount = val[i].val ? val[i].val.toString() : 0 + let ammount = val[i].val ? val[i].val.toString() : '' while (ammount.length < 4) { ammount = ammount + ' ' } if (toColor) { - row.push(C(toColor) + slicedName + ': ' + ammount + C()) + row.push(C(toColor) + slicedName + ' ' + ammount + C()) } else { row.push(slicedName + ' ' + ammount) } }) - console.log(row.join(getLetterNTimes(' ', statNameSpacing))) + + // ROW TITLE --------------------------------------------------- + let currRowTitle = + rowTitles && rowTitles[i] + ? rowTitles[i] + : getLetterNTimes(' ', beforeRowSpace) + + while (currRowTitle.length < beforeRowSpace) { + currRowTitle = currRowTitle + ' ' + } + currRowTitle = C('blue') + currRowTitle + C() + // COLORING ---------------------------------------------------- + let res = '' + if (firstRowColor && i === 0) { + res = + currRowTitle + + C('green') + + row.join(getLetterNTimes(' ', statNameSpacing)) + + C() + } else { + res = currRowTitle + row.join(getLetterNTimes(' ', statNameSpacing)) + } + // SHOW DIFF --------------------------------------------------- + if (showDiff && i !== 0) { + let diff = + lastItems[lastItems.length - 1] - lastItems[lastItems.length - 2] + if (diff > 0) { + diff = '+' + diff.toString() + } + res += C('blue') + diff + C() + } + + console.log(res) } } // ------------------------------------------------------------------------------ +printHeader('Daily stats') + const dailyStats = readJSON(`${dir}stats/vstats`) function preProcessDailyStats(obj) { - return Object.keys(obj).map((key) => { - return { name: key, val: obj[key] } + const formatted = Object.keys(obj).reduce((acc, key) => { + const includes = filterFromDailyStats.some((keyword) => { + return key.toLowerCase().includes(keyword.toLowerCase()) + }) + if (!includes) { + acc.push({ name: key, val: obj[key] }) + } + return acc + }, []) + return formatted.sort((a, b) => { + if (a.name > b.name) { + return 1 + } else if (a.name < b.name) { + return -1 + } else { + return 0 + } }) } pCols( - preProcessDailyStats(dailyStats[getDayIndex()]), - preProcessDailyStats(dailyStats[getDayIndex(-1)]), - preProcessDailyStats(dailyStats[getDayIndex(-2)]) + [ + preProcessDailyStats(dailyStats[getDayIndex()]), + preProcessDailyStats(dailyStats[getDayIndex(-1)]), + preProcessDailyStats(dailyStats[getDayIndex(-2)]), + ], + null, + true ) // ------------------------------------------------------------------------------ +printHeader('User id test solving') const userIdTestSolving = readJSON(`${dir}stats/idvstats`) -function preProcessUIdTestSolving(obj) { +function preProcessUIdTestSolving(obj, minLength) { if (!obj) { - return [{ val: 0 }] + return '0' + } + if (minLength) { + return Object.keys(obj) + .filter((key) => { + return obj[key] > minLength + }) + .length.toString() + } else { + return Object.keys(obj).length.toString() } - return [{ val: Object.keys(obj).length }] } pCols( - preProcessUIdTestSolving(userIdTestSolving[getDayIndex()]), - preProcessUIdTestSolving(userIdTestSolving[getDayIndex(-1)]), - preProcessUIdTestSolving(userIdTestSolving[getDayIndex(-2)]) + [ + ['Today', preProcessUIdTestSolving(userIdTestSolving[getDayIndex()])], + ['Yesterday', preProcessUIdTestSolving(userIdTestSolving[getDayIndex(-1)])], + [ + 'Before yesterday', + preProcessUIdTestSolving(userIdTestSolving[getDayIndex(-2)]), + ], + ], + null, + false, + 'green' ) // ------------------------------------------------------------------------------ +printHeader('User id requests') const clientIdTestSolving = readJSON(`${dir}stats/uvstats`) pCols( - preProcessUIdTestSolving(clientIdTestSolving[getDayIndex()]), - preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-1)]), - preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-2)]) + [ + [ + 'Today', + preProcessUIdTestSolving(clientIdTestSolving[getDayIndex()]), + preProcessUIdTestSolving(clientIdTestSolving[getDayIndex()], 2), + ], + [ + 'Yesterday', + preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-1)]), + preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-1)], 2), + ], + [ + 'Before Yesterday', + preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-2)]), + preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-2)], 2), + ], + ], + ['', 'All', 'More than 2'], + false, + 'green' ) // ------------------------------------------------------------------------------ +printHeader('Daily data count') const dailyDataCount = readFile(`${dir}stats/dailyDataCount`) printLastDataCount([ @@ -198,12 +361,37 @@ printLastDataCount([ ]) function printLastDataCount(data) { - const res = [[], [], []] + const res = [['Today'], ['Yesterday'], ['Before yesterday']] data.forEach((dataCount, i) => { - res[i].push({ val: dataCount.userCount }) - res[i].push({ val: dataCount.subjectCount }) - res[i].push({ val: dataCount.questionCount }) + res[i].push(dataCount.userCount.toString()) + res[i].push(dataCount.subjectCount.toString()) + res[i].push(dataCount.questionCount.toString()) }) - pCols(...res) + pCols(res, ['', 'Users', 'Subjects', 'Questions'], false, 'green', true) } +// ------------------------------------------------------------------------------ +printHeader('Daily script install / update check count') +const todaysLogs = readFile(`${dir}stats/vlogs/${getDayIndex()}`) +const yesterdaysLogs = readFile(`${dir}stats/vlogs/${getDayIndex(-1)}`) +const beforeYesterdaysLogs = readFile(`${dir}stats/vlogs/${getDayIndex(-2)}`) + +const installs = [ + [ + 'Today', + countLinesMatching(todaysLogs, '?install').toString(), + countLinesMatching(todaysLogs, '?up').toString(), + ], + [ + 'Yesterday', + countLinesMatching(yesterdaysLogs, '?install').toString(), + countLinesMatching(yesterdaysLogs, '?up').toString(), + ], + [ + 'Before yesterday', + countLinesMatching(beforeYesterdaysLogs, '?install').toString(), + countLinesMatching(beforeYesterdaysLogs, '?up').toString(), + ], +] + +pCols(installs, ['', 'Installs', 'Updates'], false, 'green')