OLD | NEW |
---|---|
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import contextlib | 5 import contextlib |
6 import datetime | 6 import datetime |
7 import datetime_encoder | 7 import datetime_encoder |
8 import json | 8 import json |
9 import logging | 9 import logging |
10 import urllib | 10 import urllib |
11 import webapp2 | 11 import webapp2 |
12 import zlib | 12 import zlib |
13 | 13 |
14 import cloudstorage as gcs | 14 import cloudstorage as gcs |
15 | 15 |
16 from google.appengine.api import app_identity | 16 from google.appengine.api import app_identity |
17 from google.appengine.api import memcache | 17 from google.appengine.api import memcache |
18 from google.appengine.api import modules | |
19 from google.appengine.api import urlfetch | |
18 from google.appengine.api import users | 20 from google.appengine.api import users |
19 from google.appengine.datastore import datastore_query | 21 from google.appengine.datastore import datastore_query |
20 from google.appengine.ext import ndb | 22 from google.appengine.ext import ndb |
21 | 23 |
22 LOGGER = logging.getLogger(__name__) | 24 LOGGER = logging.getLogger(__name__) |
23 | 25 |
24 | 26 |
25 class AlertsJSON(ndb.Model): | 27 class AlertsJSON(ndb.Model): |
26 type = ndb.StringProperty() | 28 type = ndb.StringProperty() |
27 json = ndb.BlobProperty(compressed=True) | 29 json = ndb.BlobProperty(compressed=True) |
28 date = ndb.DateTimeProperty(auto_now_add=True) | 30 date = ndb.DateTimeProperty(auto_now_add=True) |
29 # TODO(remove this property) | 31 # TODO(remove this property) |
30 use_gcs = ndb.BooleanProperty() | 32 use_gcs = ndb.BooleanProperty() |
31 gcs_filename = ndb.StringProperty() | 33 gcs_filename = ndb.StringProperty() |
32 | 34 |
33 | 35 |
34 class LastUpdated(ndb.Model): | 36 class LastUpdated(ndb.Model): |
35 date = ndb.DateTimeProperty(auto_now=True) | 37 date = ndb.DateTimeProperty(auto_now=True) |
36 type = ndb.StringProperty() | 38 type = ndb.StringProperty() |
37 haddiff = ndb.BooleanProperty() | 39 haddiff = ndb.BooleanProperty() |
38 | 40 |
39 | 41 |
42 def increment_monarch(endpoint): | |
agable
2015/08/10 23:04:37
Might be nice to implement this somewhere more gen
| |
43 base_url = app_identity.get_default_version_hostname() | |
44 url = 'http://%s-dot-%s/monitoring/%s' % ('monitoring', base_url, endpoint) | |
45 logging.info(url) | |
agable
2015/08/10 23:04:37
Log a more useful message here :) or nothing at al
| |
46 return urlfetch.fetch(url=url, method=urlfetch.GET) | |
agable
2015/08/10 23:04:37
Using GET here makes me a very sad panda. You neve
jshu
2015/08/11 21:57:18
lol yea put didn't work either. ok.
| |
47 | |
48 | |
40 class AlertsHandler(webapp2.RequestHandler): | 49 class AlertsHandler(webapp2.RequestHandler): |
41 ALERT_TYPE = 'alerts' | 50 ALERT_TYPE = 'alerts' |
42 # Max number of bytes that AppEngine allows writing to Memcache | 51 # Max number of bytes that AppEngine allows writing to Memcache |
43 MAX_JSON_SIZE = 10**6 - 10**5 | 52 MAX_JSON_SIZE = 10**6 - 10**5 |
44 | 53 |
45 # New alerts should be posted at least every 30 minutes | 54 # New alerts should be posted at least every 30 minutes |
46 MAX_STALENESS = 60*30 | 55 MAX_STALENESS = 60*30 |
47 | 56 |
48 # Has no 'response' member. | 57 # Has no 'response' member. |
49 # pylint: disable=E1101 | 58 # pylint: disable=E1101 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 def get_from_memcache(self): | 126 def get_from_memcache(self): |
118 compressed = memcache.get(self.ALERT_TYPE) | 127 compressed = memcache.get(self.ALERT_TYPE) |
119 if compressed: | 128 if compressed: |
120 logging.info('Reading alerts from memcache') | 129 logging.info('Reading alerts from memcache') |
121 uncompressed = zlib.decompress(compressed) | 130 uncompressed = zlib.decompress(compressed) |
122 data = json.loads(uncompressed) | 131 data = json.loads(uncompressed) |
123 return data | 132 return data |
124 return False | 133 return False |
125 | 134 |
126 def get(self): | 135 def get(self): |
136 increment_monarch('alerts') | |
127 data = self.get_from_memcache() or self.get_from_datastore() | 137 data = self.get_from_memcache() or self.get_from_datastore() |
128 if data: | 138 if data: |
129 self.send_json_data(data) | 139 self.send_json_data(data) |
130 else: | 140 else: |
131 self.response.write({}) | 141 self.response.write({}) |
132 | 142 |
133 def store_alerts(self, alerts): | 143 def store_alerts(self, alerts): |
134 last_entry = self.get_last_datastore(self.ALERT_TYPE) | 144 last_entry = self.get_last_datastore(self.ALERT_TYPE) |
135 last_alerts = {} | 145 last_alerts = {} |
136 if last_entry: | 146 if last_entry: |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 alerts.update({'date': datetime.datetime.utcnow()}) | 198 alerts.update({'date': datetime.datetime.utcnow()}) |
189 self.store_alerts(alerts) | 199 self.store_alerts(alerts) |
190 | 200 |
191 def post(self): | 201 def post(self): |
192 self.update_alerts() | 202 self.update_alerts() |
193 | 203 |
194 | 204 |
195 class NewAlertsHandler(AlertsHandler): | 205 class NewAlertsHandler(AlertsHandler): |
196 # pylint: disable=arguments-differ | 206 # pylint: disable=arguments-differ |
197 def get(self, tree): | 207 def get(self, tree): |
208 increment_monarch('api/v1/alerts') | |
198 self.ALERT_TYPE = 'new-alerts/%s' % tree | 209 self.ALERT_TYPE = 'new-alerts/%s' % tree |
199 super(NewAlertsHandler, self).get() | 210 super(NewAlertsHandler, self).get() |
200 | 211 |
201 # pylint: disable=arguments-differ | 212 # pylint: disable=arguments-differ |
202 def post(self, tree): | 213 def post(self, tree): |
203 self.ALERT_TYPE = 'new-alerts/%s' % tree | 214 self.ALERT_TYPE = 'new-alerts/%s' % tree |
204 super(NewAlertsHandler, self).post() | 215 super(NewAlertsHandler, self).post() |
205 | 216 |
206 | 217 |
207 app = webapp2.WSGIApplication([ | 218 app = webapp2.WSGIApplication([ |
208 ('/alerts', AlertsHandler), | 219 ('/alerts', AlertsHandler), |
209 ('/api/v1/alerts/(.*)', NewAlertsHandler) | 220 ('/api/v1/alerts/(.*)', NewAlertsHandler) |
210 ]) | 221 ]) |
OLD | NEW |