diff --git a/acp.js b/acp.js
index d1424a0e..12ad6e9e 100644
--- a/acp.js
+++ b/acp.js
@@ -160,6 +160,16 @@ module.exports = function (Server) {
ActionLog.clearOne(data);
ActionLog.record(user.ip, user.name, "acp-actionlog-clear-one", data);
});
+
+ user.socket.on("acp-view-stats", function () {
+ var db = Server.db.getConnection();
+ if(!db)
+ return;
+ var query = "SELECT * FROM stats WHERE 1";
+ var results = db.querySync(query);
+ if(results)
+ user.socket.emit("acp-view-stats", results.fetchAllSync());
+ });
}
}
}
diff --git a/database.js b/database.js
index 4c737b48..3901a3d9 100644
--- a/database.js
+++ b/database.js
@@ -201,6 +201,19 @@ function init() {
if(!results) {
Logger.errlog.log("! Failed to create actionlog table");
}
+
+ // Create stats table
+ query = ["CREATE TABLE IF NOT EXISTS `stats` (",
+ "`time` BIGINT NOT NULL,",
+ "`usercount` INT NOT NULL,",
+ "`chancount` INT NOT NULL,",
+ "`mem` INT NOT NULL,",
+ "PRIMARY KEY (`time`))",
+ "ENGINE = MyISAM;"].join("");
+ results = db.querySync(query);
+ if(!results) {
+ Logger.errlog.log("! Failed to create stats table");
+ }
}
/* REGION Global Bans */
diff --git a/server.js b/server.js
index 63c208b1..315b9554 100644
--- a/server.js
+++ b/server.js
@@ -62,6 +62,7 @@ var Server = {
//for(var i in chan)
// delete chan[i];
},
+ stats: null,
app: null,
io: null,
httpserv: null,
@@ -147,6 +148,9 @@ var Server = {
// init ACP
this.acp = require("./acp")(this);
+
+ // init stats
+ this.stats = require("./stats")(this);
},
shutdown: function () {
Logger.syslog.log("Unloading channels");
diff --git a/www/acp.html b/www/acp.html
index ae15855f..04063d84 100644
--- a/www/acp.html
+++ b/www/acp.html
@@ -44,6 +44,7 @@
Users
Loaded Channels
Action Log
+ Server Stats
@@ -219,6 +220,14 @@
+
+
User Count
+
+ Channel Count
+
+ Memory Usage (MB)
+
+
@@ -240,6 +249,7 @@
+
diff --git a/www/assets/js/acp.js b/www/assets/js/acp.js
index 81236773..fd3c983d 100644
--- a/www/assets/js/acp.js
+++ b/www/assets/js/acp.js
@@ -169,6 +169,11 @@ $("#actionlog_time").click(function() {
tableResort($("#actionlog table"), "time");
});
+menuHandler("#show_stats", "#stats");
+$("#show_stats").click(function () {
+ socket.emit("acp-view-stats");
+});
+
function reverseLog() {
$("#log").text($("#log").text().split("\n").reverse().join("\n"));
}
@@ -492,6 +497,72 @@ function setupCallbacks() {
$(" | ").appendTo(tr);
});
+ socket.on("acp-view-stats", function (stats) {
+ var labels = [];
+ var ucounts = [];
+ var ccounts = [];
+ var mcounts = [];
+ var lastdate = "";
+ stats.forEach(function (s) {
+ var d = new Date(parseInt(s.time));
+ var t = "";
+ if(d.toDateString() !== lastdate) {
+ lastdate = d.toDateString();
+ t = d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate();
+ t += " " + d.toTimeString().split(" ")[0];
+ }
+ else {
+ t = d.toTimeString().split(" ")[0];
+ }
+ labels.push(t);
+ ucounts.push(s.usercount);
+ ccounts.push(s.chancount);
+ mcounts.push(s.mem / 1000000);
+ });
+
+ var user_data = {
+ labels: labels,
+ datasets: [
+ {
+ fillColor: "rgba(151, 187, 205, 0.5)",
+ strokeColor: "rgba(151, 187, 205, 1)",
+ pointColor: "rgba(151, 187, 205, 1)",
+ pointStrokeColor: "#fff",
+ data: ucounts
+ }
+ ]
+ };
+
+ var chan_data = {
+ labels: labels,
+ datasets: [
+ {
+ fillColor: "rgba(151, 187, 205, 0.5)",
+ strokeColor: "rgba(151, 187, 205, 1)",
+ pointColor: "rgba(151, 187, 205, 1)",
+ pointStrokeColor: "#fff",
+ data: ccounts
+ }
+ ]
+ };
+
+ var mem_data = {
+ labels: labels,
+ datasets: [
+ {
+ fillColor: "rgba(151, 187, 205, 0.5)",
+ strokeColor: "rgba(151, 187, 205, 1)",
+ pointColor: "rgba(151, 187, 205, 1)",
+ pointStrokeColor: "#fff",
+ data: mcounts
+ }
+ ]
+ };
+
+ new Chart($("#stat_users")[0].getContext("2d")).Line(user_data);
+ new Chart($("#stat_channels")[0].getContext("2d")).Line(chan_data);
+ new Chart($("#stat_mem")[0].getContext("2d")).Line(mem_data);
+ });
}
/* cookie util */