Finally implement "Total Calls Today" MCI: TT
+ Add findSystemLogEntries() to StatLog amongst others
This commit is contained in:
parent
ec97b3e8d4
commit
f471fd0ebe
Binary file not shown.
|
@ -135,6 +135,7 @@
|
||||||
AN7: { width: 6 }
|
AN7: { width: 6 }
|
||||||
ND8: { width: 6 }
|
ND8: { width: 6 }
|
||||||
TC9: { width: 6 }
|
TC9: { width: 6 }
|
||||||
|
TT11: { width: 6 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
core/bbs.js
17
core/bbs.js
|
@ -12,6 +12,7 @@ const database = require('./database.js');
|
||||||
const resolvePath = require('./misc_util.js').resolvePath;
|
const resolvePath = require('./misc_util.js').resolvePath;
|
||||||
const UserProps = require('./user_property.js');
|
const UserProps = require('./user_property.js');
|
||||||
const SysProps = require('./system_property.js');
|
const SysProps = require('./system_property.js');
|
||||||
|
const SysLogKeys = require('./system_log.js');
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
|
@ -20,6 +21,7 @@ const _ = require('lodash');
|
||||||
const mkdirs = require('fs-extra').mkdirs;
|
const mkdirs = require('fs-extra').mkdirs;
|
||||||
const fs = require('graceful-fs');
|
const fs = require('graceful-fs');
|
||||||
const paths = require('path');
|
const paths = require('path');
|
||||||
|
const moment = require('moment');
|
||||||
|
|
||||||
// our main entry point
|
// our main entry point
|
||||||
exports.main = main;
|
exports.main = main;
|
||||||
|
@ -272,6 +274,21 @@ function initialize(cb) {
|
||||||
return callback(null);
|
return callback(null);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
function initCallsToday(callback) {
|
||||||
|
const StatLog = require('./stat_log.js');
|
||||||
|
const filter = {
|
||||||
|
logName : SysLogKeys.UserLoginHistory,
|
||||||
|
resultType : 'count',
|
||||||
|
date : moment(),
|
||||||
|
};
|
||||||
|
|
||||||
|
StatLog.findSystemLogEntries(filter, (err, callsToday) => {
|
||||||
|
if(!err) {
|
||||||
|
StatLog.setNonPersistentSystemStat(SysProps.LoginsToday, callsToday);
|
||||||
|
}
|
||||||
|
return callback(null);
|
||||||
|
});
|
||||||
|
},
|
||||||
function initMCI(callback) {
|
function initMCI(callback) {
|
||||||
return require('./predefined_mci.js').init(callback);
|
return require('./predefined_mci.js').init(callback);
|
||||||
},
|
},
|
||||||
|
|
|
@ -73,7 +73,7 @@ function getISOTimestampString(ts) {
|
||||||
}
|
}
|
||||||
ts = moment(ts);
|
ts = moment(ts);
|
||||||
}
|
}
|
||||||
return ts.utc().format('YYYY-MM-DDTHH:mm:ss.SSS[Z]');
|
return ts.format('YYYY-MM-DDTHH:mm:ss.SSS[Z]');
|
||||||
}
|
}
|
||||||
|
|
||||||
function sanatizeString(s) {
|
function sanatizeString(s) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ const { formatByteSize } = require('./string_util.js');
|
||||||
const ANSI = require('./ansi_term.js');
|
const ANSI = require('./ansi_term.js');
|
||||||
const UserProps = require('./user_property.js');
|
const UserProps = require('./user_property.js');
|
||||||
const SysProps = require('./system_property.js');
|
const SysProps = require('./system_property.js');
|
||||||
|
const SysLogKeys = require('./system_log.js');
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const packageJson = require('../package.json');
|
const packageJson = require('../package.json');
|
||||||
|
@ -30,7 +31,7 @@ function init(cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setNextRandomRumor(cb) {
|
function setNextRandomRumor(cb) {
|
||||||
StatLog.getSystemLogEntries('system_rumorz', StatLog.Order.Random, 1, (err, entry) => {
|
StatLog.getSystemLogEntries(SysLogKeys.UserAddedRumorz, StatLog.Order.Random, 1, (err, entry) => {
|
||||||
if(entry) {
|
if(entry) {
|
||||||
entry = entry[0];
|
entry = entry[0];
|
||||||
}
|
}
|
||||||
|
@ -191,6 +192,9 @@ const PREDEFINED_MCI_GENERATORS = {
|
||||||
AN : function activeNodes() { return clientConnections.getActiveConnections().length.toString(); },
|
AN : function activeNodes() { return clientConnections.getActiveConnections().length.toString(); },
|
||||||
|
|
||||||
TC : function totalCalls() { return StatLog.getSystemStat(SysProps.LoginCount).toLocaleString(); },
|
TC : function totalCalls() { return StatLog.getSystemStat(SysProps.LoginCount).toLocaleString(); },
|
||||||
|
TT : function totalCallsToday() {
|
||||||
|
return StatLog.getSystemStat(SysProps.LoginsToday).toLocaleString();
|
||||||
|
},
|
||||||
|
|
||||||
RR : function randomRumor() {
|
RR : function randomRumor() {
|
||||||
// start the process of picking another random one
|
// start the process of picking another random one
|
||||||
|
@ -227,7 +231,6 @@ const PREDEFINED_MCI_GENERATORS = {
|
||||||
// :TODO: PT - Messages posted *today* (Obv/2)
|
// :TODO: PT - Messages posted *today* (Obv/2)
|
||||||
// -> Include FTN/etc.
|
// -> Include FTN/etc.
|
||||||
// :TODO: NT - New users today (Obv/2)
|
// :TODO: NT - New users today (Obv/2)
|
||||||
// :TODO: CT - Calls *today* (Obv/2)
|
|
||||||
// :TODO: FT - Files uploaded/added *today* (Obv/2)
|
// :TODO: FT - Files uploaded/added *today* (Obv/2)
|
||||||
// :TODO: DD - Files downloaded *today* (iNiQUiTY)
|
// :TODO: DD - Files downloaded *today* (iNiQUiTY)
|
||||||
// :TODO: TP - total message/posts on the system (Obv/2)
|
// :TODO: TP - total message/posts on the system (Obv/2)
|
||||||
|
|
130
core/stat_log.js
130
core/stat_log.js
|
@ -5,9 +5,11 @@ const sysDb = require('./database.js').dbs.system;
|
||||||
const {
|
const {
|
||||||
getISOTimestampString
|
getISOTimestampString
|
||||||
} = require('./database.js');
|
} = require('./database.js');
|
||||||
|
const Errors = require('./enig_error.js');
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const moment = require('moment');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
System Event Log & Stats
|
System Event Log & Stats
|
||||||
|
@ -74,6 +76,19 @@ class StatLog {
|
||||||
this.systemStats[statName] = statValue;
|
this.systemStats[statName] = statValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
incrementNonPersistentSystemStat(statName, incrementBy) {
|
||||||
|
incrementBy = incrementBy || 1;
|
||||||
|
|
||||||
|
let newValue = parseInt(this.systemStats[statName]);
|
||||||
|
if(!isNaN(newValue)) {
|
||||||
|
newValue += incrementBy;
|
||||||
|
} else {
|
||||||
|
newValue = incrementBy;
|
||||||
|
}
|
||||||
|
this.setNonPersistentSystemStat(statName, newValue);
|
||||||
|
return newValue;
|
||||||
|
}
|
||||||
|
|
||||||
setSystemStat(statName, statValue, cb) {
|
setSystemStat(statName, statValue, cb) {
|
||||||
// live stats
|
// live stats
|
||||||
this.systemStats[statName] = statValue;
|
this.systemStats[statName] = statValue;
|
||||||
|
@ -99,19 +114,7 @@ class StatLog {
|
||||||
}
|
}
|
||||||
|
|
||||||
incrementSystemStat(statName, incrementBy, cb) {
|
incrementSystemStat(statName, incrementBy, cb) {
|
||||||
incrementBy = incrementBy || 1;
|
const newValue = this.incrementNonPersistentSystemStat(statName, incrementBy);
|
||||||
|
|
||||||
let newValue = parseInt(this.systemStats[statName]);
|
|
||||||
if(newValue) {
|
|
||||||
if(!_.isNumber(newValue)) {
|
|
||||||
return cb(new Error(`Value for ${statName} is not a number!`));
|
|
||||||
}
|
|
||||||
|
|
||||||
newValue += incrementBy;
|
|
||||||
} else {
|
|
||||||
newValue = incrementBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.setSystemStat(statName, newValue, cb);
|
return this.setSystemStat(statName, newValue, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,26 +219,78 @@ class StatLog {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSystemLogEntries(logName, order, limit, cb) {
|
/*
|
||||||
let sql =
|
Find System Log entries by |filter|:
|
||||||
`SELECT timestamp, log_value
|
|
||||||
FROM system_event_log
|
|
||||||
WHERE log_name = ?`;
|
|
||||||
|
|
||||||
switch(order) {
|
filter.logName (required)
|
||||||
case 'timestamp' :
|
filter.resultType = (obj) | count
|
||||||
case 'timestamp_asc' :
|
where obj contains timestamp and log_value
|
||||||
sql += ' ORDER BY timestamp ASC';
|
filter.limit
|
||||||
break;
|
filter.date - exact date to filter against
|
||||||
|
filter.order = (timestamp) | timestamp_asc | timestamp_desc | random
|
||||||
case 'timestamp_desc' :
|
*/
|
||||||
sql += ' ORDER BY timestamp DESC';
|
findSystemLogEntries(filter, cb) {
|
||||||
break;
|
filter = filter || {};
|
||||||
|
if(!_.isString(filter.logName)) {
|
||||||
case 'random' :
|
return cb(Errors.MissingParam('filter.logName is required'));
|
||||||
sql += ' ORDER BY RANDOM()';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filter.resultType = filter.resultType || 'obj';
|
||||||
|
filter.order = filter.order || 'timestamp';
|
||||||
|
|
||||||
|
let sql;
|
||||||
|
if('count' === filter.resultType) {
|
||||||
|
sql =
|
||||||
|
`SELECT COUNT() AS count
|
||||||
|
FROM system_event_log`;
|
||||||
|
} else {
|
||||||
|
sql =
|
||||||
|
`SELECT timestamp, log_value
|
||||||
|
FROM system_event_log`;
|
||||||
|
}
|
||||||
|
|
||||||
|
sql += ' WHERE log_name = ?';
|
||||||
|
|
||||||
|
if(filter.date) {
|
||||||
|
filter.date = moment(filter.date);
|
||||||
|
sql += ` AND DATE(timestamp) = DATE("${filter.date.format('YYYY-MM-DD')}")`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if('count' !== filter.resultType) {
|
||||||
|
switch(filter.order) {
|
||||||
|
case 'timestamp' :
|
||||||
|
case 'timestamp_asc' :
|
||||||
|
sql += ' ORDER BY timestamp ASC';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'timestamp_desc' :
|
||||||
|
sql += ' ORDER BY timestamp DESC';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'random' :
|
||||||
|
sql += ' ORDER BY RANDOM()';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_.isNumber(filter.limit) && 0 !== filter.limit) {
|
||||||
|
sql += ` LIMIT ${filter.limit}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
sql += ';';
|
||||||
|
|
||||||
|
if('count' === filter.resultType) {
|
||||||
|
sysDb.get(sql, [ filter.logName ], (err, row) => {
|
||||||
|
return cb(err, row ? row.count : 0);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sysDb.all(sql, [ filter.logName ], (err, rows) => {
|
||||||
|
return cb(err, rows);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getSystemLogEntries(logName, order, limit, cb) {
|
||||||
if(!cb && _.isFunction(limit)) {
|
if(!cb && _.isFunction(limit)) {
|
||||||
cb = limit;
|
cb = limit;
|
||||||
limit = 0;
|
limit = 0;
|
||||||
|
@ -243,15 +298,12 @@ class StatLog {
|
||||||
limit = limit || 0;
|
limit = limit || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(0 !== limit) {
|
const filter = {
|
||||||
sql += ` LIMIT ${limit}`;
|
logName,
|
||||||
}
|
order,
|
||||||
|
limit,
|
||||||
sql += ';';
|
};
|
||||||
|
return this.findSystemLogEntries(filter, cb);
|
||||||
sysDb.all(sql, [ logName ], (err, rows) => {
|
|
||||||
return cb(err, rows);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
appendUserLogEntry(user, logName, logValue, keepDays, cb) {
|
appendUserLogEntry(user, logName, logValue, keepDays, cb) {
|
||||||
|
|
|
@ -9,17 +9,20 @@
|
||||||
//
|
//
|
||||||
module.exports = {
|
module.exports = {
|
||||||
LoginCount : 'login_count',
|
LoginCount : 'login_count',
|
||||||
|
LoginsToday : 'logins_today', // non-persistent
|
||||||
|
|
||||||
FileBaseAreaStats : 'file_base_area_stats', // object - see file_base_area.js::getAreaStats
|
FileBaseAreaStats : 'file_base_area_stats', // object - see file_base_area.js::getAreaStats
|
||||||
FileUlTotalCount : 'ul_total_count',
|
FileUlTotalCount : 'ul_total_count',
|
||||||
FileUlTotalBytes : 'ul_total_bytes',
|
FileUlTotalBytes : 'ul_total_bytes',
|
||||||
|
|
||||||
|
// begin +op non-persistent...
|
||||||
SysOpUsername : 'sysop_username',
|
SysOpUsername : 'sysop_username',
|
||||||
SysOpRealName : 'sysop_real_name',
|
SysOpRealName : 'sysop_real_name',
|
||||||
SysOpLocation : 'sysop_location',
|
SysOpLocation : 'sysop_location',
|
||||||
SysOpAffiliations : 'sysop_affiliation',
|
SysOpAffiliations : 'sysop_affiliation',
|
||||||
SysOpSex : 'sysop_sex',
|
SysOpSex : 'sysop_sex',
|
||||||
SysOpEmailAddress : 'sysop_email_address',
|
SysOpEmailAddress : 'sysop_email_address',
|
||||||
|
// end +op non-persistent
|
||||||
|
|
||||||
NextRandomRumor : 'random_rumor',
|
NextRandomRumor : 'random_rumor',
|
||||||
};
|
};
|
||||||
|
|
|
@ -88,6 +88,7 @@ function userLogin(client, username, password, cb) {
|
||||||
return callback(null);
|
return callback(null);
|
||||||
},
|
},
|
||||||
function updateSystemLoginCount(callback) {
|
function updateSystemLoginCount(callback) {
|
||||||
|
StatLog.incrementNonPersistentSystemStat(SysProps.LoginsToday, 1);
|
||||||
return StatLog.incrementSystemStat(SysProps.LoginCount, 1, callback);
|
return StatLog.incrementSystemStat(SysProps.LoginCount, 1, callback);
|
||||||
},
|
},
|
||||||
function recordLastLogin(callback) {
|
function recordLastLogin(callback) {
|
||||||
|
|
|
@ -65,7 +65,8 @@ for a full listing. Many codes attempt to pay homage to Oblivion/2, iNiQUiTY, et
|
||||||
| `SC` | System CPU model |
|
| `SC` | System CPU model |
|
||||||
| `NV` | System underlying Node.js version |
|
| `NV` | System underlying Node.js version |
|
||||||
| `AN` | Current active node count |
|
| `AN` | Current active node count |
|
||||||
| `TC` | Total login/calls to system |
|
| `TC` | Total login/calls to the system *ever* |
|
||||||
|
| `TT` | Total login/calls to the system *today* |
|
||||||
| `RR` | Displays a random rumor |
|
| `RR` | Displays a random rumor |
|
||||||
| `SD` | Total downloads, system wide |
|
| `SD` | Total downloads, system wide |
|
||||||
| `SO` | Total downloaded amount, system wide (formatted to appropriate bytes/megs/etc.) |
|
| `SO` | Total downloaded amount, system wide (formatted to appropriate bytes/megs/etc.) |
|
||||||
|
|
Loading…
Reference in New Issue