Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2013-11-10 14:52:29 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2013-11-10 14:52:29 (GMT)
commit01159008fb206678848479b4cb3e2409f8e0c49d (patch)
tree24e78655e55d870cf1a9e1a3c786f5665fe96d1e
parentbbe3047a973b66718cc01979459471ba36d91274 (diff)
Leave HTTP visits related stats conting to web server; reveal Context.dowloads and Artifact.downloads stats
-rwxr-xr-xmisc/aslo-sync4
-rw-r--r--sugar_network/model/artifact.py4
-rw-r--r--sugar_network/model/context.py6
-rw-r--r--sugar_network/node/stats_node.py82
-rwxr-xr-xtests/units/node/stats_node.py149
5 files changed, 42 insertions, 203 deletions
diff --git a/misc/aslo-sync b/misc/aslo-sync
index 828d5a9..4641d97 100755
--- a/misc/aslo-sync
+++ b/misc/aslo-sync
@@ -135,10 +135,6 @@ LICENSES_MAP = {
}
-class AbsDict(dict):
- pass
-
-
class Application(application.Application):
_my_connection = None
diff --git a/sugar_network/model/artifact.py b/sugar_network/model/artifact.py
index 5dba159..e461c4d 100644
--- a/sugar_network/model/artifact.py
+++ b/sugar_network/model/artifact.py
@@ -40,6 +40,10 @@ class Artifact(db.Resource):
def description(self, value):
return value
+ @db.indexed_property(slot=2, default=0, acl=ACL.READ | ACL.CALC)
+ def downloads(self, value):
+ return value
+
@db.indexed_property(slot=3, typecast=model.RATINGS, default=0,
acl=ACL.READ | ACL.CALC)
def rating(self, value):
diff --git a/sugar_network/model/context.py b/sugar_network/model/context.py
index e885b53..869ad6c 100644
--- a/sugar_network/model/context.py
+++ b/sugar_network/model/context.py
@@ -89,7 +89,11 @@ class Context(db.Resource):
'mime_type': 'image/png',
})
- @db.indexed_property(slot=3, typecast=model.RATINGS, default=0,
+ @db.indexed_property(slot=3, default=0, acl=ACL.READ | ACL.CALC)
+ def downloads(self, value):
+ return value
+
+ @db.indexed_property(slot=4, typecast=model.RATINGS, default=0,
acl=ACL.READ | ACL.CALC)
def rating(self, value):
return value
diff --git a/sugar_network/node/stats_node.py b/sugar_network/node/stats_node.py
index 6c24278..e21a8bd 100644
--- a/sugar_network/node/stats_node.py
+++ b/sugar_network/node/stats_node.py
@@ -76,6 +76,7 @@ class Sniffer(object):
class _ObjectStats(object):
+ downloads = 0
reviews = 0
rating = 0
@@ -92,6 +93,12 @@ class _Stats(object):
self._volume = volume
self._directory = volume[self.RESOURCE]
+ def __getitem__(self, guid):
+ result = self.active.get(guid)
+ if result is None:
+ result = self.active[guid] = _ObjectStats()
+ return result
+
def log(self, request):
context = None
@@ -122,20 +129,8 @@ class _Stats(object):
elif request.method == 'POST':
context = parse_context(request.content)
- if request.principal:
- stats = self._stats['user']
- if request.method in ('POST', 'PUT', 'DELETE'):
- stats.effective.add(request.principal)
- stats.active.add(request.principal)
-
if context:
- return self._stats['context'].active_object(context)
-
- def active_object(self, guid):
- result = self.active.get(guid)
- if result is None:
- result = self.active[guid] = _ObjectStats()
- return result
+ return self._stats['context'][context]
def commit(self):
pass
@@ -144,10 +139,6 @@ class _Stats(object):
class _ResourceStats(_Stats):
total = 0
- created = 0
- updated = 0
- deleted = 0
- viewed = 0
def __init__(self, stats, volume):
_Stats.__init__(self, stats, volume)
@@ -156,32 +147,29 @@ class _ResourceStats(_Stats):
def log(self, request):
result = _Stats.log(self, request)
- if request.method == 'GET':
- if request.guid and not request.prop:
- self.viewed += 1
- elif request.method == 'PUT':
- self.updated += 1
- elif request.method == 'POST':
+ if request.method == 'POST':
self.total += 1
- self.created += 1
elif request.method == 'DELETE':
self.total -= 1
- self.deleted += 1
return result
def commit(self):
if type(self.active) is dict:
for guid, stats in self.active.items():
- if not stats.reviews:
+ if not stats.reviews and not stats.downloads:
continue
- reviews, rating = self._directory.get(guid)['reviews']
- reviews += stats.reviews
- rating += stats.rating
- self._directory.update(guid, {
- 'reviews': [reviews, rating],
- 'rating': int(round(float(rating) / reviews)),
- })
+ doc = self._directory.get(guid)
+ updates = {}
+ if stats.downloads:
+ updates['downloads'] = stats.downloads + doc['downloads']
+ if stats.reviews:
+ reviews, rating = doc['reviews']
+ reviews += stats.reviews
+ rating += stats.rating
+ updates['reviews'] = [reviews, rating]
+ updates['rating'] = int(round(float(rating) / reviews))
+ self._directory.update(guid, updates)
result = {}
for attr in dir(self):
@@ -193,11 +181,6 @@ class _ResourceStats(_Stats):
if type(value) in (int, long):
result[attr] = value
- self.created = 0
- self.updated = 0
- self.deleted = 0
- self.viewed = 0
-
return result
@@ -205,17 +188,6 @@ class _UserStats(_ResourceStats):
RESOURCE = 'user'
- def __init__(self, stats, volume):
- _ResourceStats.__init__(self, stats, volume)
- self.active = set()
- self.effective = set()
-
- def commit(self):
- result = _ResourceStats.commit(self)
- self.active.clear()
- self.effective.clear()
- return result
-
class _ContextStats(_ResourceStats):
@@ -250,6 +222,8 @@ class _ImplementationStats(_Stats):
if request.method == 'GET':
if request.prop == 'data':
+ context = self._volume['implementation'].get(request.guid)
+ self._stats['context'][context.context].downloads += 1
self._stats['context'].downloaded += 1
elif request.method == 'POST':
self._stats['context'].released += 1
@@ -280,7 +254,7 @@ class _ReviewStats(_ResourceStats):
if request.method == 'POST':
if request.content.get('artifact'):
artifact = self._stats['artifact']
- stats = artifact.active_object(request.content['artifact'])
+ stats = artifact[request.content['artifact']]
artifact.reviewed += 1
else:
stats = context
@@ -300,9 +274,6 @@ class _FeedbackStats(_ResourceStats):
OWNERS = ['context']
solutions = 0
- solved = 0
- rejected = 0
-
commented = 0
def __init__(self, stats, volume):
@@ -317,16 +288,12 @@ class _FeedbackStats(_ResourceStats):
if request.method in ('POST', 'PUT'):
if 'solution' in request.content:
if request.content['solution'] is None:
- self.rejected += 1
self.solutions -= 1
else:
- self.solved += 1
self.solutions += 1
def commit(self):
result = _ResourceStats.commit(self)
- self.solved = 0
- self.rejected = 0
self.commented = 0
return result
@@ -361,6 +328,7 @@ class _ArtifactStats(_ResourceStats):
if request.method == 'GET':
if request.prop == 'data':
+ self[request.guid].downloads += 1
self.downloaded += 1
def commit(self):
diff --git a/tests/units/node/stats_node.py b/tests/units/node/stats_node.py
index 2fa9446..aaf953f 100755
--- a/tests/units/node/stats_node.py
+++ b/tests/units/node/stats_node.py
@@ -13,31 +13,6 @@ from sugar_network.toolkit.router import Request
class StatsTest(tests.Test):
- def ___test_DoNotLogAnonymouses(self):
- volume = db.Volume('local', model.RESOURCES)
- stats = Sniffer(volume)
-
- request = Request(method='GET', path=['context', 'guid'])
- stats.log(request)
- self.assertEqual(0, stats._stats['context'].viewed)
-
- request.principal = 'user'
- stats.log(request)
- self.assertEqual(1, stats._stats['context'].viewed)
-
- def test_DoNotLogCmds(self):
- volume = db.Volume('local', model.RESOURCES)
- stats = Sniffer(volume)
-
- request = Request(method='GET', path=['context', 'guid'], cmd='probe')
- request.principal = 'user'
- stats.log(request)
- self.assertEqual(0, stats._stats['context'].viewed)
-
- request.cmd = None
- stats.log(request)
- self.assertEqual(1, stats._stats['context'].viewed)
-
def test_InitializeTotals(self):
volume = db.Volume('local', model.RESOURCES)
@@ -77,23 +52,6 @@ class StatsTest(tests.Test):
stats.log(request)
stats.log(request)
self.assertEqual(3, stats._stats['context'].total)
- self.assertEqual(3, stats._stats['context'].created)
- self.assertEqual(0, stats._stats['context'].updated)
- self.assertEqual(0, stats._stats['context'].deleted)
-
- def test_PUTs(self):
- volume = db.Volume('local', model.RESOURCES)
- stats = Sniffer(volume)
-
- request = Request(method='PUT', path=['context', 'guid'])
- request.principal = 'user'
- stats.log(request)
- stats.log(request)
- stats.log(request)
- self.assertEqual(0, stats._stats['context'].total)
- self.assertEqual(0, stats._stats['context'].created)
- self.assertEqual(3, stats._stats['context'].updated)
- self.assertEqual(0, stats._stats['context'].deleted)
def test_DELETEs(self):
volume = db.Volume('local', model.RESOURCES)
@@ -105,27 +63,6 @@ class StatsTest(tests.Test):
stats.log(request)
stats.log(request)
self.assertEqual(-3, stats._stats['context'].total)
- self.assertEqual(0, stats._stats['context'].created)
- self.assertEqual(0, stats._stats['context'].updated)
- self.assertEqual(3, stats._stats['context'].deleted)
-
- def test_GETs(self):
- volume = db.Volume('local', model.RESOURCES)
- stats = Sniffer(volume)
-
- request = Request(method='GET', path=['user'])
- request.principal = 'user'
- stats.log(request)
- self.assertEqual(0, stats._stats['user'].viewed)
-
- def test_GETsDocument(self):
- volume = db.Volume('local', model.RESOURCES)
- stats = Sniffer(volume)
-
- request = Request(method='GET', path=['user', 'user'])
- request.principal = 'user'
- stats.log(request)
- self.assertEqual(1, stats._stats['user'].viewed)
def test_FeedbackSolutions(self):
volume = db.Volume('local', model.RESOURCES)
@@ -136,23 +73,14 @@ class StatsTest(tests.Test):
request.principal = 'user'
request.content = {}
stats.log(request)
- self.assertEqual(1, stats._stats['feedback'].updated)
- self.assertEqual(0, stats._stats['feedback'].rejected)
- self.assertEqual(0, stats._stats['feedback'].solved)
self.assertEqual(0, stats._stats['feedback'].solutions)
request.content = {'solution': 'solution'}
stats.log(request)
- self.assertEqual(2, stats._stats['feedback'].updated)
- self.assertEqual(0, stats._stats['feedback'].rejected)
- self.assertEqual(1, stats._stats['feedback'].solved)
self.assertEqual(1, stats._stats['feedback'].solutions)
request.content = {'solution': None}
stats.log(request)
- self.assertEqual(3, stats._stats['feedback'].updated)
- self.assertEqual(1, stats._stats['feedback'].rejected)
- self.assertEqual(1, stats._stats['feedback'].solved)
self.assertEqual(0, stats._stats['feedback'].solutions)
def test_Comments(self):
@@ -303,30 +231,6 @@ class StatsTest(tests.Test):
['1', '2', '3', '4', '5', '6', '7'],
sorted(stats._stats['context'].active.keys()))
- def test_UserActive(self):
- volume = db.Volume('local', model.RESOURCES)
- stats = Sniffer(volume)
-
- request = Request(method='GET', path=['user'])
- request.principal = '1'
- stats.log(request)
- self.assertEqual(
- set(['1']),
- stats._stats['user'].active)
- self.assertEqual(
- set([]),
- stats._stats['user'].effective)
-
- request = Request(method='POST', path=['user'])
- request.principal = '2'
- stats.log(request)
- self.assertEqual(
- set(['1', '2']),
- stats._stats['user'].active)
- self.assertEqual(
- set(['2']),
- stats._stats['user'].effective)
-
def test_ArtifactDownloaded(self):
volume = db.Volume('local', model.RESOURCES)
stats = Sniffer(volume)
@@ -335,13 +239,11 @@ class StatsTest(tests.Test):
request = Request(method='GET', path=['artifact', 'artifact', 'fake'])
request.principal = 'user'
stats.log(request)
- self.assertEqual(0, stats._stats['artifact'].viewed)
self.assertEqual(0, stats._stats['artifact'].downloaded)
request = Request(method='GET', path=['artifact', 'artifact', 'data'])
request.principal = 'user'
stats.log(request)
- self.assertEqual(0, stats._stats['artifact'].viewed)
self.assertEqual(1, stats._stats['artifact'].downloaded)
def test_Commit(self):
@@ -375,94 +277,51 @@ class StatsTest(tests.Test):
stats.log(request)
self.assertEqual(1, stats._stats['user'].total)
- self.assertEqual(1, stats._stats['user'].viewed)
- self.assertEqual(1, stats._stats['user'].viewed)
- self.assertEqual(set(['user']), stats._stats['user'].active)
self.assertEqual(1, stats._stats['context'].total)
- self.assertEqual(1, stats._stats['context'].viewed)
self.assertEqual(['context'], stats._stats['context'].active.keys())
self.assertEqual(1, stats._stats['review'].total)
- self.assertEqual(1, stats._stats['review'].viewed)
self.assertEqual(1, stats._stats['feedback'].total)
- self.assertEqual(1, stats._stats['feedback'].viewed)
self.assertEqual(1, stats._stats['solution'].total)
- self.assertEqual(1, stats._stats['solution'].viewed)
self.assertEqual(1, stats._stats['artifact'].total)
- self.assertEqual(1, stats._stats['artifact'].viewed)
ts = int(time.time())
stats.commit(ts)
self.assertEqual(1, stats._stats['user'].total)
- self.assertEqual(0, stats._stats['user'].viewed)
- self.assertEqual(set(), stats._stats['user'].active)
self.assertEqual(1, stats._stats['context'].total)
- self.assertEqual(0, stats._stats['context'].viewed)
self.assertEqual([], stats._stats['context'].active.keys())
self.assertEqual(1, stats._stats['review'].total)
- self.assertEqual(0, stats._stats['review'].viewed)
self.assertEqual(1, stats._stats['feedback'].total)
- self.assertEqual(0, stats._stats['feedback'].viewed)
self.assertEqual(1, stats._stats['solution'].total)
- self.assertEqual(0, stats._stats['solution'].viewed)
self.assertEqual(1, stats._stats['artifact'].total)
- self.assertEqual(0, stats._stats['artifact'].viewed)
self.assertEqual([
[('feedback', ts, {
- 'updated': 0.0,
- 'created': 0.0,
- 'deleted': 0.0,
- 'rejected': 0.0,
- 'solved': 0.0,
'solutions': 0.0,
'total': 1.0,
'commented': 0.0,
- 'viewed': 1.0,
})],
[('review', ts, {
- 'updated': 0.0,
- 'created': 0.0,
- 'deleted': 0.0,
'total': 1.0,
'commented': 0.0,
- 'viewed': 1.0,
})],
[('solution', ts, {
- 'updated': 0.0,
- 'created': 0.0,
- 'deleted': 0.0,
'total': 1.0,
'commented': 0.0,
- 'viewed': 1.0,
})],
[('artifact', ts, {
- 'updated': 0.0,
- 'created': 0.0,
- 'deleted': 0.0,
'reviewed': 0.0,
'downloaded': 0.0,
'total': 1.0,
- 'viewed': 1.0,
'active': 0.0,
})],
[('user', ts, {
- 'updated': 0.0,
- 'effective': 0.0,
- 'created': 0.0,
- 'deleted': 0.0,
- 'active': 1.0,
'total': 1.0,
- 'viewed': 1.0,
})],
[('context', ts, {
- 'updated': 0.0,
'failed': 0.0,
- 'deleted': 0.0,
- 'created': 0.0,
'reviewed': 0.0,
'downloaded': 0.0,
- 'viewed': 1.0,
'active': 1.0,
'total': 1.0,
'released': 0.0,
@@ -478,6 +337,7 @@ class StatsTest(tests.Test):
volume['implementation'].create({'guid': 'implementation', 'context': 'context', 'license': 'GPLv3', 'version': '1', 'date': 0, 'stability': 'stable', 'notes': ''})
volume['artifact'].create({'guid': 'artifact', 'type': 'instance', 'context': 'context', 'title': '', 'description': ''})
+ self.assertEqual(0, volume['context'].get('context')['downloads'])
self.assertEqual([0, 0], volume['context'].get('context')['reviews'])
self.assertEqual(0, volume['context'].get('context')['rating'])
@@ -495,11 +355,13 @@ class StatsTest(tests.Test):
stats.log(request)
stats.commit()
+ self.assertEqual(1, volume['context'].get('context')['downloads'])
self.assertEqual([1, 5], volume['context'].get('context')['reviews'])
self.assertEqual(5, volume['context'].get('context')['rating'])
stats.commit()
+ self.assertEqual(1, volume['context'].get('context')['downloads'])
self.assertEqual([1, 5], volume['context'].get('context')['reviews'])
self.assertEqual(5, volume['context'].get('context')['rating'])
@@ -513,6 +375,7 @@ class StatsTest(tests.Test):
stats.log(request)
stats.commit()
+ self.assertEqual(2, volume['context'].get('context')['downloads'])
self.assertEqual([2, 6], volume['context'].get('context')['reviews'])
self.assertEqual(3, volume['context'].get('context')['rating'])
@@ -523,6 +386,7 @@ class StatsTest(tests.Test):
volume['context'].create({'guid': 'context', 'type': 'activity', 'title': '', 'summary': '', 'description': ''})
volume['artifact'].create({'guid': 'artifact', 'type': 'instance', 'context': 'context', 'title': '', 'description': ''})
+ self.assertEqual(0, volume['artifact'].get('artifact')['downloads'])
self.assertEqual([0, 0], volume['artifact'].get('artifact')['reviews'])
self.assertEqual(0, volume['artifact'].get('artifact')['rating'])
@@ -536,11 +400,13 @@ class StatsTest(tests.Test):
stats.log(request)
stats.commit()
+ self.assertEqual(1, volume['artifact'].get('artifact')['downloads'])
self.assertEqual([1, 5], volume['artifact'].get('artifact')['reviews'])
self.assertEqual(5, volume['artifact'].get('artifact')['rating'])
stats.commit()
+ self.assertEqual(1, volume['artifact'].get('artifact')['downloads'])
self.assertEqual([1, 5], volume['artifact'].get('artifact')['reviews'])
self.assertEqual(5, volume['artifact'].get('artifact')['rating'])
@@ -553,6 +419,7 @@ class StatsTest(tests.Test):
stats.log(request)
stats.commit()
+ self.assertEqual(2, volume['artifact'].get('artifact')['downloads'])
self.assertEqual([2, 6], volume['artifact'].get('artifact')['reviews'])
self.assertEqual(3, volume['artifact'].get('artifact')['rating'])