Added login overtime + users_helper script

pull/8/head
Sami Mokaddem 2017-11-15 09:36:44 +01:00
parent 2f74406f64
commit c1105aba73
5 changed files with 177 additions and 53 deletions

View File

@ -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 '''

View File

@ -24,6 +24,7 @@
<script src="{{ url_for('static', filename='js/jquery.flot.js') }}"></script>
<script src="{{ url_for('static', filename='js/jquery.flot.pie.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/jquery.flot.resize.js') }}"></script>
<script src="{{ url_for('static', filename='js/jquery.flot.time.js') }}"></script>
<!-- Bootstrap Core JavaScript -->
<script src="{{ url_for('static', filename='js/bootstrap.js') }}"></script>
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="text/css">
@ -104,29 +105,50 @@ small {
<div class="row">
<div style="height: 10px;"></div>
<div class="col-lg-8">
<div class="panel panel-default" style="">
<div class="panel-heading bg-info" style="font-weight: bold;">
<b>Punch card - login</b>
</div>
<div id="panelbody" class="panel-body" style="">
<div id="punchcard" style="width:100%; height: 100%;"></div>
</div>
</div><!-- /.panel-body -->
</div>
<div class="col-lg-12">
<div class="col-lg-8">
<div class="panel panel-default" style="">
<div class="panel-heading bg-info" style="font-weight: bold;">
<b>Punch card - login</b>
</div>
<div id="panelbody" class="panel-body" style="">
<div id="punchcard" style="width:100%; height: 100%;"></div>
</div>
</div><!-- /.panel-body -->
</div>
<div class="col-lg-4">
<div class="panel panel-default" style="">
<div class="panel-heading bg-info" style="font-weight: bold;">
<b>Contribution after login (API vs non-API)</b>
</div>
<div id="panelbody" class="panel-body" style="">
<div id="pieChart" style="width:100%; height: 20vh;"></div>
</div>
</div><!-- /.panel-body -->
</div>
<div class="col-lg-4">
<div class="panel panel-default" style="">
<div class="panel-heading bg-info" style="font-weight: bold;">
<b>Top login per organisation</b>
</div>
<div id="panelbody" class="panel-body" style="">
<div id="barChart" style="width:100%; height: 20vh;"></div>
</div>
</div><!-- /.panel-body -->
<div class="panel panel-default" style="">
<div class="panel-heading bg-info" style="font-weight: bold;">
<b>Contribution after login (API vs non-API)</b>
</div>
<div id="panelbody" class="panel-body" style="">
<div id="pieChart" style="width:100%; height: 20vh;"></div>
</div>
</div><!-- /.panel-body -->
</div>
</div><!-- /.col-lg-12 -->
<div class="col-lg-12">
<div class="panel panel-default" style="">
<div class="panel-heading bg-info" style="font-weight: bold;">
<b>Login overtime</b>
</div>
<div id="panelbody" class="panel-body" style="">
<div id="lineChart" style="width:100%; height: 20vh;"></div>
</div>
</div><!-- /.panel-body -->
</div><!-- /.col-lg-12 -->
</div><!-- /.row -->
</div> <!-- /.container-fluid -->
@ -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"],
}
});
});
});
</script>

73
users_helper.py Normal file
View File

@ -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

13
util.py
View File

@ -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()))

View File

@ -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