Home | History | Annotate | Download | only in docs
      1 # Code Snippets
      2 
      3 It is possible to directly execute code on a production instance of the performance dashboard. This is one way to directly query information about the state of the datastore, and make quick adjustments to data in the datastore.
      4 
      5 There are two places where production code can be run (admins only):
      6 
      7  - https://chromeperf.appspot.com/\_ah/dev\_console/interactive
      8  - https://chromeperf.appspot.com/\_ah/stats/shell
      9 
     10 ## List tests frequently marked as invalid
     11 
     12 ```python
     13 import collections
     14 from google.appengine.ext import ndb
     15 from speed.dashboard import utils
     16 from dashboard.models import anomaly
     17 
     18 sheriff = ndb.Key('Sheriff', 'Chromium Perf Sheriff')
     19 query = anomaly.Anomaly.query(anomaly.Anomaly.bug_id == -1)
     20 query = query.filter(anomaly.Anomaly.sheriff == sheriff)
     21 query = query.order(-anomaly.Anomaly.timestamp)
     22 alerts = query.fetch(limit=5000)
     23 
     24 total_alerts = len(alerts)
     25 print 'Fetched {} "invalid" alerts.'.format(len(alerts))
     26 
     27 occurrences = [[], [], []]
     28 for a in alerts:
     29   parts = utils.TestPath(a.test).split('/', 3)[1:]
     30     for i, part in enumerate(parts):
     31       occurrences[i].append(part)
     32 
     33 types = ['bot', 'benchmark', 'subtest']
     34 counters = [(type, collections.Counter(x)) for type, x in zip(types, occurrences)]
     35 for type, counter in counters:
     36   print 'nTop {}s marked invalid:'.format(type)
     37     print ' {0:>5} {1:>13} {2}'.format('Count', '% of invalid', 'Name')
     38     for name, count in counter.most_common(10):
     39       percent = 100 * float(count) / total_alerts
     40         print ' {0:>5} {1:>12}% {2}'.format(count, percent, name)
     41 ```
     42 
     43 ## List unique test suite names
     44 
     45 ```python
     46 from dashboard.models import graph_data
     47 
     48 LIMIT = 10000
     49 
     50 query = graph_data.Test.query(graph_data.Test.parent_test == None)
     51 test_keys = query.fetch(limit=LIMIT, keys_only=True)
     52 unique = sorted(set(k.string_id() for k in test_keys))
     53 print 'Fetched %d Test keys, %d unique names.' % (len(test_keys), len(unique))
     54 for name in unique:
     55   print name
     56 ```
     57 
     58 ## List deprecated test suites
     59 
     60 ```python
     61 from dashboard import utils
     62 from dashboard.models import graph_data
     63 
     64 LIMIT = 10000
     65 
     66 query = graph_data.Test.query(
     67     graph_data.Test.parent_test == None,
     68         graph_data.Test.deprecated == True)
     69         test_keys = query.fetch(limit=LIMIT, keys_only=True)
     70     print 'Fetched %d Test keys.' % len(test_keys)
     71 for key in test_keys:
     72   print utils.TestPath(key)
     73 ```
     74 
     75 ## List all sub-tests of a particular test
     76 
     77 ```python
     78 from google.appengine.ext import ndb
     79 from dashboard import utils
     80 from dashboard.models import graph_data
     81 
     82 ancestor = utils.TestKey('ChromiumPerf/linux-release/sunspider')
     83 keys = graph_data.Test.query(ancestor=ancestor).fetch(keys_only=True)
     84 
     85 print 'Fetched %d keys.' % len(keys)
     86 for key in keys:
     87   print utils.TestPath(key)
     88 ```
     89 
     90 ## Delete a particular sheriff or other entity
     91 
     92 ```python
     93 from google.appengine.ext import ndb
     94 
     95 key = ndb.Key('Sheriff', 'Sheriff name')
     96 print 'Deleting: %s\n%s' % (key.string_id(), key.get())
     97 key.delete()
     98 ```
     99 
    100 ## Clear the LastAddedRevision entities for a Test
    101 
    102 This allows point IDs that are much higher or lower to be posted.
    103 
    104 ```python
    105 from google.appengine.ext import ndb
    106 from dashboard import utils
    107 from dashboard.models import graph_data
    108 
    109 ancestor_key = utils.TestKey('Master/bot/test')
    110 test_query = graph_data.Test.query(ancestor=ancestor_key)
    111 test_keys = test_query.fetch(keys_only=True)
    112 to_delete = []
    113 for test_key in test_keys:
    114   to_delete.append(ndb.Key('LastAddedRevision', utils.TestPath(test_key)))
    115 print 'Deleting up to %d LastAddedRevision entities.' % len(to_delete)
    116 ndb.delete_multi(to_delete)
    117 ```
    118 
    119 ## Delete a few specific points (dangerous)
    120 
    121 ```python
    122 from google.appengine.ext import ndb
    123 from dashboard.models import graph_data
    124 
    125 POINTIDS = []
    126 TEST_PATHS = []
    127 
    128 to_delete = []
    129 for id in IDS:
    130   for path in TEST_PATHS:
    131     to_delete.append(ndb.Key('TestContainer', path, 'Row', id))
    132 
    133 print 'Deleting %d rows.' % len(to_delete)
    134 ndb.delete_multi(to_delete)
    135 ```
    136 
    137 ## Delete Rows and Tests under a particular Master or Bot (dangerous)
    138 
    139 ```python
    140 from google.appengine.ext import ndb
    141 from dashboard import utils
    142 from dashboard.models import graph_data
    143 
    144 ancestor_key = utils.TestKey('ChromiumEndure')
    145 test_keys = graph_data.Test.query(ancestor=ancestor_key).fetch(keys_only=True)
    146 print len(test_keys)
    147 to_delete = []
    148 for test_key in test_keys:
    149   row_keys = graph_data.Row.query(
    150       graph_data.Row.parent_test == test_key).fetch(keys_only=True, limit=100)
    151   to_delete.extend(row_keys)
    152   if not row_keys:
    153     to_delete.append(test_key)
    154 print len(to_delete)
    155 ndb.delete_multi(to_delete[:1000])
    156 ```
    157