{"action":"created","comment":{"url":"https://api.github.com/repos/oppia/oppia/pulls/comments/67597768","id":67597768,"diff_hunk":"@@ -0,0 +1,229 @@\n+# Copyright 2016 The Oppia Authors. All Rights Reserved.\n+#\n+# Licensed under the Apache License, Version 2.0 (the \"License\");\n+# you may not use this file except in compliance with the License.\n+# You may obtain a copy of the License at\n+#\n+#      http://www.apache.org/licenses/LICENSE-2.0\n+#\n+# Unless required by applicable law or agreed to in writing, software\n+# distributed under the License is distributed on an \"AS-IS\" BASIS,\n+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+# See the License for the specific language governing permissions and\n+# limitations under the License.\n+\n+\"\"\"Contains a utility for fetching performance data using Selenium and\n+Browsermob-proxy.\n+\"\"\"\n+\n+import os\n+import time\n+import urlparse\n+from browsermobproxy import Server\n+from selenium import webdriver\n+\n+# Used for headless testing i.e, making browser windows invisible to the user.\n+from xvfbwrapper import Xvfb\n+\n+from core.tests.performance_framework import perf_domain\n+\n+CHROME_DRIVER_PATH = os.path.join(\n+    '..', 'node_modules', 'protractor', 'selenium', 'chromedriver_2.21')\n+\n+BROWSERMOB_PROXY_PATH = os.path.join(\n+    '..', 'oppia_tools', 'browsermob-proxy-2.1.1', 'bin', 'browsermob-proxy')\n+\n+\n+class SeleniumPerformanceDataFetcher(object):\n+    \"\"\"Fetches performance data for locally served Oppia pages using Selenium\n+    and Browsermob-proxy.\n+\n+    Selenium is used to programitically interact with a browser.\n+    Browsermob-proxy is used to capture HTTP Archive (referred to as HAR) data.\n+\n+    The HTTP Archive format is a JSON-formatted archive file format used for\n+    logging a web browser's interaction with a site. It contains detailed\n+    performance data, including information about page loading and displaying\n+    and per-resource statistics. Each entry contains the URL requested and\n+    request and response headers. For additional details, please see:\n+    https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HAR/Overview.html\n+\n+    The HTTP Archive data is retrieved using the proxy server by recording the\n+    communication between the client and server.\n+    \"\"\"\n+\n+    # Chrome is the default browser that selenium will use for extracting\n+    # performance stats.\n+    DEFAULT_BROWSER_SOURCE = 'chrome'\n+    SUPPORTED_BROWSER_SOURCES = ['chrome', 'firefox']\n+\n+    # Duration (in seconds) to wait for the complete page to load, otherwise\n+    # XHR requests made post initial page load will not be recorded.\n+    WAIT_DURATION_SECS = 3\n+\n+    def __init__(self, browser=DEFAULT_BROWSER_SOURCE):\n+        if browser in self.SUPPORTED_BROWSER_SOURCES:\n+            self.browser = browser\n+        else:\n+            error_msg = 'Unsupported browser specified: %s' % browser\n+            raise ValueError(error_msg)\n+\n+        self.server = self.driver = self.proxy = None\n+\n+    def get_page_metrics_for_url(self, page_url):\n+        \"\"\"Returns a PageSessionMetrics domain object initialized using","path":"core/tests/performance_framework/perf_services.py","position":74,"original_position":74,"commit_id":"a561f3ee8c479aba10c26a53d94e2062b313ea61","original_commit_id":"a561f3ee8c479aba10c26a53d94e2062b313ea61","user":{"login":"BenHenning","id":12983742,"avatar_url":"https://avatars.githubusercontent.com/u/12983742?v=3","gravatar_id":"","url":"https://api.github.com/users/BenHenning","html_url":"https://github.com/BenHenning","followers_url":"https://api.github.com/users/BenHenning/followers","following_url":"https://api.github.com/users/BenHenning/following{/other_user}","gists_url":"https://api.github.com/users/BenHenning/gists{/gist_id}","starred_url":"https://api.github.com/users/BenHenning/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BenHenning/subscriptions","organizations_url":"https://api.github.com/users/BenHenning/orgs","repos_url":"https://api.github.com/users/BenHenning/repos","events_url":"https://api.github.com/users/BenHenning/events{/privacy}","received_events_url":"https://api.github.com/users/BenHenning/received_events","type":"User","site_admin":false},"body":"I really am strongly opposed to referencing HAR in either of these two methods' documentation. It's an implementation detail that will not affect the developer using these two methods, so there's not a valuable reason for the developer to know about HAR files here. HAR files are described in the docstring of this class which is already more than I would normally expect, but it seems reasonable in the sense that this fetcher does use HAR internally and may eventually be extended to support the developer passing in a HAR-formatted dict.\r\n\r\nThese two methods don't actually need to be implemented using HAR files underneath in order to still function correctly (in the eyes of the programmer using the methods). For that reason, ``get_page_metrics_for_url`` and ``get_page_metrics_from_cached_state`` do not need to have HAR in their documentation.","created_at":"2016-06-18T08:26:13Z","updated_at":"2016-06-18T08:26:13Z","html_url":"https://github.com/oppia/oppia/pull/2068#discussion_r67597768","pull_request_url":"https://api.github.com/repos/oppia/oppia/pulls/2068","_links":{"self":{"href":"https://api.github.com/repos/oppia/oppia/pulls/comments/67597768"},"html":{"href":"https://github.com/oppia/oppia/pull/2068#discussion_r67597768"},"pull_request":{"href":"https://api.github.com/repos/oppia/oppia/pulls/2068"}}},"pull_request":{"url":"https://api.github.com/repos/oppia/oppia/pulls/2068","id":73163986,"html_url":"https://github.com/oppia/oppia/pull/2068","diff_url":"https://github.com/oppia/oppia/pull/2068.diff","patch_url":"https://github.com/oppia/oppia/pull/2068.patch","issue_url":"https://api.github.com/repos/oppia/oppia/issues/2068","number":2068,"state":"open","locked":false,"title":"Fix #2047: implement performance testing framework.","user":{"login":"gvishal","id":1708579,"avatar_url":"https://avatars.githubusercontent.com/u/1708579?v=3","gravatar_id":"","url":"https://api.github.com/users/gvishal","html_url":"https://github.com/gvishal","followers_url":"https://api.github.com/users/gvishal/followers","following_url":"https://api.github.com/users/gvishal/following{/other_user}","gists_url":"https://api.github.com/users/gvishal/gists{/gist_id}","starred_url":"https://api.github.com/users/gvishal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gvishal/subscriptions","organizations_url":"https://api.github.com/users/gvishal/orgs","repos_url":"https://api.github.com/users/gvishal/repos","events_url":"https://api.github.com/users/gvishal/events{/privacy}","received_events_url":"https://api.github.com/users/gvishal/received_events","type":"User","site_admin":false},"body":"[Wiki entry](https://github.com/oppia/oppia/wiki/Performance-Testing-Framework). I'll add more details to it soon.","created_at":"2016-06-09T06:39:18Z","updated_at":"2016-06-18T08:26:13Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a7d1093b12cf7a09ab394ddf5836599177777dcc","assignee":{"login":"maitbayev","id":5602283,"avatar_url":"https://avatars.githubusercontent.com/u/5602283?v=3","gravatar_id":"","url":"https://api.github.com/users/maitbayev","html_url":"https://github.com/maitbayev","followers_url":"https://api.github.com/users/maitbayev/followers","following_url":"https://api.github.com/users/maitbayev/following{/other_user}","gists_url":"https://api.github.com/users/maitbayev/gists{/gist_id}","starred_url":"https://api.github.com/users/maitbayev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maitbayev/subscriptions","organizations_url":"https://api.github.com/users/maitbayev/orgs","repos_url":"https://api.github.com/users/maitbayev/repos","events_url":"https://api.github.com/users/maitbayev/events{/privacy}","received_events_url":"https://api.github.com/users/maitbayev/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/oppia/oppia/pulls/2068/commits","review_comments_url":"https://api.github.com/repos/oppia/oppia/pulls/2068/comments","review_comment_url":"https://api.github.com/repos/oppia/oppia/pulls/comments{/number}","comments_url":"https://api.github.com/repos/oppia/oppia/issues/2068/comments","statuses_url":"https://api.github.com/repos/oppia/oppia/statuses/a561f3ee8c479aba10c26a53d94e2062b313ea61","head":{"label":"gvishal:performance-testing-framework","ref":"performance-testing-framework","sha":"a561f3ee8c479aba10c26a53d94e2062b313ea61","user":{"login":"gvishal","id":1708579,"avatar_url":"https://avatars.githubusercontent.com/u/1708579?v=3","gravatar_id":"","url":"https://api.github.com/users/gvishal","html_url":"https://github.com/gvishal","followers_url":"https://api.github.com/users/gvishal/followers","following_url":"https://api.github.com/users/gvishal/following{/other_user}","gists_url":"https://api.github.com/users/gvishal/gists{/gist_id}","starred_url":"https://api.github.com/users/gvishal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gvishal/subscriptions","organizations_url":"https://api.github.com/users/gvishal/orgs","repos_url":"https://api.github.com/users/gvishal/repos","events_url":"https://api.github.com/users/gvishal/events{/privacy}","received_events_url":"https://api.github.com/users/gvishal/received_events","type":"User","site_admin":false},"repo":{"id":52909507,"name":"oppia","full_name":"gvishal/oppia","owner":{"login":"gvishal","id":1708579,"avatar_url":"https://avatars.githubusercontent.com/u/1708579?v=3","gravatar_id":"","url":"https://api.github.com/users/gvishal","html_url":"https://github.com/gvishal","followers_url":"https://api.github.com/users/gvishal/followers","following_url":"https://api.github.com/users/gvishal/following{/other_user}","gists_url":"https://api.github.com/users/gvishal/gists{/gist_id}","starred_url":"https://api.github.com/users/gvishal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gvishal/subscriptions","organizations_url":"https://api.github.com/users/gvishal/orgs","repos_url":"https://api.github.com/users/gvishal/repos","events_url":"https://api.github.com/users/gvishal/events{/privacy}","received_events_url":"https://api.github.com/users/gvishal/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/gvishal/oppia","description":"Tool for collaboratively building intelligent tutors.","fork":true,"url":"https://api.github.com/repos/gvishal/oppia","forks_url":"https://api.github.com/repos/gvishal/oppia/forks","keys_url":"https://api.github.com/repos/gvishal/oppia/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gvishal/oppia/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gvishal/oppia/teams","hooks_url":"https://api.github.com/repos/gvishal/oppia/hooks","issue_events_url":"https://api.github.com/repos/gvishal/oppia/issues/events{/number}","events_url":"https://api.github.com/repos/gvishal/oppia/events","assignees_url":"https://api.github.com/repos/gvishal/oppia/assignees{/user}","branches_url":"https://api.github.com/repos/gvishal/oppia/branches{/branch}","tags_url":"https://api.github.com/repos/gvishal/oppia/tags","blobs_url":"https://api.github.com/repos/gvishal/oppia/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gvishal/oppia/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gvishal/oppia/git/refs{/sha}","trees_url":"https://api.github.com/repos/gvishal/oppia/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gvishal/oppia/statuses/{sha}","languages_url":"https://api.github.com/repos/gvishal/oppia/languages","stargazers_url":"https://api.github.com/repos/gvishal/oppia/stargazers","contributors_url":"https://api.github.com/repos/gvishal/oppia/contributors","subscribers_url":"https://api.github.com/repos/gvishal/oppia/subscribers","subscription_url":"https://api.github.com/repos/gvishal/oppia/subscription","commits_url":"https://api.github.com/repos/gvishal/oppia/commits{/sha}","git_commits_url":"https://api.github.com/repos/gvishal/oppia/git/commits{/sha}","comments_url":"https://api.github.com/repos/gvishal/oppia/comments{/number}","issue_comment_url":"https://api.github.com/repos/gvishal/oppia/issues/comments{/number}","contents_url":"https://api.github.com/repos/gvishal/oppia/contents/{+path}","compare_url":"https://api.github.com/repos/gvishal/oppia/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gvishal/oppia/merges","archive_url":"https://api.github.com/repos/gvishal/oppia/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gvishal/oppia/downloads","issues_url":"https://api.github.com/repos/gvishal/oppia/issues{/number}","pulls_url":"https://api.github.com/repos/gvishal/oppia/pulls{/number}","milestones_url":"https://api.github.com/repos/gvishal/oppia/milestones{/number}","notifications_url":"https://api.github.com/repos/gvishal/oppia/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gvishal/oppia/labels{/name}","releases_url":"https://api.github.com/repos/gvishal/oppia/releases{/id}","deployments_url":"https://api.github.com/repos/gvishal/oppia/deployments","created_at":"2016-03-01T20:57:37Z","updated_at":"2016-03-01T20:57:41Z","pushed_at":"2016-06-17T19:16:35Z","git_url":"git://github.com/gvishal/oppia.git","ssh_url":"git@github.com:gvishal/oppia.git","clone_url":"https://github.com/gvishal/oppia.git","svn_url":"https://github.com/gvishal/oppia","homepage":"https://www.oppia.org","size":45212,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":false,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"oppia:develop","ref":"develop","sha":"cf2cc2c55614c42be38b2301982f80e3239ba590","user":{"login":"oppia","id":11620230,"avatar_url":"https://avatars.githubusercontent.com/u/11620230?v=3","gravatar_id":"","url":"https://api.github.com/users/oppia","html_url":"https://github.com/oppia","followers_url":"https://api.github.com/users/oppia/followers","following_url":"https://api.github.com/users/oppia/following{/other_user}","gists_url":"https://api.github.com/users/oppia/gists{/gist_id}","starred_url":"https://api.github.com/users/oppia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oppia/subscriptions","organizations_url":"https://api.github.com/users/oppia/orgs","repos_url":"https://api.github.com/users/oppia/repos","events_url":"https://api.github.com/users/oppia/events{/privacy}","received_events_url":"https://api.github.com/users/oppia/received_events","type":"Organization","site_admin":false},"repo":{"id":40687563,"name":"oppia","full_name":"oppia/oppia","owner":{"login":"oppia","id":11620230,"avatar_url":"https://avatars.githubusercontent.com/u/11620230?v=3","gravatar_id":"","url":"https://api.github.com/users/oppia","html_url":"https://github.com/oppia","followers_url":"https://api.github.com/users/oppia/followers","following_url":"https://api.github.com/users/oppia/following{/other_user}","gists_url":"https://api.github.com/users/oppia/gists{/gist_id}","starred_url":"https://api.github.com/users/oppia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oppia/subscriptions","organizations_url":"https://api.github.com/users/oppia/orgs","repos_url":"https://api.github.com/users/oppia/repos","events_url":"https://api.github.com/users/oppia/events{/privacy}","received_events_url":"https://api.github.com/users/oppia/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/oppia/oppia","description":"Tool for collaboratively building interactive lessons.","fork":false,"url":"https://api.github.com/repos/oppia/oppia","forks_url":"https://api.github.com/repos/oppia/oppia/forks","keys_url":"https://api.github.com/repos/oppia/oppia/keys{/key_id}","collaborators_url":"https://api.github.com/repos/oppia/oppia/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/oppia/oppia/teams","hooks_url":"https://api.github.com/repos/oppia/oppia/hooks","issue_events_url":"https://api.github.com/repos/oppia/oppia/issues/events{/number}","events_url":"https://api.github.com/repos/oppia/oppia/events","assignees_url":"https://api.github.com/repos/oppia/oppia/assignees{/user}","branches_url":"https://api.github.com/repos/oppia/oppia/branches{/branch}","tags_url":"https://api.github.com/repos/oppia/oppia/tags","blobs_url":"https://api.github.com/repos/oppia/oppia/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/oppia/oppia/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/oppia/oppia/git/refs{/sha}","trees_url":"https://api.github.com/repos/oppia/oppia/git/trees{/sha}","statuses_url":"https://api.github.com/repos/oppia/oppia/statuses/{sha}","languages_url":"https://api.github.com/repos/oppia/oppia/languages","stargazers_url":"https://api.github.com/repos/oppia/oppia/stargazers","contributors_url":"https://api.github.com/repos/oppia/oppia/contributors","subscribers_url":"https://api.github.com/repos/oppia/oppia/subscribers","subscription_url":"https://api.github.com/repos/oppia/oppia/subscription","commits_url":"https://api.github.com/repos/oppia/oppia/commits{/sha}","git_commits_url":"https://api.github.com/repos/oppia/oppia/git/commits{/sha}","comments_url":"https://api.github.com/repos/oppia/oppia/comments{/number}","issue_comment_url":"https://api.github.com/repos/oppia/oppia/issues/comments{/number}","contents_url":"https://api.github.com/repos/oppia/oppia/contents/{+path}","compare_url":"https://api.github.com/repos/oppia/oppia/compare/{base}...{head}","merges_url":"https://api.github.com/repos/oppia/oppia/merges","archive_url":"https://api.github.com/repos/oppia/oppia/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/oppia/oppia/downloads","issues_url":"https://api.github.com/repos/oppia/oppia/issues{/number}","pulls_url":"https://api.github.com/repos/oppia/oppia/pulls{/number}","milestones_url":"https://api.github.com/repos/oppia/oppia/milestones{/number}","notifications_url":"https://api.github.com/repos/oppia/oppia/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/oppia/oppia/labels{/name}","releases_url":"https://api.github.com/repos/oppia/oppia/releases{/id}","deployments_url":"https://api.github.com/repos/oppia/oppia/deployments","created_at":"2015-08-14T00:16:14Z","updated_at":"2016-06-16T06:01:38Z","pushed_at":"2016-06-17T22:13:02Z","git_url":"git://github.com/oppia/oppia.git","ssh_url":"git@github.com:oppia/oppia.git","clone_url":"https://github.com/oppia/oppia.git","svn_url":"https://github.com/oppia/oppia","homepage":"https://www.oppia.org","size":81547,"stargazers_count":139,"watchers_count":139,"language":"Python","has_issues":true,"has_downloads":false,"has_wiki":true,"has_pages":false,"forks_count":232,"mirror_url":null,"open_issues_count":347,"forks":232,"open_issues":347,"watchers":139,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/oppia/oppia/pulls/2068"},"html":{"href":"https://github.com/oppia/oppia/pull/2068"},"issue":{"href":"https://api.github.com/repos/oppia/oppia/issues/2068"},"comments":{"href":"https://api.github.com/repos/oppia/oppia/issues/2068/comments"},"review_comments":{"href":"https://api.github.com/repos/oppia/oppia/pulls/2068/comments"},"review_comment":{"href":"https://api.github.com/repos/oppia/oppia/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/oppia/oppia/pulls/2068/commits"},"statuses":{"href":"https://api.github.com/repos/oppia/oppia/statuses/a561f3ee8c479aba10c26a53d94e2062b313ea61"}}}}
{"actor":{"display_login":"BenHenning"}}