Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: tools/metrics/actions/extract_actions.py

Issue 848453002: Improve script to find user actions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Extract UserMetrics "actions" strings from the Chrome source. 7 """Extract UserMetrics "actions" strings from the Chrome source.
8 8
9 This program generates the list of known actions we expect to see in the 9 This program generates the list of known actions we expect to see in the
10 user behavior logs. It walks the Chrome source, looking for calls to 10 user behavior logs. It walks the Chrome source, looking for calls to
11 UserMetrics functions, extracting actions and warning on improper calls, 11 UserMetrics functions, extracting actions and warning on improper calls,
12 as well as generating the lists of possible actions in situations where 12 as well as generating the lists of possible actions in situations where
13 there are many possible actions. 13 there are many possible actions.
14 14
15 See also: 15 See also:
16 base/metrics/user_metrics.h 16 base/metrics/user_metrics.h
17 http://wiki.corp.google.com/twiki/bin/view/Main/ChromeUserExperienceMetrics
18 17
19 After extracting all actions, the content will go through a pretty print 18 After extracting all actions, the content will go through a pretty print
20 function to make sure it's well formatted. If the file content needs to be 19 function to make sure it's well formatted. If the file content needs to be
21 changed, a window will be prompted asking for user's consent. The old version 20 changed, a window will be prompted asking for user's consent. The old version
22 will also be saved in a backup file. 21 will also be saved in a backup file.
23 """ 22 """
24 23
25 __author__ = 'evanm (Evan Martin)' 24 __author__ = 'evanm (Evan Martin)'
26 25
27 from HTMLParser import HTMLParser 26 from HTMLParser import HTMLParser
28 import logging 27 import logging
29 import os 28 import os
30 import re 29 import re
31 import shutil 30 import shutil
32 import sys 31 import sys
33 from xml.dom import minidom 32 from xml.dom import minidom
34 33
35 import print_style 34 import print_style
36 35
37 sys.path.insert(1, os.path.join(sys.path[0], '..', '..', 'python')) 36 sys.path.insert(1, os.path.join(sys.path[0], '..', '..', 'python'))
38 from google import path_utils 37 from google import path_utils
39 38
40 # Import the metrics/common module for pretty print xml. 39 # Import the metrics/common module for pretty print xml.
41 sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common')) 40 sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common'))
42 import diff_util 41 import diff_util
43 import pretty_print_xml 42 import pretty_print_xml
44 43
44 USER_METRICS_ACTION_RE = re.compile(r'UserMetricsAction\(\s*(.+?)\)')
Ilya Sherman 2015/01/09 22:25:43 nit: I think it might be worth using the verbose r
Ilya Sherman 2015/01/09 22:25:44 It looks like you've changed the regexes quite a b
Alexei Svitkine (slow) 2015/01/12 19:58:24 I've re-added it now.
Alexei Svitkine (slow) 2015/01/12 19:58:24 Done.
45 COMPUTED_ACTION_RE = re.compile(r'RecordComputedAction')
46 QUOTED_STRING_RE = re.compile(r'\"(.+?)\"')
47
45 # Files that are known to use content::RecordComputedAction(), which means 48 # Files that are known to use content::RecordComputedAction(), which means
46 # they require special handling code in this script. 49 # they require special handling code in this script.
47 # To add a new file, add it to this list and add the appropriate logic to 50 # To add a new file, add it to this list and add the appropriate logic to
48 # generate the known actions to AddComputedActions() below. 51 # generate the known actions to AddComputedActions() below.
49 KNOWN_COMPUTED_USERS = ( 52 KNOWN_COMPUTED_USERS = (
50 'back_forward_menu_model.cc', 53 'back_forward_menu_model.cc',
51 'options_page_view.cc', 54 'options_page_view.cc',
52 'render_view_host.cc', # called using webkit identifiers 55 'render_view_host.cc', # called using webkit identifiers
53 'user_metrics.cc', # method definition 56 'user_metrics.cc', # method definition
54 'new_tab_ui.cc', # most visited clicks 1-9 57 'new_tab_ui.cc', # most visited clicks 1-9
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 actions.add('ConnectivityDiagnostics.LaunchSource.WebStore') 406 actions.add('ConnectivityDiagnostics.LaunchSource.WebStore')
404 actions.add('ConnectivityDiagnostics.UA.LogsShown') 407 actions.add('ConnectivityDiagnostics.UA.LogsShown')
405 actions.add('ConnectivityDiagnostics.UA.PassingTestsShown') 408 actions.add('ConnectivityDiagnostics.UA.PassingTestsShown')
406 actions.add('ConnectivityDiagnostics.UA.SettingsShown') 409 actions.add('ConnectivityDiagnostics.UA.SettingsShown')
407 actions.add('ConnectivityDiagnostics.UA.TestResultExpanded') 410 actions.add('ConnectivityDiagnostics.UA.TestResultExpanded')
408 actions.add('ConnectivityDiagnostics.UA.TestSuiteRun') 411 actions.add('ConnectivityDiagnostics.UA.TestSuiteRun')
409 412
410 # Actions sent by 'Ok Google' Hotwording. 413 # Actions sent by 'Ok Google' Hotwording.
411 actions.add('Hotword.HotwordTrigger') 414 actions.add('Hotword.HotwordTrigger')
412 415
416 def FindActionNames(contents, pos):
417 """Finds actions from the first UserMetricsAction() call in |contents|.
418
419 Arguments:
420 contents: string to search through
421 pos: position in |contents| to start the search from
422
423 Returns:
424 The list action names (strings) that was found.
Ilya Sherman 2015/01/09 22:25:43 Please update this -- it looks like there are two
Alexei Svitkine (slow) 2015/01/12 19:58:24 Done.
425 """
426 match = USER_METRICS_ACTION_RE.search(contents, pos=pos)
427 if not match:
428 return None, None
429 return QUOTED_STRING_RE.findall(match.group(1)), match.end()
430
413 def GrepForActions(path, actions): 431 def GrepForActions(path, actions):
414 """Grep a source file for calls to UserMetrics functions. 432 """Grep a source file for calls to UserMetrics functions.
415 433
416 Arguments: 434 Arguments:
417 path: path to the file 435 path: path to the file
418 actions: set of actions to add to 436 actions: set of actions to add to
419 """ 437 """
420 global number_of_files_total 438 global number_of_files_total
421 number_of_files_total = number_of_files_total + 1 439 number_of_files_total = number_of_files_total + 1
422 # we look for the UserMetricsAction structure constructor 440
423 # this should be on one line 441 contents = open(path).read()
424 action_re = re.compile(r'[^a-zA-Z]UserMetricsAction\("([^"]*)') 442 pos = 0
425 malformed_action_re = re.compile(r'[^a-zA-Z]UserMetricsAction\([^"]') 443 while True:
426 computed_action_re = re.compile(r'RecordComputedAction') 444 action_names, pos = FindActionNames(contents, pos)
445 if not action_names:
446 break
447 actions.update(action_names)
448
427 line_number = 0 449 line_number = 0
428 for line in open(path): 450 for line in open(path):
429 line_number = line_number + 1 451 line_number = line_number + 1
430 match = action_re.search(line) 452 if COMPUTED_ACTION_RE.search(line):
431 if match: # Plain call to RecordAction
432 actions.add(match.group(1))
433 elif malformed_action_re.search(line):
434 # Warn if this line is using RecordAction incorrectly.
435 print >>sys.stderr, ('WARNING: %s has malformed call to RecordAction'
436 ' at %d' % (path, line_number))
437 elif computed_action_re.search(line):
438 # Warn if this file shouldn't be calling RecordComputedAction. 453 # Warn if this file shouldn't be calling RecordComputedAction.
439 if os.path.basename(path) not in KNOWN_COMPUTED_USERS: 454 if os.path.basename(path) not in KNOWN_COMPUTED_USERS:
440 print >>sys.stderr, ('WARNING: %s has RecordComputedAction at %d' % 455 print >>sys.stderr, ('WARNING: %s has RecordComputedAction at %d' %
441 (path, line_number)) 456 (path, line_number))
442 457
443 class WebUIActionsParser(HTMLParser): 458 class WebUIActionsParser(HTMLParser):
444 """Parses an HTML file, looking for all tags with a 'metric' attribute. 459 """Parses an HTML file, looking for all tags with a 'metric' attribute.
445 Adds user actions corresponding to any metrics found. 460 Adds user actions corresponding to any metrics found.
446 461
447 Arguments: 462 Arguments:
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 829
815 with open(actions_xml_path, 'wb') as f: 830 with open(actions_xml_path, 'wb') as f:
816 f.write(pretty) 831 f.write(pretty)
817 print ('Updated %s. Don\'t forget to add it to your changelist' % 832 print ('Updated %s. Don\'t forget to add it to your changelist' %
818 actions_xml_path) 833 actions_xml_path)
819 return 0 834 return 0
820 835
821 836
822 if '__main__' == __name__: 837 if '__main__' == __name__:
823 sys.exit(main(sys.argv)) 838 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | tools/metrics/actions/extract_actions_test.py » ('j') | tools/metrics/actions/extract_actions_test.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698