pcon/sfdc-eventMonitoring

View on GitHub
src/show/logins.js

Summary

Maintainability
A
2 hrs
Test Coverage
var chalk = require('chalk');
var lo = require('lodash');
var Q = require('q');

const { table } = require('table');

var config = require('../lib/config.js');
var formatter = require('../lib/formatter.js');
var sfdc = require('../lib/sfdc.js');
var queries = require('../lib/queries.js');
var utils = require('../lib/utils.js');

/**
 * Take the value in the increment string and add one to it
 * @param {object} data The data
 * @param {string} incrementString The string to increment
 * @return {undefined}
 */
var incrementValues = function (data, incrementString) {
    lo.set(data, incrementString, lo.get(data, incrementString) + 1);
};

/**
 * Filters out the users that we don't care about
 * @param {object[]} logs The logs
 * @returns {Promise} A promise for when the logs have been filtered
 */
var filterResults = function (logs) {
    var deferred = Q.defer();
    var results = [];

    if (
        lo.isEmpty(global.config.userid) &&
        !global.config.api
    ) {
        deferred.resolve(logs);
        return deferred.promise;
    }

    lo.forEach(logs, function (log) {
        var include = false;

        if (lo.includes(lo.castArray(global.config.userid), log.USER_ID)) {
            include = true;
        }

        if (
            global.config.api &&
            lo.isEmpty(log.API_TYPE)
        ) {
            include = false;
        }

        if (include) {
            results.push(log);
        }
    });

    deferred.resolve(results);

    return deferred.promise;
};

/**
 * Sets up a new user id record in the data
 * @param {object} data The data
 * @param {object} log The log
 * @return {undefined}
 */
var setupNewUserId = function (data, log) {
    var baseObj = {
        info: {
            userid: log.USER_ID,
            username: log.USER_NAME
        },
        averages: {
            completedSessions: 0,
            sessionLength: 0
        },
        counts: {
            login: 0,
            explicitLogout: 0,
            implicitLogout: 0
        },
        sessions: {}
    };

    lo.set(data, log.USER_ID, baseObj);
};

/**
 * Adds the log to the sessions lookup if it should be
 * @param {object} data The data
 * @param {object} log The log
 * @returns {undefined}
 */
var addToSessions = function (data, log) {
    if (lo.isEmpty(log.REQUEST_ID)) {
        return;
    }

    lo.set(data[log.USER_ID].sessions, log.REQUEST_ID + '.' + lo.upperFirst(log.EVENT_TYPE), log);
};

/**
 * Counts the log under the user
 * @param {object} data The data
 * @param {object} log The log
 * @returns {undefined}
 */
var countLog = function (data, log) {
    var incrementString = log.USER_ID + '.counts.login';

    if (lo.upperFirst(log.EVENT_TYPE) === 'Logout') {
        if (lo.toInteger(log.USER_INITIATED_LOGOUT) === 0) {
            incrementString = log.USER_ID + '.counts.implicitLogout';
        } else {
            incrementString = log.USER_ID + '.counts.explicitLogout';
        }
    }

    incrementValues(data, incrementString);
};

/**
 * Group the data
 * @param {object[]} logs The logs
 * @returns {Promise} A promise for when the data is grouped
 */
var groupData = function (logs) {
    var deferred = Q.defer();
    var data = {};

    lo.forEach(logs, function (log) {
        if (!lo.has(data, log.USER_ID)) {
            setupNewUserId(data, log);
        } else if (lo.isUndefined(lo.get(data, log.USER_ID + '.info.username'))) {
            lo.set(data, log.USER_ID + '.info.username', log.USER_NAME);
        }

        addToSessions(data, log);
        countLog(data, log);
    });

    deferred.resolve(data);

    return deferred.promise;
};

/**
 * Get the session length
 * @param {object} session The session
 * @returns {number} The session length
 */
var getSessionLength = function (session) {
    return utils.toTimestamp(session.Logout.TIMESTAMP_DERIVED) - utils.toTimestamp(session.Login.TIMESTAMP_DERIVED);
};

/**
 * Generates the averages
 * @param {object} data The data
 * @returns {Promise} A promise for when the data has been averaged
 */
var generateAverages = function (data) {
    var deferred = Q.defer();

    lo.forEach(data, function (grouping, user_id) {
        var totalSessionLength = 0;
        var completedSessions = 0;

        lo.forEach(grouping.sessions, function (session) {
            if (
                !lo.has(session, 'Login') ||
                !lo.has(session, 'Logout')
            ) {
                return;
            }

            totalSessionLength += getSessionLength(session);
            completedSessions += 1;
        });

        if (completedSessions > 0) {
            lo.set(data, user_id + '.averages.completedSessions', completedSessions);
            lo.set(data, user_id + '.averages.sessionLength', totalSessionLength / completedSessions);
        }
    });

    deferred.resolve(data);

    return deferred.promise;
};

