{"action":"created","comment":{"url":"https://api.github.com/repos/grafana/metrictank/pulls/comments/208379543","pull_request_review_id":144177612,"id":208379543,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwODM3OTU0Mw==","diff_hunk":"@@ -0,0 +1,258 @@\n+package expr\n+\n+import (\n+\t\"errors\"\n+\t\"fmt\"\n+\t\"math\"\n+\t\"sort\"\n+\t\"strings\"\n+\n+\t\"github.com/grafana/metrictank/api/models\"\n+\tschema \"gopkg.in/raintank/schema.v1\"\n+)\n+\n+type FuncAsPercent struct {\n+\tin          GraphiteFunc\n+\ttotalFloat  float64\n+\ttotalSeries GraphiteFunc\n+\tnodes       []expr\n+}\n+\n+func NewAsPercent() GraphiteFunc {\n+\treturn &FuncAsPercent{totalFloat: math.NaN()}\n+}\n+\n+func (s *FuncAsPercent) Signature() ([]Arg, []Arg) {\n+\treturn []Arg{\n+\t\tArgSeriesList{val: &s.in},\n+\t\tArgIn{\n+\t\t\tkey: \"total\",\n+\t\t\topt: true,\n+\t\t\targs: []Arg{\n+\t\t\t\tArgFloat{val: &s.totalFloat},\n+\t\t\t\tArgSeriesList{val: &s.totalSeries},\n+\t\t\t},\n+\t\t},\n+\t\tArgStringsOrInts{val: &s.nodes, opt: true, key: \"nodes\"},\n+\t}, []Arg{ArgSeriesList{}}\n+}\n+\n+func (s *FuncAsPercent) Context(context Context) Context {\n+\treturn context\n+}\n+\n+func (s *FuncAsPercent) Exec(cache map[Req][]models.Series) ([]models.Series, error) {\n+\tseries, err := s.in.Exec(cache)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tvar outSeries []models.Series\n+\tdefer func() { cache[Req{}] = append(cache[Req{}], outSeries...) }()\n+\tvar totals []models.Series\n+\tif s.totalSeries != nil {\n+\t\ttotals, err = s.totalSeries.Exec(cache)\n+\t\tif err != nil {\n+\t\t\treturn nil, err\n+\t\t}\n+\t\tif len(totals) == 0 {\n+\t\t\ttotals = nil\n+\t\t}\n+\t}\n+\n+\tif s.nodes != nil {\n+\t\t// Set of keys\n+\t\tkeys := make(map[string]struct{})\n+\t\t// Series grouped by key\n+\t\tmetaSeries := groupSeriesByKey(series, s.nodes, &keys)\n+\t\t// The totals series for each key\n+\t\tvar totalSeries map[string]models.Series\n+\n+\t\t// calculate the sum\n+\t\tif math.IsNaN(s.totalFloat) && totals == nil {\n+\t\t\ttotalSeries = getTotalSeries(metaSeries)\n+\t\t\t// calculate sum of totals series\n+\t\t} else if totals != nil {\n+\t\t\ttotalSeriesLists := groupSeriesByKey(totals, s.nodes, &keys)\n+\t\t\ttotalSeries = getTotalSeries(totalSeriesLists)\n+\t\t} else {\n+\t\t\treturn nil, errors.New(\"total must be None or a seriesList\")","path":"expr/func_aspercent.go","position":null,"original_position":79,"commit_id":"f5ed45b0cd11ae9b202f109c1832394496867618","original_commit_id":"79d81bdf9f71cea140c24cefc8e8aa128d2e2bfd","user":{"login":"stivenbb","id":40801081,"node_id":"MDQ6VXNlcjQwODAxMDgx","avatar_url":"https://avatars0.githubusercontent.com/u/40801081?v=4","gravatar_id":"","url":"https://api.github.com/users/stivenbb","html_url":"https://github.com/stivenbb","followers_url":"https://api.github.com/users/stivenbb/followers","following_url":"https://api.github.com/users/stivenbb/following{/other_user}","gists_url":"https://api.github.com/users/stivenbb/gists{/gist_id}","starred_url":"https://api.github.com/users/stivenbb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stivenbb/subscriptions","organizations_url":"https://api.github.com/users/stivenbb/orgs","repos_url":"https://api.github.com/users/stivenbb/repos","events_url":"https://api.github.com/users/stivenbb/events{/privacy}","received_events_url":"https://api.github.com/users/stivenbb/received_events","type":"User","site_admin":false},"body":"FWIW, Graphite crashes if you do that.\r\n\r\nLet me see if I can handle it in some clean way","created_at":"2018-08-07T20:46:58Z","updated_at":"2018-08-07T20:46:58Z","html_url":"https://github.com/grafana/metrictank/pull/966#discussion_r208379543","pull_request_url":"https://api.github.com/repos/grafana/metrictank/pulls/966","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/grafana/metrictank/pulls/comments/208379543"},"html":{"href":"https://github.com/grafana/metrictank/pull/966#discussion_r208379543"},"pull_request":{"href":"https://api.github.com/repos/grafana/metrictank/pulls/966"}},"in_reply_to_id":208360871},"pull_request":{"url":"https://api.github.com/repos/grafana/metrictank/pulls/966","id":204255094,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA0MjU1MDk0","html_url":"https://github.com/grafana/metrictank/pull/966","diff_url":"https://github.com/grafana/metrictank/pull/966.diff","patch_url":"https://github.com/grafana/metrictank/pull/966.patch","issue_url":"https://api.github.com/repos/grafana/metrictank/issues/966","number":966,"state":"open","locked":false,"title":"Add asPercent function","user":{"login":"stivenbb","id":40801081,"node_id":"MDQ6VXNlcjQwODAxMDgx","avatar_url":"https://avatars0.githubusercontent.com/u/40801081?v=4","gravatar_id":"","url":"https://api.github.com/users/stivenbb","html_url":"https://github.com/stivenbb","followers_url":"https://api.github.com/users/stivenbb/followers","following_url":"https://api.github.com/users/stivenbb/following{/other_user}","gists_url":"https://api.github.com/users/stivenbb/gists{/gist_id}","starred_url":"https://api.github.com/users/stivenbb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stivenbb/subscriptions","organizations_url":"https://api.github.com/users/stivenbb/orgs","repos_url":"https://api.github.com/users/stivenbb/repos","events_url":"https://api.github.com/users/stivenbb/events{/privacy}","received_events_url":"https://api.github.com/users/stivenbb/received_events","type":"User","site_admin":false},"body":"Native implementation of asPercent() Graphite function. (http://graphite.readthedocs.io/en/latest/functions.html#graphite.render.functions.asPercent)\r\n\r\nAdded a new argument type `ArgIn` that allows multiple other argument types. This was necessary for the *total* argument. Some of the code borrowed from an abandoned PR: https://github.com/grafana/metrictank/pull/672\r\n\r\nIn terms of speed improvement:\r\n```\r\n---------- Native Implementation ----------\r\nRequests      [total, rate]            900, 5.01\r\nDuration      [total, attack, wait]    3m0.13756s, 2m59.799999s, 337.561ms\r\nLatencies     [mean, 50, 95, 99, max]  72.006704ms, 38.065ms, 342.887ms, 472.467ms, 765.657ms\r\nBytes In      [total, mean]            130300948, 144778.83\r\nBytes Out     [total, mean]            0, 0.00\r\nSuccess       [ratio]                  100.00%\r\nStatus Codes  [code:count]             200:900\r\nError Set:\r\n---------- Graphite (Python) Implementation ----------\r\nRequests      [total, rate]            900, 5.01\r\nDuration      [total, attack, wait]    3m6.337648s, 2m59.799999s, 6.537649s\r\nLatencies     [mean, 50, 95, 99, max]  797.282367ms, 167.489ms, 4.789024s, 6.756318s, 8.006429s\r\nBytes In      [total, mean]            144407224, 160452.47\r\nBytes Out     [total, mean]            0, 0.00\r\nSuccess       [ratio]                  100.00%\r\nStatus Codes  [code:count]             200:900\r\nError Set:\r\n```\r\n\r\nOn average, the native implementation was 11x faster, median was 4x faster, p95 was 14x faster, p99 was 14x faster and max was over 10x faster","created_at":"2018-07-26T20:17:56Z","updated_at":"2018-08-07T20:46:58Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0168a34d31fd0fcaf642e1cdf94f0e3f1e806ffc","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/grafana/metrictank/pulls/966/commits","review_comments_url":"https://api.github.com/repos/grafana/metrictank/pulls/966/comments","review_comment_url":"https://api.github.com/repos/grafana/metrictank/pulls/comments{/number}","comments_url":"https://api.github.com/repos/grafana/metrictank/issues/966/comments","statuses_url":"https://api.github.com/repos/grafana/metrictank/statuses/f5ed45b0cd11ae9b202f109c1832394496867618","head":{"label":"bloomberg:asPercent","ref":"asPercent","sha":"f5ed45b0cd11ae9b202f109c1832394496867618","user":{"login":"bloomberg","id":1416818,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTY4MTg=","avatar_url":"https://avatars2.githubusercontent.com/u/1416818?v=4","gravatar_id":"","url":"https://api.github.com/users/bloomberg","html_url":"https://github.com/bloomberg","followers_url":"https://api.github.com/users/bloomberg/followers","following_url":"https://api.github.com/users/bloomberg/following{/other_user}","gists_url":"https://api.github.com/users/bloomberg/gists{/gist_id}","starred_url":"https://api.github.com/users/bloomberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bloomberg/subscriptions","organizations_url":"https://api.github.com/users/bloomberg/orgs","repos_url":"https://api.github.com/users/bloomberg/repos","events_url":"https://api.github.com/users/bloomberg/events{/privacy}","received_events_url":"https://api.github.com/users/bloomberg/received_events","type":"Organization","site_admin":false},"repo":{"id":105683784,"node_id":"MDEwOlJlcG9zaXRvcnkxMDU2ODM3ODQ=","name":"metrictank","full_name":"bloomberg/metrictank","owner":{"login":"bloomberg","id":1416818,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTY4MTg=","avatar_url":"https://avatars2.githubusercontent.com/u/1416818?v=4","gravatar_id":"","url":"https://api.github.com/users/bloomberg","html_url":"https://github.com/bloomberg","followers_url":"https://api.github.com/users/bloomberg/followers","following_url":"https://api.github.com/users/bloomberg/following{/other_user}","gists_url":"https://api.github.com/users/bloomberg/gists{/gist_id}","starred_url":"https://api.github.com/users/bloomberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bloomberg/subscriptions","organizations_url":"https://api.github.com/users/bloomberg/orgs","repos_url":"https://api.github.com/users/bloomberg/repos","events_url":"https://api.github.com/users/bloomberg/events{/privacy}","received_events_url":"https://api.github.com/users/bloomberg/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/bloomberg/metrictank","description":"Cassandra-backed, metrics2.0 based, multi-tenant timeseries database for Graphite and friends","fork":true,"url":"https://api.github.com/repos/bloomberg/metrictank","forks_url":"https://api.github.com/repos/bloomberg/metrictank/forks","keys_url":"https://api.github.com/repos/bloomberg/metrictank/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bloomberg/metrictank/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bloomberg/metrictank/teams","hooks_url":"https://api.github.com/repos/bloomberg/metrictank/hooks","issue_events_url":"https://api.github.com/repos/bloomberg/metrictank/issues/events{/number}","events_url":"https://api.github.com/repos/bloomberg/metrictank/events","assignees_url":"https://api.github.com/repos/bloomberg/metrictank/assignees{/user}","branches_url":"https://api.github.com/repos/bloomberg/metrictank/branches{/branch}","tags_url":"https://api.github.com/repos/bloomberg/metrictank/tags","blobs_url":"https://api.github.com/repos/bloomberg/metrictank/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bloomberg/metrictank/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bloomberg/metrictank/git/refs{/sha}","trees_url":"https://api.github.com/repos/bloomberg/metrictank/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bloomberg/metrictank/statuses/{sha}","languages_url":"https://api.github.com/repos/bloomberg/metrictank/languages","stargazers_url":"https://api.github.com/repos/bloomberg/metrictank/stargazers","contributors_url":"https://api.github.com/repos/bloomberg/metrictank/contributors","subscribers_url":"https://api.github.com/repos/bloomberg/metrictank/subscribers","subscription_url":"https://api.github.com/repos/bloomberg/metrictank/subscription","commits_url":"https://api.github.com/repos/bloomberg/metrictank/commits{/sha}","git_commits_url":"https://api.github.com/repos/bloomberg/metrictank/git/commits{/sha}","comments_url":"https://api.github.com/repos/bloomberg/metrictank/comments{/number}","issue_comment_url":"https://api.github.com/repos/bloomberg/metrictank/issues/comments{/number}","contents_url":"https://api.github.com/repos/bloomberg/metrictank/contents/{+path}","compare_url":"https://api.github.com/repos/bloomberg/metrictank/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bloomberg/metrictank/merges","archive_url":"https://api.github.com/repos/bloomberg/metrictank/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bloomberg/metrictank/downloads","issues_url":"https://api.github.com/repos/bloomberg/metrictank/issues{/number}","pulls_url":"https://api.github.com/repos/bloomberg/metrictank/pulls{/number}","milestones_url":"https://api.github.com/repos/bloomberg/metrictank/milestones{/number}","notifications_url":"https://api.github.com/repos/bloomberg/metrictank/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bloomberg/metrictank/labels{/name}","releases_url":"https://api.github.com/repos/bloomberg/metrictank/releases{/id}","deployments_url":"https://api.github.com/repos/bloomberg/metrictank/deployments","created_at":"2017-10-03T17:51:01Z","updated_at":"2018-07-31T06:22:50Z","pushed_at":"2018-08-07T20:36:17Z","git_url":"git://github.com/bloomberg/metrictank.git","ssh_url":"git@github.com:bloomberg/metrictank.git","clone_url":"https://github.com/bloomberg/metrictank.git","svn_url":"https://github.com/bloomberg/metrictank","homepage":"","size":17613,"stargazers_count":2,"watchers_count":2,"language":"Go","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"agpl-3.0","name":"GNU Affero General Public License v3.0","spdx_id":"AGPL-3.0","url":"https://api.github.com/licenses/agpl-3.0","node_id":"MDc6TGljZW5zZTE="},"forks":2,"open_issues":2,"watchers":2,"default_branch":"master"}},"base":{"label":"grafana:master","ref":"master","sha":"2cb286b24984e7dd93c2a9002336804cb66ab234","user":{"login":"grafana","id":7195757,"node_id":"MDEyOk9yZ2FuaXphdGlvbjcxOTU3NTc=","avatar_url":"https://avatars0.githubusercontent.com/u/7195757?v=4","gravatar_id":"","url":"https://api.github.com/users/grafana","html_url":"https://github.com/grafana","followers_url":"https://api.github.com/users/grafana/followers","following_url":"https://api.github.com/users/grafana/following{/other_user}","gists_url":"https://api.github.com/users/grafana/gists{/gist_id}","starred_url":"https://api.github.com/users/grafana/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/grafana/subscriptions","organizations_url":"https://api.github.com/users/grafana/orgs","repos_url":"https://api.github.com/users/grafana/repos","events_url":"https://api.github.com/users/grafana/events{/privacy}","received_events_url":"https://api.github.com/users/grafana/received_events","type":"Organization","site_admin":false},"repo":{"id":30401116,"node_id":"MDEwOlJlcG9zaXRvcnkzMDQwMTExNg==","name":"metrictank","full_name":"grafana/metrictank","owner":{"login":"grafana","id":7195757,"node_id":"MDEyOk9yZ2FuaXphdGlvbjcxOTU3NTc=","avatar_url":"https://avatars0.githubusercontent.com/u/7195757?v=4","gravatar_id":"","url":"https://api.github.com/users/grafana","html_url":"https://github.com/grafana","followers_url":"https://api.github.com/users/grafana/followers","following_url":"https://api.github.com/users/grafana/following{/other_user}","gists_url":"https://api.github.com/users/grafana/gists{/gist_id}","starred_url":"https://api.github.com/users/grafana/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/grafana/subscriptions","organizations_url":"https://api.github.com/users/grafana/orgs","repos_url":"https://api.github.com/users/grafana/repos","events_url":"https://api.github.com/users/grafana/events{/privacy}","received_events_url":"https://api.github.com/users/grafana/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/grafana/metrictank","description":"Cassandra-backed, metrics2.0 based, multi-tenant timeseries database for Graphite and friends","fork":false,"url":"https://api.github.com/repos/grafana/metrictank","forks_url":"https://api.github.com/repos/grafana/metrictank/forks","keys_url":"https://api.github.com/repos/grafana/metrictank/keys{/key_id}","collaborators_url":"https://api.github.com/repos/grafana/metrictank/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/grafana/metrictank/teams","hooks_url":"https://api.github.com/repos/grafana/metrictank/hooks","issue_events_url":"https://api.github.com/repos/grafana/metrictank/issues/events{/number}","events_url":"https://api.github.com/repos/grafana/metrictank/events","assignees_url":"https://api.github.com/repos/grafana/metrictank/assignees{/user}","branches_url":"https://api.github.com/repos/grafana/metrictank/branches{/branch}","tags_url":"https://api.github.com/repos/grafana/metrictank/tags","blobs_url":"https://api.github.com/repos/grafana/metrictank/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/grafana/metrictank/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/grafana/metrictank/git/refs{/sha}","trees_url":"https://api.github.com/repos/grafana/metrictank/git/trees{/sha}","statuses_url":"https://api.github.com/repos/grafana/metrictank/statuses/{sha}","languages_url":"https://api.github.com/repos/grafana/metrictank/languages","stargazers_url":"https://api.github.com/repos/grafana/metrictank/stargazers","contributors_url":"https://api.github.com/repos/grafana/metrictank/contributors","subscribers_url":"https://api.github.com/repos/grafana/metrictank/subscribers","subscription_url":"https://api.github.com/repos/grafana/metrictank/subscription","commits_url":"https://api.github.com/repos/grafana/metrictank/commits{/sha}","git_commits_url":"https://api.github.com/repos/grafana/metrictank/git/commits{/sha}","comments_url":"https://api.github.com/repos/grafana/metrictank/comments{/number}","issue_comment_url":"https://api.github.com/repos/grafana/metrictank/issues/comments{/number}","contents_url":"https://api.github.com/repos/grafana/metrictank/contents/{+path}","compare_url":"https://api.github.com/repos/grafana/metrictank/compare/{base}...{head}","merges_url":"https://api.github.com/repos/grafana/metrictank/merges","archive_url":"https://api.github.com/repos/grafana/metrictank/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/grafana/metrictank/downloads","issues_url":"https://api.github.com/repos/grafana/metrictank/issues{/number}","pulls_url":"https://api.github.com/repos/grafana/metrictank/pulls{/number}","milestones_url":"https://api.github.com/repos/grafana/metrictank/milestones{/number}","notifications_url":"https://api.github.com/repos/grafana/metrictank/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/grafana/metrictank/labels{/name}","releases_url":"https://api.github.com/repos/grafana/metrictank/releases{/id}","deployments_url":"https://api.github.com/repos/grafana/metrictank/deployments","created_at":"2015-02-06T07:44:12Z","updated_at":"2018-08-07T18:56:51Z","pushed_at":"2018-08-07T19:59:15Z","git_url":"git://github.com/grafana/metrictank.git","ssh_url":"git@github.com:grafana/metrictank.git","clone_url":"https://github.com/grafana/metrictank.git","svn_url":"https://github.com/grafana/metrictank","homepage":"","size":29341,"stargazers_count":242,"watchers_count":242,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":45,"mirror_url":null,"archived":false,"open_issues_count":132,"license":{"key":"agpl-3.0","name":"GNU Affero General Public License v3.0","spdx_id":"AGPL-3.0","url":"https://api.github.com/licenses/agpl-3.0","node_id":"MDc6TGljZW5zZTE="},"forks":45,"open_issues":132,"watchers":242,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/grafana/metrictank/pulls/966"},"html":{"href":"https://github.com/grafana/metrictank/pull/966"},"issue":{"href":"https://api.github.com/repos/grafana/metrictank/issues/966"},"comments":{"href":"https://api.github.com/repos/grafana/metrictank/issues/966/comments"},"review_comments":{"href":"https://api.github.com/repos/grafana/metrictank/pulls/966/comments"},"review_comment":{"href":"https://api.github.com/repos/grafana/metrictank/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/grafana/metrictank/pulls/966/commits"},"statuses":{"href":"https://api.github.com/repos/grafana/metrictank/statuses/f5ed45b0cd11ae9b202f109c1832394496867618"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"stivenbb"}}