New live stat: Total new users today

* Add NT (Obv/2 throwback) MCI for new users today
* Keep live stat up to date in stat log
* Exposed via WFC
This commit is contained in:
Bryan Ashby 2022-05-07 10:48:40 -06:00
parent bb86f386e9
commit 9e5b3369a5
No known key found for this signature in database
GPG Key ID: C2C1B501E4EFD994
13 changed files with 49 additions and 22 deletions

View File

@ -259,7 +259,7 @@
mainInfoFormat15: "|00|10{lastLoginUserName:<26} |02{lastLogin}"
mainInfoFormat16: ""
mainInfoFormat16: "|00|10{newUsersToday}"
mainInfoFormat17: "|00|10{freeMemoryBytes!sizeWithoutAbbr} |02{freeMemoryBytes!sizeAbbr} free |08/ |10{totalMemoryBytes!sizeWithoutAbbr} |02{totalMemoryBytes!sizeAbbr}"
mainInfoFormat18: "|00|10{systemCurrentLoad} |02% |08/ |10{systemAvgLoad} |02load avg|08."
@ -279,22 +279,30 @@
error: |00|12E
fatal: |00|28F
}
quickLogLevelMessagePrefixes: {
trace : |00|02
debug: |00|03
info: |00|07
warn: |00|14
error: |00|12
fatal: |00|28
}
}
0: {
mci: {
TL17: { width: 23 }
TL18: { width: 23 }
TL19: { width: 13 }
TL19: { width: 14 }
VM1: {
height: 5
widht: 37
width: 36
itemFormat: "|00|11{node:<3.2} |10{userName:>13} |08> |02{action:<14.13} |14{serverName}"
}
VM2: {
height: 5
width: 73
itemFormat: "{levelIndicator} |15{timestamp} |07{message:<51.50}"
itemFormat: "|00|07{nodeId} {levelIndicator} |02{timestamp} {message:<51.50}"
}
}
}

View File

