{"action":"created","comment":{"url":"https://api.github.com/repos/intelsdi-x/snap/pulls/comments/57449605","id":57449605,"diff_hunk":"@@ -160,23 +189,162 @@ func (m *metricType) Timestamp() time.Time {\n }\n \n type metricCatalog struct {\n-\ttree        *MTTrie\n-\tmutex       *sync.Mutex\n-\tkeys        []string\n+\ttree  *MTTrie\n+\tmutex *sync.Mutex\n+\tkeys  []string\n+\n+\t// mKeys holds requested metric's keys which can include wildcards and matched to them the cataloged keys\n+\tmKeys       map[string][]string\n \tcurrentIter int\n }\n \n func newMetricCatalog() *metricCatalog {\n-\tvar k []string\n \treturn &metricCatalog{\n \t\ttree:        NewMTTrie(),\n \t\tmutex:       &sync.Mutex{},\n \t\tcurrentIter: 0,\n-\t\tkeys:        k,\n+\t\tkeys:        []string{},\n+\t\tmKeys:       make(map[string][]string),\n \t}\n }\n \n+func (mc *metricCatalog) Keys() []string {\n+\treturn mc.keys\n+}\n+\n+// GetMatchedMetrics returns all matched keys for metric with namespace 'ns'\n+func (mc *metricCatalog) GetMatchedMetrics(ns []string) ([][]string, error) {\n+\tmc.mutex.Lock()\n+\tdefer mc.mutex.Unlock()\n+\n+\t// get metric key (might contain wildcard(s))\n+\twkey := getMetricKey(ns)\n+\n+\t// if not exist, match `wkey` with cataloged keys\n+\tif _, exist := mc.mKeys[wkey]; !exist {\n+\t\tmc.addItemToMatchingMap(wkey)\n+\t}\n+\n+\t// mkeys means matched metrics keys\n+\tmkeys := mc.mKeys[wkey]\n+\n+\tif len(mkeys) == 0 {\n+\t\treturn nil, errorMetricNotFound(ns)\n+\t}\n+\n+\t// convert matched keys to a slice of namespaces\n+\tnss := convertKeysToNamespaces(mkeys)\n+\n+\treturn nss, nil\n+}\n+\n+func convertKeysToNamespaces(keys []string) [][]string {\n+\t// nss is a slice of slices which holds metrics namespaces\n+\tnss := [][]string{}\n+\tfor _, key := range keys {\n+\t\tns := getMetricNamespace(key)\n+\t\tif len(ns) != 0 {\n+\t\t\tnss = append(nss, ns)\n+\t\t}\n+\t}\n+\n+\treturn nss\n+}\n+\n+// addItemToMatchingMap adds `wkey` to matching map (or updates if exists) with corresponding cataloged keys as a content;\n+// if this 'wkey' does not match to any cataloged keys, it will be removed from matching map\n+func (mc *metricCatalog) addItemToMatchingMap(wkey string) {\n+\tmatchedKeys := []string{}\n+\n+\t// wkey contains `.` which should not be interpreted as regexp tokens, but as a single character\n+\texp := strings.Replace(wkey, \".\", \"[.]\", -1)\n+\n+\t// change `*` into regexp `.*` which matches any characters\n+\texp = strings.Replace(exp, \"*\", \".*\", -1)\n+\n+\tregex := regexp.MustCompile(\"^\" + exp + \"$\")\n+\n+\tfor _, key := range mc.keys {\n+\t\tmatch := regex.FindStringSubmatch(key)\n+\n+\t\tif match == nil {\n+\t\t\tcontinue\n+\t\t}\n+\n+\t\tmatchedKeys = appendIfMissing(matchedKeys, key)\n+\t}\n+\n+\tif len(matchedKeys) == 0 {\n+\t\tmc.removeItemFromMatchingMap(wkey)\n+\t} else {\n+\t\tmc.mKeys[wkey] = matchedKeys\n+\t}\n+}\n+\n+// removeItemFromMatchingMap removes `wkey` from matching map\n+func (mc *metricCatalog) removeItemFromMatchingMap(wkey string) {\n+\tif _, exist := mc.mKeys[wkey]; exist {\n+\t\tdelete(mc.mKeys, wkey)\n+\t}\n+}\n+\n+// updateMatchingMap updates the contents of matching map\n+func (mc *metricCatalog) updateMatchingMap() {\n+\tfor wkey := range mc.mKeys {\n+\t\t// add (or update if exist) item `wkey'\n+\t\tmc.addItemToMatchingMap(wkey)\n+\t}\n+}\n+\n+// removeMatchedKey iterates over all items in the mKey and removes `key` from its content\n+func (mc *metricCatalog) removeMatchedKey(key string) {\n+\tfor wkey, mkeys := range mc.mKeys {\n+\t\tfor index, mkey := range mkeys {\n+\t\t\tif mkey == key {\n+\t\t\t\t// remove this key from slice\n+\t\t\t\tmc.mKeys[wkey] = append(mkeys[:index], mkeys[index+1:]...)\n+\t\t\t}\n+\t\t}\n+\t\t// if no matched key left, remove this item from map\n+\t\tif len(mc.mKeys[wkey]) == 0 {\n+\t\t\tmc.removeItemFromMatchingMap(wkey)\n+\t\t}\n+\t}\n+}\n+\n+// validateMetricNamespace validates metric namespace in terms of containing not allowed characters and ending with an asterisk\n+func validateMetricNamespace(ns []string) error {\n+\tname := strings.Join(ns, \"\")\n+\n+\tfor _, chars := range notAllowedChars {\n+\t\tfor _, ch := range chars {\n+\t\t\tif strings.ContainsAny(name, ch) {\n+\t\t\t\treturn errorMetricContainsNotAllowedChars(ns)\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t// todo uncomment this after adjusting all plugins","path":"control/metrics.go","position":203,"original_position":203,"commit_id":"cc5c2440f1e1d9d87635f00b58686145aa5d41db","original_commit_id":"cc5c2440f1e1d9d87635f00b58686145aa5d41db","user":{"login":"IzabellaRaulin","id":11335874,"avatar_url":"https://avatars.githubusercontent.com/u/11335874?v=3","gravatar_id":"","url":"https://api.github.com/users/IzabellaRaulin","html_url":"https://github.com/IzabellaRaulin","followers_url":"https://api.github.com/users/IzabellaRaulin/followers","following_url":"https://api.github.com/users/IzabellaRaulin/following{/other_user}","gists_url":"https://api.github.com/users/IzabellaRaulin/gists{/gist_id}","starred_url":"https://api.github.com/users/IzabellaRaulin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IzabellaRaulin/subscriptions","organizations_url":"https://api.github.com/users/IzabellaRaulin/orgs","repos_url":"https://api.github.com/users/IzabellaRaulin/repos","events_url":"https://api.github.com/users/IzabellaRaulin/events{/privacy}","received_events_url":"https://api.github.com/users/IzabellaRaulin/received_events","type":"User","site_admin":false},"body":"Thanks, I decided to remove this commented out code. \r\n\r\nWhen I finish revising that all plugins do not exposed a wildcard in the end of namespace + refactoring that one which has such like metrics, I will add this part of validation + unit test which covers that again in another pull request.\r\n\r\nAlready even plugin has metrics which ends with wildcard, it will works properly,  So, as a first step the plugins will be refactored","created_at":"2016-03-25T14:41:13Z","updated_at":"2016-03-25T14:41:13Z","html_url":"https://github.com/intelsdi-x/snap/pull/803#discussion_r57449605","pull_request_url":"https://api.github.com/repos/intelsdi-x/snap/pulls/803","_links":{"self":{"href":"https://api.github.com/repos/intelsdi-x/snap/pulls/comments/57449605"},"html":{"href":"https://github.com/intelsdi-x/snap/pull/803#discussion_r57449605"},"pull_request":{"href":"https://api.github.com/repos/intelsdi-x/snap/pulls/803"}}},"pull_request":{"url":"https://api.github.com/repos/intelsdi-x/snap/pulls/803","id":64042973,"html_url":"https://github.com/intelsdi-x/snap/pull/803","diff_url":"https://github.com/intelsdi-x/snap/pull/803.diff","patch_url":"https://github.com/intelsdi-x/snap/pull/803.patch","issue_url":"https://api.github.com/repos/intelsdi-x/snap/issues/803","number":803,"state":"open","locked":false,"title":"First implementation of dynamic query support","user":{"login":"IzabellaRaulin","id":11335874,"avatar_url":"https://avatars.githubusercontent.com/u/11335874?v=3","gravatar_id":"","url":"https://api.github.com/users/IzabellaRaulin","html_url":"https://github.com/IzabellaRaulin","followers_url":"https://api.github.com/users/IzabellaRaulin/followers","following_url":"https://api.github.com/users/IzabellaRaulin/following{/other_user}","gists_url":"https://api.github.com/users/IzabellaRaulin/gists{/gist_id}","starred_url":"https://api.github.com/users/IzabellaRaulin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IzabellaRaulin/subscriptions","organizations_url":"https://api.github.com/users/IzabellaRaulin/orgs","repos_url":"https://api.github.com/users/IzabellaRaulin/repos","events_url":"https://api.github.com/users/IzabellaRaulin/events{/privacy}","received_events_url":"https://api.github.com/users/IzabellaRaulin/received_events","type":"User","site_admin":false},"body":"Related to #676 \r\n\r\nSummary of changes:\r\n- adding dynamic query support (wildcard and tuple)\r\n- adding validation of metric's namespace (already part of not accepting metrics which end with an asterisk is commented out until some of plugins will be refactored)\r\n\r\nTesting done:\r\n-  checking a query support for plugin with no-dynamic metrics \r\n-  checking a query support for plugin with dynamic metrics (if plugin accepts wildcards in this location the framework does not attempt to evaluate that)\r\n\r\n@intelsdi-x/snap-maintainers\r\n\r\n","created_at":"2016-03-24T14:39:28Z","updated_at":"2016-03-25T14:41:13Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3eeed01ab190a6f1a1a7af52f24a2b93486d3d37","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/intelsdi-x/snap/pulls/803/commits","review_comments_url":"https://api.github.com/repos/intelsdi-x/snap/pulls/803/comments","review_comment_url":"https://api.github.com/repos/intelsdi-x/snap/pulls/comments{/number}","comments_url":"https://api.github.com/repos/intelsdi-x/snap/issues/803/comments","statuses_url":"https://api.github.com/repos/intelsdi-x/snap/statuses/cc5c2440f1e1d9d87635f00b58686145aa5d41db","head":{"label":"IzabellaRaulin:dynamic_query_support","ref":"dynamic_query_support","sha":"cc5c2440f1e1d9d87635f00b58686145aa5d41db","user":{"login":"IzabellaRaulin","id":11335874,"avatar_url":"https://avatars.githubusercontent.com/u/11335874?v=3","gravatar_id":"","url":"https://api.github.com/users/IzabellaRaulin","html_url":"https://github.com/IzabellaRaulin","followers_url":"https://api.github.com/users/IzabellaRaulin/followers","following_url":"https://api.github.com/users/IzabellaRaulin/following{/other_user}","gists_url":"https://api.github.com/users/IzabellaRaulin/gists{/gist_id}","starred_url":"https://api.github.com/users/IzabellaRaulin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IzabellaRaulin/subscriptions","organizations_url":"https://api.github.com/users/IzabellaRaulin/orgs","repos_url":"https://api.github.com/users/IzabellaRaulin/repos","events_url":"https://api.github.com/users/IzabellaRaulin/events{/privacy}","received_events_url":"https://api.github.com/users/IzabellaRaulin/received_events","type":"User","site_admin":false},"repo":{"id":47624119,"name":"snap","full_name":"IzabellaRaulin/snap","owner":{"login":"IzabellaRaulin","id":11335874,"avatar_url":"https://avatars.githubusercontent.com/u/11335874?v=3","gravatar_id":"","url":"https://api.github.com/users/IzabellaRaulin","html_url":"https://github.com/IzabellaRaulin","followers_url":"https://api.github.com/users/IzabellaRaulin/followers","following_url":"https://api.github.com/users/IzabellaRaulin/following{/other_user}","gists_url":"https://api.github.com/users/IzabellaRaulin/gists{/gist_id}","starred_url":"https://api.github.com/users/IzabellaRaulin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IzabellaRaulin/subscriptions","organizations_url":"https://api.github.com/users/IzabellaRaulin/orgs","repos_url":"https://api.github.com/users/IzabellaRaulin/repos","events_url":"https://api.github.com/users/IzabellaRaulin/events{/privacy}","received_events_url":"https://api.github.com/users/IzabellaRaulin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/IzabellaRaulin/snap","description":"A powerful telemetry framework","fork":true,"url":"https://api.github.com/repos/IzabellaRaulin/snap","forks_url":"https://api.github.com/repos/IzabellaRaulin/snap/forks","keys_url":"https://api.github.com/repos/IzabellaRaulin/snap/keys{/key_id}","collaborators_url":"https://api.github.com/repos/IzabellaRaulin/snap/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/IzabellaRaulin/snap/teams","hooks_url":"https://api.github.com/repos/IzabellaRaulin/snap/hooks","issue_events_url":"https://api.github.com/repos/IzabellaRaulin/snap/issues/events{/number}","events_url":"https://api.github.com/repos/IzabellaRaulin/snap/events","assignees_url":"https://api.github.com/repos/IzabellaRaulin/snap/assignees{/user}","branches_url":"https://api.github.com/repos/IzabellaRaulin/snap/branches{/branch}","tags_url":"https://api.github.com/repos/IzabellaRaulin/snap/tags","blobs_url":"https://api.github.com/repos/IzabellaRaulin/snap/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/IzabellaRaulin/snap/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/IzabellaRaulin/snap/git/refs{/sha}","trees_url":"https://api.github.com/repos/IzabellaRaulin/snap/git/trees{/sha}","statuses_url":"https://api.github.com/repos/IzabellaRaulin/snap/statuses/{sha}","languages_url":"https://api.github.com/repos/IzabellaRaulin/snap/languages","stargazers_url":"https://api.github.com/repos/IzabellaRaulin/snap/stargazers","contributors_url":"https://api.github.com/repos/IzabellaRaulin/snap/contributors","subscribers_url":"https://api.github.com/repos/IzabellaRaulin/snap/subscribers","subscription_url":"https://api.github.com/repos/IzabellaRaulin/snap/subscription","commits_url":"https://api.github.com/repos/IzabellaRaulin/snap/commits{/sha}","git_commits_url":"https://api.github.com/repos/IzabellaRaulin/snap/git/commits{/sha}","comments_url":"https://api.github.com/repos/IzabellaRaulin/snap/comments{/number}","issue_comment_url":"https://api.github.com/repos/IzabellaRaulin/snap/issues/comments{/number}","contents_url":"https://api.github.com/repos/IzabellaRaulin/snap/contents/{+path}","compare_url":"https://api.github.com/repos/IzabellaRaulin/snap/compare/{base}...{head}","merges_url":"https://api.github.com/repos/IzabellaRaulin/snap/merges","archive_url":"https://api.github.com/repos/IzabellaRaulin/snap/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/IzabellaRaulin/snap/downloads","issues_url":"https://api.github.com/repos/IzabellaRaulin/snap/issues{/number}","pulls_url":"https://api.github.com/repos/IzabellaRaulin/snap/pulls{/number}","milestones_url":"https://api.github.com/repos/IzabellaRaulin/snap/milestones{/number}","notifications_url":"https://api.github.com/repos/IzabellaRaulin/snap/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/IzabellaRaulin/snap/labels{/name}","releases_url":"https://api.github.com/repos/IzabellaRaulin/snap/releases{/id}","deployments_url":"https://api.github.com/repos/IzabellaRaulin/snap/deployments","created_at":"2015-12-08T13:34:02Z","updated_at":"2016-01-12T12:31:42Z","pushed_at":"2016-03-24T14:25:01Z","git_url":"git://github.com/IzabellaRaulin/snap.git","ssh_url":"git@github.com:IzabellaRaulin/snap.git","clone_url":"https://github.com/IzabellaRaulin/snap.git","svn_url":"https://github.com/IzabellaRaulin/snap","homepage":"http://github.com/intelsdi-x/snap","size":9735,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"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":"master"}},"base":{"label":"intelsdi-x:master","ref":"master","sha":"89e29ab274b1fe7e353949b7d0cfaca27ddd3f8a","user":{"login":"intelsdi-x","id":8398747,"avatar_url":"https://avatars.githubusercontent.com/u/8398747?v=3","gravatar_id":"","url":"https://api.github.com/users/intelsdi-x","html_url":"https://github.com/intelsdi-x","followers_url":"https://api.github.com/users/intelsdi-x/followers","following_url":"https://api.github.com/users/intelsdi-x/following{/other_user}","gists_url":"https://api.github.com/users/intelsdi-x/gists{/gist_id}","starred_url":"https://api.github.com/users/intelsdi-x/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/intelsdi-x/subscriptions","organizations_url":"https://api.github.com/users/intelsdi-x/orgs","repos_url":"https://api.github.com/users/intelsdi-x/repos","events_url":"https://api.github.com/users/intelsdi-x/events{/privacy}","received_events_url":"https://api.github.com/users/intelsdi-x/received_events","type":"Organization","site_admin":false},"repo":{"id":22931257,"name":"snap","full_name":"intelsdi-x/snap","owner":{"login":"intelsdi-x","id":8398747,"avatar_url":"https://avatars.githubusercontent.com/u/8398747?v=3","gravatar_id":"","url":"https://api.github.com/users/intelsdi-x","html_url":"https://github.com/intelsdi-x","followers_url":"https://api.github.com/users/intelsdi-x/followers","following_url":"https://api.github.com/users/intelsdi-x/following{/other_user}","gists_url":"https://api.github.com/users/intelsdi-x/gists{/gist_id}","starred_url":"https://api.github.com/users/intelsdi-x/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/intelsdi-x/subscriptions","organizations_url":"https://api.github.com/users/intelsdi-x/orgs","repos_url":"https://api.github.com/users/intelsdi-x/repos","events_url":"https://api.github.com/users/intelsdi-x/events{/privacy}","received_events_url":"https://api.github.com/users/intelsdi-x/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/intelsdi-x/snap","description":"A powerful telemetry framework","fork":false,"url":"https://api.github.com/repos/intelsdi-x/snap","forks_url":"https://api.github.com/repos/intelsdi-x/snap/forks","keys_url":"https://api.github.com/repos/intelsdi-x/snap/keys{/key_id}","collaborators_url":"https://api.github.com/repos/intelsdi-x/snap/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/intelsdi-x/snap/teams","hooks_url":"https://api.github.com/repos/intelsdi-x/snap/hooks","issue_events_url":"https://api.github.com/repos/intelsdi-x/snap/issues/events{/number}","events_url":"https://api.github.com/repos/intelsdi-x/snap/events","assignees_url":"https://api.github.com/repos/intelsdi-x/snap/assignees{/user}","branches_url":"https://api.github.com/repos/intelsdi-x/snap/branches{/branch}","tags_url":"https://api.github.com/repos/intelsdi-x/snap/tags","blobs_url":"https://api.github.com/repos/intelsdi-x/snap/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/intelsdi-x/snap/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/intelsdi-x/snap/git/refs{/sha}","trees_url":"https://api.github.com/repos/intelsdi-x/snap/git/trees{/sha}","statuses_url":"https://api.github.com/repos/intelsdi-x/snap/statuses/{sha}","languages_url":"https://api.github.com/repos/intelsdi-x/snap/languages","stargazers_url":"https://api.github.com/repos/intelsdi-x/snap/stargazers","contributors_url":"https://api.github.com/repos/intelsdi-x/snap/contributors","subscribers_url":"https://api.github.com/repos/intelsdi-x/snap/subscribers","subscription_url":"https://api.github.com/repos/intelsdi-x/snap/subscription","commits_url":"https://api.github.com/repos/intelsdi-x/snap/commits{/sha}","git_commits_url":"https://api.github.com/repos/intelsdi-x/snap/git/commits{/sha}","comments_url":"https://api.github.com/repos/intelsdi-x/snap/comments{/number}","issue_comment_url":"https://api.github.com/repos/intelsdi-x/snap/issues/comments{/number}","contents_url":"https://api.github.com/repos/intelsdi-x/snap/contents/{+path}","compare_url":"https://api.github.com/repos/intelsdi-x/snap/compare/{base}...{head}","merges_url":"https://api.github.com/repos/intelsdi-x/snap/merges","archive_url":"https://api.github.com/repos/intelsdi-x/snap/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/intelsdi-x/snap/downloads","issues_url":"https://api.github.com/repos/intelsdi-x/snap/issues{/number}","pulls_url":"https://api.github.com/repos/intelsdi-x/snap/pulls{/number}","milestones_url":"https://api.github.com/repos/intelsdi-x/snap/milestones{/number}","notifications_url":"https://api.github.com/repos/intelsdi-x/snap/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/intelsdi-x/snap/labels{/name}","releases_url":"https://api.github.com/repos/intelsdi-x/snap/releases{/id}","deployments_url":"https://api.github.com/repos/intelsdi-x/snap/deployments","created_at":"2014-08-13T21:04:51Z","updated_at":"2016-03-25T13:20:32Z","pushed_at":"2016-03-25T09:00:09Z","git_url":"git://github.com/intelsdi-x/snap.git","ssh_url":"git@github.com:intelsdi-x/snap.git","clone_url":"https://github.com/intelsdi-x/snap.git","svn_url":"https://github.com/intelsdi-x/snap","homepage":"http://intelsdi-x.github.io/snap/","size":22980,"stargazers_count":582,"watchers_count":582,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":62,"mirror_url":null,"open_issues_count":77,"forks":62,"open_issues":77,"watchers":582,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/intelsdi-x/snap/pulls/803"},"html":{"href":"https://github.com/intelsdi-x/snap/pull/803"},"issue":{"href":"https://api.github.com/repos/intelsdi-x/snap/issues/803"},"comments":{"href":"https://api.github.com/repos/intelsdi-x/snap/issues/803/comments"},"review_comments":{"href":"https://api.github.com/repos/intelsdi-x/snap/pulls/803/comments"},"review_comment":{"href":"https://api.github.com/repos/intelsdi-x/snap/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/intelsdi-x/snap/pulls/803/commits"},"statuses":{"href":"https://api.github.com/repos/intelsdi-x/snap/statuses/cc5c2440f1e1d9d87635f00b58686145aa5d41db"}}}}