Skip to content
This repository was archived by the owner on Mar 7, 2022. It is now read-only.

Commit aee9db9

Browse files
committed
bug fixes, exporting csv files
1 parent bb38dbe commit aee9db9

16 files changed

+259
-404
lines changed

FileWr.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from __future__ import with_statement
2+
3+
import logging
4+
from google.appengine.api import files
5+
from google.appengine.ext import db
6+
from google.appengine.ext import blobstore
7+
8+
class FileWr(db.Model):
9+
bkey = blobstore.BlobReferenceProperty(default=None)
10+
def append(self, filename, data):
11+
if self.bkey:
12+
blob_reader = blobstore.BlobReader(self.bkey)
13+
newblob = files.blobstore.create(mime_type='text/csv', _blobinfo_uploaded_filename=filename)
14+
with files.open(newblob, 'a') as f:
15+
if self.bkey:
16+
buf = blob_reader.read(1000000)
17+
while buf:
18+
f.write(buf)
19+
buf = blob_reader.read(1000000)
20+
logging.info("rewritting %d" % len(buf))
21+
f.write(data)
22+
logging.info("writing %d" % len(data))
23+
files.finalize(newblob)
24+
if self.bkey:
25+
self.bkey.delete()
26+
blobkey = files.blobstore.get_blob_key(newblob)
27+
self.bkey = blobkey
28+
self.put()
29+
def clear(self):
30+
self.bkey.delete()
31+
self.bkey = None
32+
self.put()
33+
def get(self):
34+
blob_reader = blobstore.BlobReader(self.bkey)
35+
return blob_reader.read()
36+

admin_ops.py

+13-150
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# You should have received a copy of the GNU General Public License along with ankidroid-triage.
1515
# If not, see http://www.gnu.org/licenses/.
1616
# #####
17+
from __future__ import with_statement
1718

1819
import os, sys, logging, re, hashlib, time
1920
from datetime import datetime
@@ -28,47 +29,35 @@
2829
settings._target = None
2930

3031
from google.appengine.ext import webapp
32+
from google.appengine.ext import db
33+
from google.appengine.ext import blobstore
3134
from google.appengine.ext.webapp.util import run_wsgi_app
3235
from google.appengine.ext.webapp import template
3336
from google.appengine.api.urlfetch import fetch
3437
from google.appengine.api.urlfetch import Error
3538
from google.appengine.api import taskqueue
3639
from google.appengine.api import memcache
40+
from google.appengine.api import files
41+
from google.appengine.ext.webapp import blobstore_handlers
3742

3843
from receive_ankicrashes import AppVersion
3944
from receive_ankicrashes import Feedback
4045
from receive_ankicrashes import CrashReport
41-
from receive_ankicrashes import HospitalizedReport
4246
from receive_ankicrashes import Bug
4347
from BeautifulSoup import BeautifulSoup
4448
from Cnt import Cnt
49+
from FileWr import FileWr
4550
from Lst import Lst
4651

47-
# Remove the standard version of Django
48-
#for k in [k for k in sys.modules if k.startswith('django')]:
49-
# del sys.modules[k]
5052
webapp.template.register_template_library('templatetags.basic_math')
5153

52-
class AdminOpsBackendManager(webapp.RequestHandler):
54+
class BlobSetter(webapp.RequestHandler):
5355
def get(self):
54-
vq = AppVersion.all()
55-
vq.order("-activeFrom")
56-
vo = vq.fetch(2000)
57-
vn = [v.name for v in vo]
58-
vn.insert(0, 'all')
59-
Lst.set("all_version_names_list", vn)
60-
61-
outputstr = repr(Lst.get("all_version_names_list"))
62-
self.response.out.write(outputstr)
63-
64-
def post(self):
65-
params = {'op': self.request.get('op'), 'cmd': self.request.get('cmd')}
66-
#taskqueue.add(queue_name='admin-ops-queue', url='/backend/testing', params=params, method='GET', target='admin-ops-handler')
67-
for i in range(1, 98):
68-
taskqueue.add(queue_name='admin-ops-queue', url='/backend/testing', params=params, method='GET')#, target='admin-ops-handler')
69-
70-
#time.sleep(5)
71-
#self.redirect('/admin_ops/backend')
56+
fwe = FileWr.get_by_key_name("export_csv")
57+
fwc = FileWr(key_name="crash_export_csv")
58+
fwc.bkey = fwe.bkey
59+
fwc.put()
60+
self.response.out.write("OK")
7261

7362
class ShowCrashBody(webapp.RequestHandler):
7463
def get(self):
@@ -82,135 +71,9 @@ def get(self):
8271
path = os.path.join(os.path.dirname(__file__), 'templates/admin_ops_show.html')
8372
self.response.out.write(template.render(path, template_values))
8473