@ -109,7 +109,7 @@ exports.getModule = class AbracadabraModule extends MenuModule {
name : self.config.name,
activeCount : activeDoorNodeInstances[self.config.name]
},
'Too many active instances');
`Too many active instances of door "${self.config.name}"`);
if(_.isString(self.config.tooManyArt)) {
theme.displayThemeArt( { client : self.client, name : self.config.tooManyArt }, function displayed() {

View File

@ -299,6 +299,7 @@ function initialize(cb) {
[ UserLogNames.UlFileBytes, [ SysProps.FileUlTodayBytes, 'obj' ] ],
[ UserLogNames.DlFiles, [ SysProps.FileDlTodayCount, 'count' ] ],
[ UserLogNames.DlFileBytes, [ SysProps.FileDlTodayBytes, 'obj' ] ],
[ UserLogNames.NewUser, [ SysProps.NewUsersTodayCount, 'count' ] ],
];
async.each(entries, (entry, nextEntry) => {
@ -310,8 +311,6 @@ function initialize(cb) {
date : moment(),
};
filter.logName = logName;
StatLog.findUserLogEntries(filter, (err, stat) => {
if (!err) {
if (resultType === 'obj') {

View File

@ -105,7 +105,7 @@ function addNewClient(client, clientSock) {
connInfo.family = clientSock.localFamily;
}
client.log.info(connInfo, 'Client connected');
client.log.info(connInfo, `Client connected (${connInfo.port}/${connInfo.serverName})`);
Events.emit(
Events.getSystemEvents().ClientConnected,

View File

@ -150,7 +150,7 @@ const ansiQuerySyncTermFontSupport = (client, cb) => {
const [_, w] = pos;
if (w === 1) {
// cursor didn't move
client.log.info('Client supports SyncTERM fonts or properly ignores unknown ESC sequence');
client.log.info('Enabling SyncTERM font support');
client.term.syncTermFontsEnabled = true;
}
},

View File

@ -108,7 +108,7 @@ class ScheduledEvent {
}
executeAction(reason, cb) {
Log.info( { eventName : this.name, action : this.action, reason : reason }, 'Executing scheduled event action...');
Log.info( { eventName : this.name, action : this.action, reason : reason }, `Executing scheduled event "${this.name}"...`);
if('method' === this.action.type) {
const modulePath = path.join(__dirname, '../', this.action.location); // enigma-bbs base + supplied location (path/file.js')

View File

@ -10,7 +10,12 @@ function dailyMaintenanceScheduledEvent(args, cb) {
//
// Various stats need reset daily
//
[ SysProps.LoginsToday, SysProps.MessagesToday ].forEach(prop => {
// :TODO: files/etc. here
const resetProps = [
SysProps.LoginsToday, SysProps.MessagesToday, SysProps.NewUsersTodayCount,
];
resetProps.forEach(prop => {
StatLog.setNonPersistentSystemStat(prop, 0);
});

View File

@ -299,8 +299,10 @@ const PREDEFINED_MCI_GENERATORS = {
const byteSize = StatLog.getSystemStatNum(SysProps.FileDlTodayBytes);
return formatByteSize(byteSize, true); // true=withAbbr
},
NT : function totalNewUsersToday() { // Obv/2
return StatLog.getSystemStatNum(SysProps.NewUsersTodayCount);
},
// :TODO: NT - New users today (Obv/2)
// :TODO: TZ - Average *system* post/call ratio (iNiQUiTY)
// :TODO: ?? - Total users on system

View File

@ -3,6 +3,7 @@
const Events = require('./events.js');
const LogNames = require('./user_log_name.js');
const SysProps = require('./system_property.js');
const DefaultKeepForDays = 365;
@ -26,6 +27,7 @@ module.exports = function systemEventUserLogInit(statLog) {
const detailHandler = {
[ systemEvents.NewUser ] : (e) => {
append(e, LogNames.NewUser, 1);
statLog.incrementNonPersistentSystemStat(SysProps.NewUsersTodayCount, 1);
},
[ systemEvents.UserLogin ] : (e) => {
append(e, LogNames.Login, 1);

View File

@ -39,4 +39,5 @@ module.exports = {
SystemLoadStats : 'system_load_stats', // object { average, current }; non-persistent
TotalUserCount : 'user_total_count', // non-persistent
NewUsersTodayCount : 'user_new_today_count', // non-persistent
};

View File

@ -86,7 +86,7 @@ function userLogin(client, username, password, options, cb) {
username : user.username,
userId : user.userId
},
'Already logged in'
`User ${user.username} already logged in`
);
return cb(Errors.BadLogin(
@ -104,7 +104,7 @@ function userLogin(client, username, password, options, cb) {
}
);
client.log.info('Successful login');
client.log.info(`User ${user.username} successfully logged in`);
// User's unique session identifier is the same as the connection itself
user.sessionId = client.session.uniqueId; // convenience

View File

@ -188,6 +188,7 @@ exports.getModule = class WaitingForCallerModule extends MenuModule {
uploadBytesToday : StatLog.getSystemStatNum(SysProps.FileUlTodayBytes),
downloadsToday : StatLog.getSystemStatNum(SysProps.FileDlTodayCount),
downloadsBytesToday : StatLog.getSystemStatNum(SysProps.FileDlTodayBytes),
newUsersToday : StatLog.getSystemStatNum(SysProps.NewUsersTodayCount),
// Current
currentUserName : this.client.user.username,
@ -265,18 +266,26 @@ exports.getModule = class WaitingForCallerModule extends MenuModule {
fatal : 'F',
};
const makeLevelIndicator = (level) => {
return levelIndicators[bunyan.nameFromLevel[level]] || '?';
return levelIndicators[level] || '?';
};
const quickLogLevelMessagePrefixes = this.config.quickLogLevelMessagePrefixes || {};
const prefixMssage = (message, level) => {
const prefix = quickLogLevelMessagePrefixes[level] || '';
return `${prefix}${message}`;
};
const logItems = records.map(rec => {
const level = bunyan.nameFromLevel[rec.level];
return {
timestamp : moment(rec.time).format(quickLogTimestampFormat),
level : rec.level,
levelIndicator : makeLevelIndicator(rec.level),
nodeId : rec.nodeId,
levelIndicator : makeLevelIndicator(level),
nodeId : rec.nodeId || '*',
sessionId : rec.sessionId || '',
message : rec.msg,
message : prefixMssage(rec.msg, level),
};
});

View File

@ -104,6 +104,7 @@ There are many predefined MCI codes that can be used anywhere on the system (pla
| `LT` | Time of last caller |
| `LD` | Date of last caller |
| `TU` | Total number of users on the system |
| `NT` | Total *new* users *today* |
Some additional special case codes also exist: