aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/Client.ts13
-rw-r--r--src/server/DashStats.ts119
-rw-r--r--src/server/index.ts6
-rw-r--r--src/server/stats/userLoginStats.csv77
-rw-r--r--src/server/websocket.ts24
-rw-r--r--views/stats.pug22
-rw-r--r--views/stylesheets/statsview.css56
7 files changed, 290 insertions, 27 deletions
diff --git a/src/server/Client.ts b/src/server/Client.ts
index e6f953712..be1ffc2ba 100644
--- a/src/server/Client.ts
+++ b/src/server/Client.ts
@@ -1,11 +1,22 @@
-import { computed } from "mobx";
+import { action, computed } from "mobx";
export class Client {
private _guid: string;
+ // private operations: number;
constructor(guid: string) {
this._guid = guid;
+ // this.operations = 0;
}
+ // @computed public get OPERATIONS(): number {
+ // return this.operations;
+ // }
+
+ // @action
+ // public setOperations(newOperations: number): void {
+ // this.operations = newOperations;
+ // }
+
@computed public get GUID(): string { return this._guid; }
} \ No newline at end of file
diff --git a/src/server/DashStats.ts b/src/server/DashStats.ts
index 13ee61b3a..a10b28608 100644
--- a/src/server/DashStats.ts
+++ b/src/server/DashStats.ts
@@ -1,11 +1,11 @@
-import { magenta } from 'colors';
+import { cyan, magenta } from 'colors';
import { Request, Response } from 'express';
+import { Server } from 'http';
import SocketIO from 'socket.io';
-import { Client } from './Client';
+import { timeMap } from './ApiManagers/UserManager';
import { WebSocket } from './websocket';
const fs = require('fs');
const csv = require('csv-parser');
-import { stringify } from 'csv-stringify/sync';
export namespace DashStats {
const statsCSVFilename = './src/server/stats/userLoginStats.csv';
@@ -14,6 +14,8 @@ export namespace DashStats {
interface SocketPair {
socketId: string;
username: string;
+ time: string;
+ operations: number;
}
interface CSVStore {
@@ -22,49 +24,128 @@ export namespace DashStats {
TIME: string;
}
- export function handleStatsView(res: Response) {
+ enum ServerTraffic {
+ NOT_BUSY,
+ BUSY,
+ VERY_BUSY
+ }
+
+ const BUSY_SERVER_BOUND = 2;
+ const VERY_BUSY_SERVER_BOUND = 3;
+
+ const serverTrafficMessages = [
+ "Not Busy",
+ "Busy",
+ "Very Busy"
+ ]
+
+ export function handleStats(res: Response) {
+ let current = getCurrentConnections();
const results: CSVStore[] = [];
- fs.createReadStream(statsCSVFilename)
- .pipe(csv(columns))
- .on('data', (data: any) => results.push(data))
- .on('end', () => {
- console.log(results);
+ res.json({
+ message: 'welcome to stats',
+ currentConnections: current.length,
+ socketMap: current,
});
- // let newRow = stringify([{ USERNAME: 'hi', ACTION: 'hi', TIME: 'hi' }], { header: true, columns: columns });
- // console.log(newRow);
+ // fs.createReadStream(statsCSVFilename)
+ // .pipe(csv())
+ // .on('data', (data: any) => results.push(data))
+ // .on('end', () => {
+ // console.log(results);
+ // res.json({
+ // message: 'welcome to stats',
+ // currentConnections: current.length,
+ // socketMap: current,
+ // results: results,
+ // });
+ // });
+ }
+ export function handleStatsView(res: Response) {
let current = getCurrentConnections();
- res.json({
- message: 'welcome to stats',
- currentConnections: current.length,
- socketMap: current,
+
+ let connectedUsers = current.map((socketPair) => {
+ return socketPair.time + " - " + socketPair.username + " Operations: " + socketPair.operations;
+ })
+
+ let serverTraffic = ServerTraffic.NOT_BUSY;
+ if(current.length < BUSY_SERVER_BOUND) {
+ serverTraffic = ServerTraffic.NOT_BUSY;
+ } else if(current.length >= BUSY_SERVER_BOUND && current.length < VERY_BUSY_SERVER_BOUND) {
+ serverTraffic = ServerTraffic.BUSY;
+ } else {
+ serverTraffic = ServerTraffic.VERY_BUSY;
+ }
+
+ res.render("stats.pug", {
+ title: "Dash Stats",
+ numConnections: current.length,
+ serverTraffic: serverTraffic,
+ serverTrafficMessage : serverTrafficMessages[serverTraffic],
+ connectedUsers: connectedUsers
});
}
export function logUserLogin(username: string | undefined, socket: SocketIO.Socket) {
if (!(username === undefined)) {
let currentDate = new Date();
- console.log(magenta(`User ${username.split(' ')[0]} logged in at: ${currentDate.toISOString()}`));
- console.log('stringify -> ');
+ // console.log(magenta(`User ${username.split(' ')[0]} logged in at: ${currentDate.toISOString()}`));
+
+ let toWrite: CSVStore = {
+ USERNAME : username,
+ ACTION : "loggedIn",
+ TIME : currentDate.toISOString()
+ }
+
+ let statsFile = fs.createWriteStream(statsCSVFilename, { flags: "a"});
+ statsFile.write(convertToCSV(toWrite));
+ statsFile.end();
+ console.log(cyan(convertToCSV(toWrite)));
}
}
export function logUserLogout(username: string | undefined, socket: SocketIO.Socket) {
if (!(username === undefined)) {
let currentDate = new Date();
- console.log(magenta(`User ${username.split(' ')[0]} logged out at: ${currentDate.toISOString()}`));
+ // console.log(magenta(`User ${username.split(' ')[0]} logged out at: ${currentDate.toISOString()}`));
+
+ let statsFile = fs.createWriteStream(statsCSVFilename, { flags: "a"});
+ let toWrite: CSVStore = {
+ USERNAME : username,
+ ACTION : "loggedOut",
+ TIME : currentDate.toISOString()
+ }
+ statsFile.write(convertToCSV(toWrite));
+ statsFile.end();
}
}
function getCurrentConnections(): SocketPair[] {
+ console.log("timeMap: " + timeMap);
+ console.log("clients:" + WebSocket.clients);
let socketPairs: SocketPair[] = [];
for (let [key, value] of WebSocket.socketMap) {
+ let username = value.split(' ')[0];
+ let connectionTime = new Date(timeMap[username]);
+
+ let connectionTimeString = connectionTime.toLocaleDateString() + " " + connectionTime.toLocaleTimeString();
+
if (!key.disconnected) {
- socketPairs.push({ socketId: key.id, username: value.split(' ')[0] });
+ socketPairs.push({
+ socketId: key.id,
+ username: username,
+ time: connectionTimeString.includes("Invalid Date") ? "" : connectionTimeString,
+ operations : WebSocket.userOperations.get(username) ? WebSocket.userOperations.get(username)! : 0,
+ });
}
}
console.log(socketPairs);
+ // console.log([...WebSocket.clients.entries()]);
return socketPairs;
}
+
+ function convertToCSV(dataObject: CSVStore): string {
+ return `${dataObject.USERNAME},${dataObject.ACTION},${dataObject.TIME}\n`;
+ }
}
diff --git a/src/server/index.ts b/src/server/index.ts
index 0848d828e..d76f12b95 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -87,6 +87,12 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
addSupervisedRoute({
method: Method.GET,
subscription: '/stats',
+ secureHandler: ({ res }) => DashStats.handleStats(res),
+ });
+
+ addSupervisedRoute({
+ method: Method.GET,
+ subscription: '/statsview',
secureHandler: ({ res }) => DashStats.handleStatsView(res),
});
diff --git a/src/server/stats/userLoginStats.csv b/src/server/stats/userLoginStats.csv
index ec33b01b2..d5e56502c 100644
--- a/src/server/stats/userLoginStats.csv
+++ b/src/server/stats/userLoginStats.csv
@@ -1,2 +1,75 @@
-USERNAME,ACTION,TIME
-boo15869,loggedIn,2023-01 \ No newline at end of file
+USER,ACTION,TIME
+aaa@gmail.com,loggedIn,2023-03-18T20:10:29.928Z
+guest,loggedIn,2023-03-18T20:10:47.384Z
+aaa@gmail.com,loggedOut,2023-03-18T20:10:55.364Z
+aaa@gmail.com,loggedIn,2023-03-18T20:11:15.879Z
+guest,loggedIn,2023-03-18T20:18:03.724Z
+aaa@gmail.com,loggedIn,2023-03-18T20:18:03.860Z
+guest,loggedOut,2023-03-18T20:19:00.211Z
+guest,loggedIn,2023-03-18T20:19:03.087Z
+guest,loggedOut,2023-03-18T20:19:50.668Z
+boo15869@gmail.com,loggedIn,2023-03-18T20:20:17.890Z
+boo15869@gmail.com,loggedOut,2023-03-18T20:21:03.542Z
+boo15869@gmail.com,loggedIn,2023-03-18T20:21:06.149Z
+boo15869@gmail.com,loggedOut,2023-03-18T20:21:51.874Z
+a@gmail.com,loggedIn,2023-03-18T20:22:02.122Z
+aaa@gmail.com,loggedOut,2023-03-18T20:22:42.882Z
+aaa@gmail.com,loggedIn,2023-03-18T20:22:45.631Z
+aaa@gmail.com,loggedIn,2023-03-18T20:25:34.658Z
+a@gmail.com,loggedIn,2023-03-18T20:25:34.681Z
+aaa@gmail.com,loggedIn,2023-03-18T20:29:04.297Z
+a@gmail.com,loggedIn,2023-03-18T20:29:08.701Z
+a@gmail.com,loggedIn,2023-03-18T20:29:18.565Z
+aaa@gmail.com,loggedIn,2023-03-18T20:29:21.974Z
+aaa@gmail.com,loggedIn,2023-03-18T20:29:51.477Z
+a@gmail.com,loggedIn,2023-03-18T20:29:51.489Z
+aaa@gmail.com,loggedIn,2023-03-18T20:30:15.011Z
+aaa@gmail.com,loggedIn,2023-03-18T20:30:57.818Z
+a@gmail.com,loggedIn,2023-03-18T20:30:57.838Z
+aaa@gmail.com,loggedIn,2023-03-18T20:31:12.061Z
+a@gmail.com,loggedIn,2023-03-18T20:31:12.080Z
+a@gmail.com,loggedIn,2023-03-18T20:31:19.447Z
+aaa@gmail.com,loggedIn,2023-03-18T20:31:22.738Z
+aaa@gmail.com,loggedIn,2023-03-18T20:32:36.919Z
+a@gmail.com,loggedIn,2023-03-18T20:32:36.929Z
+a@gmail.com,loggedIn,2023-03-18T20:32:56.212Z
+aaa@gmail.com,loggedIn,2023-03-18T20:32:59.300Z
+aaa@gmail.com,loggedIn,2023-03-18T20:34:27.543Z
+a@gmail.com,loggedIn,2023-03-18T20:34:27.570Z
+a@gmail.com,loggedIn,2023-03-18T20:34:35.299Z
+aaa@gmail.com,loggedIn,2023-03-18T20:34:35.302Z
+a@gmail.com,loggedIn,2023-03-18T20:34:51.579Z
+aaa@gmail.com,loggedIn,2023-03-18T20:34:52.392Z
+a@gmail.com,loggedIn,2023-03-18T20:35:08.509Z
+aaa@gmail.com,loggedIn,2023-03-18T20:35:15.202Z
+a@gmail.com,loggedIn,2023-03-18T20:36:46.796Z
+aaa@gmail.com,loggedIn,2023-03-18T20:36:51.756Z
+a@gmail.com,loggedIn,2023-03-18T20:36:55.286Z
+a@gmail.com,loggedIn,2023-03-18T20:40:06.226Z
+a@gmail.com,loggedIn,2023-03-18T20:40:18.474Z
+aaa@gmail.com,loggedIn,2023-03-18T20:40:31.894Z
+a@gmail.com,loggedIn,2023-03-18T20:40:31.903Z
+a@gmail.com,loggedIn,2023-03-18T20:42:25.301Z
+aaa@gmail.com,loggedIn,2023-03-18T20:42:31.182Z
+aaa@gmail.com,loggedOut,2023-03-18T20:43:05.741Z
+aaa@gmail.com,loggedIn,2023-03-18T20:43:09.203Z
+a@gmail.com,loggedOut,2023-03-18T20:45:24.343Z
+a@gmail.com,loggedIn,2023-03-18T20:45:27.207Z
+aaa@gmail.com,loggedIn,2023-03-18T20:46:15.618Z
+a@gmail.com,loggedIn,2023-03-18T20:46:56.163Z
+a@gmail.com,loggedOut,2023-03-18T20:48:37.464Z
+a@gmail.com,loggedIn,2023-03-18T20:48:40.562Z
+a@gmail.com,loggedOut,2023-03-18T20:50:32.478Z
+a@gmail.com,loggedIn,2023-03-18T20:50:40.384Z
+a@gmail.com,loggedOut,2023-03-18T20:51:34.159Z
+a@gmail.com,loggedIn,2023-03-18T20:51:49.206Z
+a@gmail.com,loggedOut,2023-03-18T20:52:04.673Z
+qw@gmail.com,loggedIn,2023-03-18T20:52:36.270Z
+qw@gmail.com,loggedIn,2023-03-18T20:53:58.175Z
+aaa@gmail.com,loggedIn,2023-03-18T20:53:58.204Z
+aaa@gmail.com,loggedIn,2023-03-18T20:54:20.518Z
+qw@gmail.com,loggedIn,2023-03-18T20:54:24.225Z
+qw@gmail.com,loggedIn,2023-03-18T20:54:37.007Z
+aaa@gmail.com,loggedIn,2023-03-18T20:54:39.959Z
+aaa@gmail.com,loggedOut,2023-03-18T20:55:55.199Z
+qw@gmail.com,loggedOut,2023-03-18T20:55:59.010Z
diff --git a/src/server/websocket.ts b/src/server/websocket.ts
index e556ecc17..54944e944 100644
--- a/src/server/websocket.ts
+++ b/src/server/websocket.ts
@@ -1,4 +1,4 @@
-import { blue, magenta } from 'colors';
+import { blue, magenta, yellow } from 'colors';
import * as express from 'express';
import { createServer, Server } from 'https';
import { networkInterfaces } from 'os';
@@ -22,7 +22,9 @@ import { resolvedPorts } from './server_Initialization';
export namespace WebSocket {
export let _socket: Socket;
export const clients: { [key: string]: Client } = {};
+ // export const clients = new Map<string, Client>();
export const socketMap = new Map<SocketIO.Socket, string>();
+ export const userOperations = new Map<string, number>();
export let disconnect: Function;
export async function initialize(isRelease: boolean, app: express.Express) {
@@ -101,7 +103,9 @@ export namespace WebSocket {
socket.on('disconnect', function () {
let currentUser = socketMap.get(socket);
if (!(currentUser === undefined)) {
- DashStats.logUserLogout(socketMap.get(socket), socket);
+ let currentUsername = currentUser.split(' ')[0]
+ DashStats.logUserLogout(currentUsername, socket);
+ delete timeMap[currentUsername]
}
});
@@ -180,16 +184,20 @@ export namespace WebSocket {
}
function barReceived(socket: SocketIO.Socket, userEmail: string) {
- clients[userEmail] = new Client(userEmail.toString());
+ clients[userEmail] = new Client(userEmail.toString());
+ // clients.set(userEmail, new Client(userEmail.toString()));
const currentdate = new Date();
const datetime = currentdate.getDate() + '/' + (currentdate.getMonth() + 1) + '/' + currentdate.getFullYear() + ' @ ' + currentdate.getHours() + ':' + currentdate.getMinutes() + ':' + currentdate.getSeconds();
console.log(blue(`user ${userEmail} has connected to the web socket at: ${datetime}`));
- console.log(magenta(`currently connected: ${JSON.stringify(clients)}`));
+ // console.log(magenta(`currently connected: ${[...clients.entries()]}`));
// console.log(magenta('socket map below'));
// console.log([...socketMap.entries()]);
printActiveUsers();
+
+ timeMap[userEmail] = Date.now();
socketMap.set(socket, userEmail + ' at ' + datetime);
- DashStats.logUserLogin(socketMap.get(socket), socket);
+ userOperations.set(userEmail, 0);
+ DashStats.logUserLogin(userEmail, socket);
}
function getField([id, callback]: [string, (result?: Transferable) => void]) {
@@ -359,6 +367,12 @@ export namespace WebSocket {
var CurUser: string | undefined = undefined;
function UpdateField(socket: Socket, diff: Diff) {
+ console.log(magenta(`1 OP ${socketMap.get(socket)}`));
+
+ let currentUsername = socketMap.get(socket)!.split(' ')[0];
+ userOperations.set(currentUsername, userOperations.get(currentUsername) !== undefined ? userOperations.get(currentUsername)! + 1 : 0);
+ console.log(yellow("Total Operations: " + userOperations.get(currentUsername)));
+
if (CurUser !== socketMap.get(socket)) {
CurUser = socketMap.get(socket);
console.log('Switch User: ' + CurUser);
diff --git a/views/stats.pug b/views/stats.pug
new file mode 100644
index 000000000..54c017e70
--- /dev/null
+++ b/views/stats.pug
@@ -0,0 +1,22 @@
+extends ./layout
+
+block content
+ style
+ include ./stylesheets/authentication.css
+ include ./stylesheets/statsview.css
+ .outermost
+ .stats-container
+ h1 Dash Stats
+ p(class="stats-content") Current Connections: #{numConnections}
+ div(class="stats-content stats-server-status-container")
+ p Server Status:
+ div(class="stats-server-status-item stats-server-status-" + serverTraffic)
+ p #{serverTrafficMessage}
+ div(class="stats-content stats-connected-users")
+ p Connected Users:
+ ul
+ each username in connectedUsers
+ li(class="none")= username
+
+
+ \ No newline at end of file
diff --git a/views/stylesheets/statsview.css b/views/stylesheets/statsview.css
new file mode 100644
index 000000000..c018bedfc
--- /dev/null
+++ b/views/stylesheets/statsview.css
@@ -0,0 +1,56 @@
+.outermost {
+ background-color: #251f1f;
+ display: flex;
+ flex-direction: row;
+ height: 98vh;
+ width: 99vw;
+ justify-content: center;
+ position: relative;
+}
+
+.stats-container {
+ background-color: white;
+
+ padding: 1rem;
+ width: 80vw;
+ border-radius: 8px;
+}
+
+.stats-content {
+ font-size: 1.25em;
+
+}
+
+.stats-server-status-container {
+ display: flex;
+ flex-direction: row;
+}
+
+.stats-server-status-item {
+ margin-left: 0.25rem;
+ padding: 0px 5px;
+
+ border-radius: 3px;
+ width: 8rem;
+ text-align: center;
+}
+
+.stats-server-status-0 {
+ /* not busy */
+ border: 3px green solid;
+}
+
+.stats-server-status-1 {
+ /* busy */
+ border: 3px #ffcc00 solid;
+}
+
+.stats-server-status-2 {
+ /* very busy */
+ border: 3px red solid;
+}
+
+.stats-connected-users {
+ max-height: 70vh;
+ overflow-y: auto;
+} \ No newline at end of file