85-
###
86-
# This class is used for bulk ad hoc operations in the DB, eg reparsing signatures, rebuilding the
87-
# bugs table or adding new properties to the entities.
88-
#
89-
# Due to limitations of time and memory in the AppEngine, we can't process all the entities in a
90-
# big loop, we have to work in batches. Each page loaded is a batch, following Next we can process
91-
# the next one, until all are done.
92-
##########
93-
class RebuildVersions(webapp.RequestHandler):
94-
batch_size = 400
95-
def get(self):
96-
batch = RebuildVersions.batch_size
97-
crashes_query = CrashReport.all()
98-
crashes = []
99-
page = int(self.request.get('page', 0))
100-
if page == 0:
101-
# Reset appVersion crashCount & lastIncident
102-
versions_query = AppVersion.all()
103-
versions = versions_query.fetch(2000)
104-
for v in versions:
105-
v.crashCount = 0
106-
v.lastIncident = datetime(2000,1,1)
107-
v.put()
108-
109-
total_results = crashes_query.count(1000000)
110-
logging.info("Admin ops - total_results: ", total_results)
111-
last_page = max((total_results - 1) // batch, 0)
112-
if page > last_page:
113-
page = last_page
114-
crashes = crashes_query.fetch(batch, page * batch)
115-
versionCounts = {}
116-
versionLastIncidents = {}
117-
for cr in crashes:
118-
vname = cr.versionName.strip()
119-
if cr.versionName <> vname:
120-
cr.versionName = vname
121-
cr.put()
122-
if vname in versionCounts:
123-
versionCounts[vname] = versionCounts[vname] + 1
124-
else:
125-
versionCounts[vname] = 1
126-
127-
if cr.versionName in versionLastIncidents:
128-
if versionLastIncidents[vname] < cr.crashTime:
129-
versionLastIncidents[vname] = cr.crashTime
130-
else:
131-
versionLastIncidents[vname] = cr.crashTime
132-
133-
for vname in versionCounts:
134-
versions_query = AppVersion.all()
135-
versions_query.filter('name =', vname)
136-
versions = versions_query.fetch(1)
137-
if versions:
138-
version = versions[0]
139-
version.crashCount = version.crashCount + versionCounts[vname]
140-
if version.lastIncident < versionLastIncidents[vname]:
141-
version.lastIncident = versionLastIncidents[vname]
142-
version.put()
143-
else:
144-
logging.info("missing version: " + vname)
145-
146-
template_values = {
147-
'values': versionCounts,
148-
'page': page,
149-
'last_page': last_page,
150-
'page_size': batch,
151-
'op_link': 'rebuild_versions',
152-
'column_key': 'Version',
153-
'column_value': 'Count',
154-
'page_results': len(crashes),
155-
'total_results': total_results}
156-
path = os.path.join(os.path.dirname(__file__), 'templates/admin_ops.html')
157-
self.response.out.write(template.render(path, template_values))
158-
159-
class RebuildBugs(webapp.RequestHandler):
160-
def get(self):
161-
batch = RebuildBugs.batch_size
162-
crashes_query = CrashReport.all()
163-
crashes = []
164-
page = int(self.request.get('page', 0))
165-
if page == 0:
166-
# Remove Bugs
167-
bugs_query = Bug.all()
168-
bugs = bugs_query.fetch(2000)
169-
for b in bugs:
170-
b.delete()
171-
172-
total_results = crashes_query.count(1000000)
173-
last_page = max((total_results - 1) // batch, 0)
174-
if page > last_page:
175-
page = last_page
176-
logging.info("Admin ops - total_results: ", str(total_results) + ", page: " + str(page) + "/" + str(last_page))
177-
crashes = crashes_query.fetch(batch, page * batch)
178-
valueSet = {}
179-
valueSet["unlinked"] = 0
180-
# Main ops loop
181-
for cr in crashes:
182-
cr.bugKey = None
183-
cr.crashSignature = CrashReport.getCrashSignature(cr.report)
184-
cr.put()
185-
if cr.crashSignature == '\n':
186-
logging.warning("Can't get signature for CrashReport: " + str(cr.key().id()))
187-
valueSet["unlinked"] = valueSet["unlinked"] + 1
188-
else:
189-
cr.signHash = hashlib.sha1(cr.crashSignature).hexdigest()
190-
cr.linkToBug()
191-
bugId = str(cr.bugKey.key().id())
192-
if bugId in valueSet:
193-
valueSet[bugId] = valueSet[bugId] + 1
194-
else:
195-
valueSet[bugId] = 1
196-
template_values = {
197-
'values': valueSet,
198-
'page': page,
199-
'last_page': last_page,
200-
'page_size': batch,
201-
'op_link': 'rebuild_bugs',
202-
'column_key': 'BugId',
203-
'column_value': 'Count',
204-
'page_results': len(crashes),
205-
'total_results': total_results}
206-
path = os.path.join(os.path.dirname(__file__), 'templates/admin_ops.html')
207-
self.response.out.write(template.render(path, template_values))
208-
20974
application = webapp.WSGIApplication(
21075
[(r'^/admin_show.*$', ShowCrashBody),
211-
(r'^/admin_ops/rebuild_versions$', RebuildVersions),
212-
#(r'^/admin_ops/rebuild_bugs$', RebuildBugs)],
213-
(r'^/admin_ops/backend.*$', AdminOpsBackendManager)],
76+
(r'^/admin_ops/bset.*$', BlobSetter)],
21477
debug=True)
21578

21679
def main():

app.yaml

+2-10
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,13 @@ handlers:
1515
- url: /css
1616
static_dir: css
1717

18-
#- url: /_ah/mail/ankidroid_crash_reports@ankidroid-triage\.appspotmail\.com.*
19-
# script: receive_ankicrashes.py
20-
# login: admin
21-
2218
- url: /admin_.*
2319
script: admin_ops.py
2420
login: admin
2521

26-
- url: /backend/testing
22+
- url: /backend/append_export
2723
script: backends.py
28-
#login: admin
24+
login: admin
2925

3026
- url: /cron_updater.*
3127
script: cron_updater.py
@@ -44,10 +40,6 @@ handlers:
4440
- url: /.*
4541
script: report_ankicrashes.py
4642

47-
48-
inbound_services:
49-
- mail
50-
5143
builtins:
5244
- datastore_admin: on
5345

0 commit comments

Comments
 (0)