diff --git a/server.py b/server.py
index 9999d37..a45f663 100755
--- a/server.py
+++ b/server.py
@@ -11,6 +11,7 @@ import os
import util
import contributor_helper
+import users_helper
configfile = os.path.join(os.environ['DASH_CONFIG'], 'config.cfg')
cfg = configparser.ConfigParser()
@@ -32,6 +33,7 @@ serv_redis_db = redis.StrictRedis(
db=cfg.getint('RedisDB', 'db'))
contributor_helper = contributor_helper.Contributor_helper(serv_redis_db, cfg)
+users_helper = users_helper.Users_helper(serv_redis_db, cfg)
subscriber_log = redis_server_log.pubsub(ignore_subscribe_messages=True)
subscriber_log.psubscribe(cfg.get('RedisLog', 'channel'))
@@ -206,35 +208,17 @@ def getUserLogins():
except:
date = datetime.datetime.now()
- keyname = "USER_LOGIN:{}"
- prev_days = 6
- week = {}
- for curDate in util.getXPrevDaysSpan(date, prev_days):
- timestamps = serv_redis_db.smembers(keyname.format(util.getDateStrFormat(curDate)))
- timestamps = [int(timestamp.decode('utf8')) for timestamp in timestamps]
- day = {}
- for timestamp in timestamps:
- date = datetime.datetime.fromtimestamp(float(timestamp))
- if date.hour not in day:
- day[date.hour] = 0
- day[date.hour] += 1
- week[curDate.weekday()] = day
+ data = users_helper.getUserLoginsForPunchCard(date)
+ return jsonify(data)
- # Format data
- data = []
- for d in range(7):
- try:
- to_append = []
- for h in range(24):
- try:
- to_append.append(week[d][h])
- except KeyError:
- to_append.append(0)
- # swap 24 and 1. (punchcard starts at 1h)
- temp = to_append[1:]+[to_append[0]]
- data.append(temp)
- except KeyError:
- data.append([0 for x in range(24)])
+@app.route("/_getUserLoginsOvertime")
+def getUserLoginsOvertime():
+ try:
+ date = datetime.datetime.fromtimestamp(float(request.args.get('date')))
+ except:
+ date = datetime.datetime.now()
+
+ data = users_helper.getUserLoginsOvertime(date)
return jsonify(data)
''' INDEX '''
diff --git a/templates/users.html b/templates/users.html
index 7779528..bd6345f 100644
--- a/templates/users.html
+++ b/templates/users.html
@@ -24,6 +24,7 @@
+
@@ -104,29 +105,50 @@ small {
-
-
-
- Punch card - login
-
-
-
-
+
+
+
+
+ Punch card - login
+
+
+
+
-
-
-
- Contribution after login (API vs non-API)
-
-
-
-
+
+
+
+ Top login per organisation
+
+
+
+
+
+
+ Contribution after login (API vs non-API)
+
+
+
+
+
+
@@ -178,6 +200,40 @@ small {
});
});
+ $.getJSON( "{{ url_for('getUserLogins') }}", function( data ) {
+ data = [{label: 'org1', data:[ Math.floor(Math.random() * 100) + 1]},
+ {label: 'org2', data:[ Math.floor(Math.random() * 100) + 1]},
+ {label: 'org3', data:[ Math.floor(Math.random() * 100) + 1]}]
+ $.plot('#barChart', data, {
+ series: {
+ pie: {
+ innerRadius: 0.5,
+ show: true
+ }
+ }
+ });
+ });
+
+ $.getJSON( "{{ url_for('getUserLoginsOvertime') }}", function( data ) {
+ temp = [];
+ var i=0;
+ for (item of data) {
+ temp.push([new Date(item[0]*1000), item[1]]);
+ }
+ console.log(temp);
+ data = {label: 'Login overtime', data: temp}
+ $.plot('#lineChart', [data], {
+ lines: {
+ show: true,
+ steps: true,
+ fill: true
+ },
+ xaxis: {
+ mode: "time",
+ minTickSize: [1, "hour"],
+ }
+ });
+ });
});
diff --git a/users_helper.py b/users_helper.py
new file mode 100644
index 0000000..caf4914
--- /dev/null
+++ b/users_helper.py
@@ -0,0 +1,73 @@
+import math, random
+import os
+import json
+import datetime, time
+
+import util
+
+class Users_helper:
+ def __init__(self, serv_redis_db, cfg):
+ self.serv_redis_db = serv_redis_db
+ self.cfg = cfg
+
+ def add_user_login(self, timestamp):
+ timestampDate = datetime.datetime.fromtimestamp(float(timestamp))
+ timestampDate_str = util.getDateStrFormat(timestampDate)
+ keyname = "{}:{}".format('USER_LOGIN', timestampDate_str)
+ self.serv_redis_db.sadd(keyname, timestamp)
+
+ def getUserLogins(self, date):
+ keyname = "USER_LOGIN:{}"
+ timestamps = self.serv_redis_db.smembers(keyname.format(util.getDateStrFormat(date)))
+ timestamps = [int(timestamp.decode('utf8')) for timestamp in timestamps]
+ return timestamps
+
+ def getUserLoginsForPunchCard(self, date, prev_days=6):
+ week = {}
+ for curDate in util.getXPrevDaysSpan(date, prev_days):
+ timestamps = self.getUserLogins(curDate)
+ day = {}
+ for timestamp in timestamps:
+ date = datetime.datetime.fromtimestamp(float(timestamp))
+ if date.hour not in day:
+ day[date.hour] = 0
+ day[date.hour] += 1
+ week[curDate.weekday()] = day
+
+ # Format data
+ data = []
+ for d in range(7):
+ try:
+ to_append = []
+ for h in range(24):
+ try:
+ to_append.append(week[d][h])
+ except KeyError:
+ to_append.append(0)
+ # swap 24 and 1. (punchcard starts at 1h)
+ temp = to_append[1:]+[to_append[0]]
+ data.append(temp)
+ except KeyError: # no data
+ data.append([0 for x in range(24)])
+
+ return data
+
+ def getUserLoginsOvertime(self, date, prev_days=6):
+ dico_hours = {}
+ for curDate in util.getXPrevHoursSpan(date, prev_days*24):
+ dico_hours[util.getTimestamp(curDate)] = 0 # populate with empty data
+
+ for curDate in util.getXPrevDaysSpan(date, prev_days):
+ timestamps = self.getUserLogins(curDate)
+ for timestamp in timestamps: # sum occurence during the current hour
+ date = datetime.datetime.fromtimestamp(float(timestamp))
+ date = date.replace(minute=0, second=0, microsecond=0)
+ dico_hours[util.getTimestamp(date)] += 1
+
+ # Format data
+ data = []
+ for date, occ in dico_hours.items():
+ data.append([date, occ])
+
+ data.sort(key=lambda x: x[0])
+ return data
diff --git a/util.py b/util.py
index 8518554..535480e 100644
--- a/util.py
+++ b/util.py
@@ -24,8 +24,19 @@ def getXPrevDaysSpan(date, days):
to_return.append(de - datetime.timedelta(days=i))
return to_return
+def getXPrevHoursSpan(date, hours):
+ de = date
+ de = de.replace(minute=0, second=0, microsecond=0)
+ ds = de - datetime.timedelta(hours=hours)
+
+ delta = de - ds
+ to_return = []
+ for i in range(0, int(delta.total_seconds()/3600)+1):
+ to_return.append(de - datetime.timedelta(hours=i))
+ return to_return
+
def getDateStrFormat(date):
return str(date.year)+str(date.month).zfill(2)+str(date.day).zfill(2)
def getTimestamp(date):
- return time.mktime(date.timetuple())
+ return int(time.mktime(date.timetuple()))
diff --git a/zmq_subscriber.py b/zmq_subscriber.py
index 263a977..4369814 100755
--- a/zmq_subscriber.py
+++ b/zmq_subscriber.py
@@ -16,6 +16,7 @@ import geoip2.database
import util
import contributor_helper
+import users_helper
configfile = os.path.join(os.environ['DASH_CONFIG'], 'config.cfg')
cfg = configparser.ConfigParser()
@@ -53,6 +54,7 @@ serv_redis_db = redis.StrictRedis(
db=cfg.getint('RedisDB', 'db'))
contributor_helper = contributor_helper.Contributor_helper(serv_redis_db, cfg)
+users_helper = users_helper.Users_helper(serv_redis_db, cfg)
reader = geoip2.database.Reader(PATH_TO_DB)
@@ -194,10 +196,8 @@ def handler_user(zmq_name, jsondata):
timestamp = json_user['current_login']
except KeyError:
return
- now = datetime.datetime.now()
- today_str = util.getDateStrFormat(now)
- keyname = "{}:{}".format('USER_LOGIN', today_str)
- serv_redis_db.sadd(keyname, timestamp)
+ if timestamp != 0: # "invited_by": "xxxx" ???
+ users_helper.add_user_login(timestamp)
def handler_conversation(zmq_name, jsonevent):
try: #only consider POST, not THREAD