/**
 * Get the array of data to sort by
 * @param {object} data The data
 * @returns {object[]} The sorted data
 */
var getSortArray = function (data) {
    var results = [];

    lo.forEach(data, function (row, user_id) {
        results.push({
            userid: user_id,
            count: row.counts.login,
            explicit: row.counts.explicitLogout,
            implicit: row.counts.implicitLogout,
            session: row.averages.sessionLength
        });
    });

    results = utils.sortArray(results, global.config.sort);

    if (global.config.asc) {
        results = lo.reverse(results);
    }

    results = utils.limitArray(results, global.config.limit);

    return results;
};

/**
 * Prints the data to the terminal
 * @param {object} data The data
 * @returns {undefined}
 */
var sortAndLimitData = function (data) {
    var deferred = Q.defer();
    var sortArray = getSortArray(data);
    var results = [];

    lo.forEach(sortArray, function (sort) {
        results.push(lo.get(data, sort.userid));
    });

    deferred.resolve(results);

    return deferred.promise;
};

/**
 * Prints out a single entry in a summary
 * @param {object} data The data to print
 * @returns {undefined}
 */
var printSummaryLine = function (data) {
    if (lo.isUndefined(data.info.username)) {
        global.printer.print(chalk.bold('User Id: ') + data.info.userid);
    } else {
        global.printer.print(chalk.bold('Username: ') + data.info.username + ' (' + data.info.userid + ')');
    }
    global.printer.print(chalk.bold('Total Logins: ') + data.counts.login);

    var totalLogouts = data.counts.explicitLogout + data.counts.implicitLogout;
    global.printer.print(
        chalk.bold('Total Logouts: ') + lo.padEnd(totalLogouts, 10) +
        chalk.bold('Explicit: ') + lo.padEnd(data.counts.explicitLogout, 10) +
        chalk.bold('Implicit: ') + data.counts.implicitLogout
    );

    if (data.averages.sessionLength !== 0) {
        global.printer.print(chalk.bold('Average Session Length: ') + formatter.prettyms(data.averages.sessionLength));
    }

    var table_data = [ [
        chalk.bold('URI'),
        chalk.bold('Duration'),
        chalk.bold('Version')
    ] ];

    lo.forEach(data.sessions, function (session) {
        if (
            !lo.has(session, 'Login') ||
            !lo.has(session, 'Logout')
        ) {
            return;
        }

        var sessionLength = getSessionLength(session);
        var apiVersion = session.Login.API_VERSION === '9998.0' ? 'N/A' : session.Login.API_VERSION;
        table_data.push([
            session.Login.URI,
            formatter.prettyms(sessionLength),
            apiVersion
        ]);
    });

    if (lo.size(table_data) > 1) {
        global.printer.print(table(table_data));
    }

    global.printer.print('');
};

/**
 * Print out our data in a summary format
 * @param {object[]} data The data to print
 * @returns {undefined}
 */
var printSummary = function (data) {
    lo.forEach(data, function (row) {
        printSummaryLine(row);
    });
};

/**
 * Prints the data out based on the format
 * @param {object} data The data to print
 * @returns {Promise} A promise for when the printing is done
 */
var printCounts = function (data) {
    var deferred = Q.defer();

    if (config.isJSON()) {
        utils.printJSON(data);
    } else if (config.isTable()) {
        printSummary(data);
    }

    deferred.resolve();

    return deferred.promise;
};

/**
 * The stuff to run
 * @returns {undefined}
 */
var run = function () {
    'use strict';

    utils.updateUserIdCriteria();

    sfdc.query(queries.show.logins())
        .then(utils.fetchAndConvert)
        .then(filterResults)
        .then(groupData)
        .then(generateAverages)
        .then(sortAndLimitData)
        .then(printCounts);
};

var cli = {
    functions: {
        addToSessions: addToSessions,
        contLog: countLog,
        filterResults: filterResults,
        generateAverages: generateAverages,
        getSortArray: getSortArray,
        groupData: groupData,
        incrementValues: incrementValues,
        printCounts: printCounts,
        printSummary: printSummary,
        setupNewUserId: setupNewUserId,
        sortAndLimitData: sortAndLimitData
    },
    run: run
};

module.exports = cli;