Last caller information / MCI
This commit is contained in:
parent
3a7f7750ab
commit
9c7fb16196
36
core/bbs.js
36
core/bbs.js
|
@ -236,6 +236,8 @@ function initialize(cb) {
|
|||
//
|
||||
const User = require('./user.js');
|
||||
|
||||
// :TODO: use User.getUserInfo() for this!
|
||||
|
||||
const propLoadOpts = {
|
||||
names : [
|
||||
UserProps.RealName, UserProps.Sex, UserProps.EmailAddress,
|
||||
|
@ -246,7 +248,7 @@ function initialize(cb) {
|
|||
async.waterfall(
|
||||
[
|
||||
function getOpUserName(next) {
|
||||
return User.getUserName(1, next);
|
||||
return User.getUserName(User.RootUserID, next);
|
||||
},
|
||||
function getOpProps(opUserName, next) {
|
||||
User.loadProperties(User.RootUserID, propLoadOpts, (err, opProps) => {
|
||||
|
@ -273,8 +275,9 @@ function initialize(cb) {
|
|||
}
|
||||
);
|
||||
},
|
||||
function initCallsToday(callback) {
|
||||
function initSystemLogStats(callback) {
|
||||
const StatLog = require('./stat_log.js');
|
||||
|
||||
const filter = {
|
||||
logName : SysLogKeys.UserLoginHistory,
|
||||
resultType : 'count',
|
||||
|
@ -288,7 +291,7 @@ function initialize(cb) {
|
|||
return callback(null);
|
||||
});
|
||||
},
|
||||
function initUserTransferStats(callback) {
|
||||
function initUserLogStats(callback) {
|
||||
const StatLog = require('./stat_log');
|
||||
|
||||
const entries = [
|
||||
|
@ -324,6 +327,33 @@ function initialize(cb) {
|
|||
return callback(null);
|
||||
});
|
||||
},
|
||||
function initLastLogin(callback) {
|
||||
const StatLog = require('./stat_log');
|
||||
StatLog.getSystemLogEntries(SysLogKeys.UserLoginHistory, 'timestamp_desc', 1, (err, lastLogin) => {
|
||||
if (err) {
|
||||
return callback(null);
|
||||
}
|
||||
|
||||
let loginObj;
|
||||
try
|
||||
{
|
||||
loginObj = JSON.parse(lastLogin[0].log_value);
|
||||
loginObj.timestamp = moment(lastLogin[0].timestamp);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
return callback(null);
|
||||
}
|
||||
|
||||
// For live stats we want to resolve user ID -> name, etc.
|
||||
const User = require('./user');
|
||||
User.getUserInfo(loginObj.userId, (err, props) => {
|
||||
const stat = Object.assign({}, props, loginObj);
|
||||
StatLog.setNonPersistentSystemStat(SysProps.LastLogin, stat);
|
||||
return callback(null);
|
||||
});
|
||||
});
|
||||
},
|
||||
function initMessageStats(callback) {
|
||||
return require('./message_area.js').startup(callback);
|
||||
},
|
||||
|
|
|
@ -98,7 +98,6 @@ const PREDEFINED_MCI_GENERATORS = {
|
|||
SA : function opAffils() { return StatLog.getSystemStat(SysProps.SysOpAffiliations); },
|
||||
SS : function opSex() { return StatLog.getSystemStat(SysProps.SysOpSex); },
|
||||
SE : function opEmail() { return StatLog.getSystemStat(SysProps.SysOpEmailAddress); },
|
||||
// :TODO: op age, web, ?????
|
||||
|
||||
//
|
||||
// Current user / session
|
||||
|
@ -243,10 +242,6 @@ const PREDEFINED_MCI_GENERATORS = {
|
|||
UU : function systemUptime() {
|
||||
return moment.duration(process.uptime(), 'seconds').humanize();
|
||||
},
|
||||
|
||||
// :TODO: MCI for core count, e.g. os.cpus().length
|
||||
|
||||
// :TODO: cpu load average (over N seconds): http://stackoverflow.com/questions/9565912/convert-the-output-of-os-cpus-in-node-js-to-percentage
|
||||
NV : function nodeVersion() { return process.version; },
|
||||
AN : function activeNodes() { return clientConnections.getActiveConnections().length.toString(); },
|
||||
|
||||
|
@ -265,8 +260,6 @@ const PREDEFINED_MCI_GENERATORS = {
|
|||
//
|
||||
// System File Base, Up/Download Info
|
||||
//
|
||||
// :TODO: DD - Today's # of downloads (iNiQUiTY)
|
||||
//
|
||||
SD : function systemNumDownloads() { return StatLog.getFriendlySystemStat(SysProps.FileDlTotalCount, 0); },
|
||||
SO : function systemByteDownload() {
|
||||
const byteSize = StatLog.getSystemStatNum(SysProps.FileDlTotalBytes);
|
||||
|
@ -308,10 +301,27 @@ const PREDEFINED_MCI_GENERATORS = {
|
|||
},
|
||||
|
||||
// :TODO: NT - New users today (Obv/2)
|
||||
// :TODO: LC - name of last caller to system (Obv/2)
|
||||
// :TODO: TZ - Average *system* post/call ratio (iNiQUiTY)
|
||||
// :TODO: ?? - Total users on system
|
||||
|
||||
LC : function lastCallerUserName() { // Obv/2
|
||||
const lastLogin = StatLog.getSystemStat(SysProps.LastLogin) || {};
|
||||
return lastLogin.userName || 'N/A';
|
||||
},
|
||||
LD : function lastCallerDate(client) {
|
||||
const lastLogin = StatLog.getSystemStat(SysProps.LastLogin) || {};
|
||||
if (!lastLogin.timestamp) {
|
||||
return 'N/A';
|
||||
}
|
||||
return lastLogin.timestamp.format(client.currentTheme.helpers.getDateFormat());
|
||||
},
|
||||
LT : function lastCallerTime(client) {
|
||||
const lastLogin = StatLog.getSystemStat(SysProps.LastLogin) || {};
|
||||
if (!lastLogin.timestamp) {
|
||||
return 'N/A';
|
||||
}
|
||||
return lastLogin.timestamp.format(client.currentTheme.helpers.getTimeFormat());
|
||||
},
|
||||
|
||||
//
|
||||
// Special handling for XY
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
module.exports = {
|
||||
LoginCount : 'login_count',
|
||||
LoginsToday : 'logins_today', // non-persistent
|
||||
LastLogin : 'last_login', // object { userId, sessionId, userName, userRealName, timestamp }; non-persistent
|
||||
|
||||
FileBaseAreaStats : 'file_base_area_stats', // object - see file_base_area.js::getAreaStats
|
||||
FileUlTotalCount : 'ul_total_count',
|
||||
|
@ -25,19 +26,15 @@ module.exports = {
|
|||
MessageTotalCount : 'message_post_total_count', // total non-private messages on the system; non-persistent
|
||||
MessagesToday : 'message_post_today', // non-private messages posted/imported today; non-persistent
|
||||
|
||||
// begin +op non-persistent...
|
||||
SysOpUsername : 'sysop_username',
|
||||
SysOpRealName : 'sysop_real_name',
|
||||
SysOpLocation : 'sysop_location',
|
||||
SysOpAffiliations : 'sysop_affiliation',
|
||||
SysOpSex : 'sysop_sex',
|
||||
SysOpEmailAddress : 'sysop_email_address',
|
||||
// end +op non-persistent
|
||||
SysOpUsername : 'sysop_username', // non-persistent
|
||||
SysOpRealName : 'sysop_real_name', // non-persistent
|
||||
SysOpLocation : 'sysop_location', // non-persistent
|
||||
SysOpAffiliations : 'sysop_affiliation', // non-persistent
|
||||
SysOpSex : 'sysop_sex', // non-persistent
|
||||
SysOpEmailAddress : 'sysop_email_address', // non-persistent
|
||||
|
||||
NextRandomRumor : 'random_rumor',
|
||||
|
||||
// begin system stat non-persistent...
|
||||
SystemMemoryStats : 'system_memory_stats', // object { totalBytes, freeBytes }
|
||||
SystemLoadStats : 'system_load_stats', // object { average, current }
|
||||
// end system stat non persistent
|
||||
SystemMemoryStats : 'system_memory_stats', // object { totalBytes, freeBytes }; non-persistent
|
||||
SystemLoadStats : 'system_load_stats', // object { average, current }; non-persistent
|
||||
};
|
||||
|
|
35
core/user.js
35
core/user.js
|
@ -630,6 +630,41 @@ module.exports = class User {
|
|||
);
|
||||
}
|
||||
|
||||
static getUserInfo(userId, propsList, cb) {
|
||||
if (!cb && _.isFunction(propsList)) {
|
||||
cb = propsList;
|
||||
propsList = [
|
||||
UserProps.RealName, UserProps.Sex, UserProps.EmailAddress,
|
||||
UserProps.Location, UserProps.Affiliations,
|
||||
];
|
||||
}
|
||||
|
||||
async.waterfall(
|
||||
[
|
||||
(callback) => {
|
||||
return User.getUserName(userId, callback);
|
||||
},
|
||||
(userName, callback) => {
|
||||
User.loadProperties(userId, { names : propsList }, (err, props) => {
|
||||
return callback(err, Object.assign({}, props, { user_name : userName }));
|
||||
});
|
||||
}
|
||||
],
|
||||
(err, userProps) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
const userInfo = {};
|
||||
Object.keys(userProps).forEach(key => {
|
||||
userInfo[_.camelCase(key)] = userProps[key] || 'N/A';
|
||||
});
|
||||
|
||||
return cb(null, userInfo);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static isRootUserId(userId) {
|
||||
return (User.RootUserID === userId);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ const {
|
|||
const async = require('async');
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
const moment = require('moment');
|
||||
|
||||
exports.userLogin = userLogin;
|
||||
exports.recordLogin = recordLogin;
|
||||
|
@ -176,6 +177,8 @@ function recordLogin(client, cb) {
|
|||
assert(client.user.authenticated); // don't get in situations where this isn't true
|
||||
|
||||
const user = client.user;
|
||||
const loginTimestamp = StatLog.now;
|
||||
|
||||
async.parallel(
|
||||
[
|
||||
(callback) => {
|
||||
|
@ -183,7 +186,7 @@ function recordLogin(client, cb) {
|
|||
return StatLog.incrementSystemStat(SysProps.LoginCount, 1, callback);
|
||||
},
|
||||
(callback) => {
|
||||
return StatLog.setUserStat(user, UserProps.LastLoginTs, StatLog.now, callback);
|
||||
return StatLog.setUserStat(user, UserProps.LastLoginTs, loginTimestamp, callback);
|
||||
},
|
||||
(callback) => {
|
||||
return StatLog.incrementUserStat(user, UserProps.LoginCount, 1, callback);
|
||||
|
@ -202,6 +205,24 @@ function recordLogin(client, cb) {
|
|||
StatLog.KeepType.Max,
|
||||
callback
|
||||
);
|
||||
},
|
||||
(callback) => {
|
||||
// Update live last login information which includes additional
|
||||
// (pre-resolved) information such as user name/etc.
|
||||
const lastLogin = {
|
||||
userId : user.userId,
|
||||
sessionId : user.sessionId,
|
||||
userName : user.username,
|
||||
realName : user.getProperty(UserProps.RealName),
|
||||
affiliation : user.getProperty(UserProps.Affiliations),
|
||||
emailAddress : user.getProperty(UserProps.EmailAddress),
|
||||
sex : user.getProperty(UserProps.Sex),
|
||||
location : user.getProperty(UserProps.Location),
|
||||
timestamp : moment(loginTimestamp),
|
||||
};
|
||||
|
||||
StatLog.setNonPersistentSystemStat(SysProps.LastLogin, lastLogin);
|
||||
return callback(null);
|
||||
}
|
||||
],
|
||||
err => {
|
||||
|
|
|
@ -100,7 +100,9 @@ There are many predefined MCI codes that can be used anywhere on the system (pla
|
|||
| `LA` | System load average (e.g. 0.25)<br>(Not available for all platforms) |
|
||||
| `CL` | System current load percentage<br>(Not available for all platforms) |
|
||||
| `UU` | System uptime in friendly format |
|
||||
|
||||
| `LC` | Last caller to the system (username) |
|
||||
| `LT` | Time of last caller |
|
||||
| `LD` | Date of last caller |
|
||||
|
||||
Some additional special case codes also exist:
|
||||
|
||||
|
|
Loading…
Reference in New Issue