We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[go_expvar] add ability to override default metric namespace
By default, the go_expvar check uses the `go_expvar` namespace. However, I'd much rather have these metrics available under the same namespace as my application metrics. To accomplish this, I'm thinking it would just be a `namespace` key within `init_config` that allows you to override the default value.

Looking at the `go_expvar` package it seems fairly simple, however I thought I'd open an issue before trying to submit a patch.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `checks.d/go_expvar.py`
Content:
```
1 # stdlib
2 from collections import defaultdict
3 import re
4 
5 # 3rd party
6 import requests
7 
8 # project
9 from checks import AgentCheck
10 
11 DEFAULT_MAX_METRICS = 350
12 PATH = "path"
13 ALIAS = "alias"
14 TYPE = "type"
15 TAGS = "tags"
16 
17 GAUGE = "gauge"
18 RATE = "rate"
19 DEFAULT_TYPE = GAUGE
20 
21 
22 SUPPORTED_TYPES = {
23     GAUGE: AgentCheck.gauge,
24     RATE: AgentCheck.rate,
25 }
26 
27 METRIC_NAMESPACE = "go_expvar"
28 
29 
30 # See http://golang.org/pkg/runtime/#MemStats
31 DEFAULT_GAUGE_MEMSTAT_METRICS = [
32     # General statistics
33     "Alloc", "TotalAlloc",
34 
35     # Main allocation heap statistics
36     "HeapAlloc", "HeapSys", "HeapIdle", "HeapInuse",
37     "HeapReleased", "HeapObjects",
38 
39 ]
40 
41 DEFAULT_RATE_MEMSTAT_METRICS = [
42     # General statistics
43     "Lookups", "Mallocs", "Frees",
44 
45     # Garbage collector statistics
46     "PauseTotalNs", "NumGC",
47 ]
48 
49 DEFAULT_METRICS = [{PATH: "memstats/%s" % path, TYPE: GAUGE} for path in DEFAULT_GAUGE_MEMSTAT_METRICS] +\
50     [{PATH: "memstats/%s" % path, TYPE: RATE} for path in DEFAULT_RATE_MEMSTAT_METRICS]
51 
52 
53 class GoExpvar(AgentCheck):
54 
55     def __init__(self, name, init_config, agentConfig, instances=None):
56         AgentCheck.__init__(self, name, init_config, agentConfig, instances)
57         self._last_gc_count = defaultdict(int)
58 
59     def _get_data(self, url):
60         r = requests.get(url)
61         r.raise_for_status()
62         return r.json()
63 
64     def _load(self, instance):
65         url = instance.get('expvar_url')
66         if not url:
67             raise Exception('GoExpvar instance missing "expvar_url" value.')
68 
69         tags = instance.get('tags', [])
70         tags.append("expvar_url:%s" % url)
71         data = self._get_data(url)
72         metrics = DEFAULT_METRICS + instance.get("metrics", [])
73         max_metrics = instance.get("max_returned_metrics", DEFAULT_MAX_METRICS)
74         return data, tags, metrics, max_metrics, url
75 
76     def get_gc_collection_histogram(self, data, tags, url):
77         num_gc = data.get("memstats", {}).get("NumGC")
78         pause_hist = data.get("memstats", {}).get("PauseNs")
79         last_gc_count = self._last_gc_count[url]
80         if last_gc_count == num_gc:
81             # No GC has run. Do nothing
82             return
83         start = last_gc_count % 256
84         end = (num_gc + 255) % 256 + 1
85         if start < end:
86             values = pause_hist[start:end]
87         else:
88             values = pause_hist[start:] + pause_hist[:end]
89 
90         self._last_gc_count[url] = num_gc
91 
92         for value in values:
93             self.histogram(
94                 self.normalize("memstats.PauseNs", METRIC_NAMESPACE, fix_case=True),
95                 value, tags=tags)
96 
97     def check(self, instance):
98         data, tags, metrics, max_metrics, url = self._load(instance)
99         self.get_gc_collection_histogram(data, tags, url)
100         self.parse_expvar_data(data, tags, metrics, max_metrics)
101 
102     def parse_expvar_data(self, data, tags, metrics, max_metrics):
103         '''
104         Report all the metrics based on the configuration in instance
105         If a metric is not well configured or is not present in the payload,
106         continue processing metrics but log the information to the info page
107         '''
108         count = 0
109         for metric in metrics:
110             path = metric.get(PATH)
111             metric_type = metric.get(TYPE, DEFAULT_TYPE)
112             metric_tags = list(metric.get(TAGS, []))
113             metric_tags += tags
114             alias = metric.get(ALIAS)
115 
116             if not path:
117                 self.warning("Metric %s has no path" % metric)
118                 continue
119 
120             if metric_type not in SUPPORTED_TYPES:
121                 self.warning("Metric type %s not supported for this check" % metric_type)
122                 continue
123 
124             keys = path.split("/")
125             values = self.deep_get(data, keys)
126 
127             if len(values) == 0:
128                 self.warning("No results matching path %s" % path)
129                 continue
130 
131             tag_by_path = alias is not None
132 
133             for traversed_path, value in values:
134                 actual_path = ".".join(traversed_path)
135                 if tag_by_path:
136                     metric_tags.append("path:%s" % actual_path)
137 
138                 metric_name = alias or self.normalize(actual_path, METRIC_NAMESPACE, fix_case=True)
139 
140                 try:
141                     float(value)
142                 except ValueError:
143                     self.log.warning("Unreportable value for path %s: %s" % (path, value))
144                     continue
145 
146                 if count >= max_metrics:
147                     self.warning("Reporting more metrics than the allowed maximum. "
148                                  "Please contact support@datadoghq.com for more information.")
149                     return
150 
151                 SUPPORTED_TYPES[metric_type](self, metric_name, value, metric_tags)
152                 count += 1
153 
154     def deep_get(self, content, keys, traversed_path=None):
155         '''
156         Allow to retrieve content nested inside a several layers deep dict/list
157 
158         Examples: -content: {
159                             "key1": {
160                                 "key2" : [
161                                             {
162                                                 "name"  : "object1",
163                                                 "value" : 42
164                                             },
165                                             {
166                                                 "name"  : "object2",
167                                                 "value" : 72
168                                             }
169                                           ]
170                             }
171                         }
172                   -keys: ["key1", "key2", "1", "value"] would return [(["key1", "key2", "1", "value"], 72)]
173                   -keys: ["key1", "key2", "1", "*"] would return [(["key1", "key2", "1", "value"], 72), (["key1", "key2", "1", "name"], "object2")]
174                   -keys: ["key1", "key2", "*", "value"] would return [(["key1", "key2", "1", "value"], 72), (["key1", "key2", "0", "value"], 42)]
175         '''
176 
177         if traversed_path is None:
178             traversed_path = []
179 
180         if keys == []:
181             return [(traversed_path, content)]
182 
183         key = keys[0]
184         regex = "".join(["^", key, "$"])
185         try:
186             key_rex = re.compile(regex)
187         except Exception:
188             self.warning("Cannot compile regex: %s" % regex)
189             return []
190 
191         results = []
192         for new_key, new_content in self.items(content):
193             if key_rex.match(new_key):
194                 results.extend(self.deep_get(new_content, keys[1:], traversed_path + [str(new_key)]))
195         return results
196 
197     def items(self, object):
198         if isinstance(object, list):
199             for new_key, new_content in enumerate(object):
200                 yield str(new_key), new_content
201         elif isinstance(object, dict):
202             for new_key, new_content in object.iteritems():
203                 yield str(new_key), new_content
204         else:
205             self.log.warning("Could not parse this object, check the json"
206                              "served by the expvar")
207
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/checks.d/go_expvar.py b/checks.d/go_expvar.py
--- a/checks.d/go_expvar.py
+++ b/checks.d/go_expvar.py
@@ -24,7 +24,7 @@
     RATE: AgentCheck.rate,
 }
 
-METRIC_NAMESPACE = "go_expvar"
+DEFAULT_METRIC_NAMESPACE = "go_expvar"
 
 
 # See http://golang.org/pkg/runtime/#MemStats
@@ -71,9 +71,10 @@
         data = self._get_data(url)
         metrics = DEFAULT_METRICS + instance.get("metrics", [])
         max_metrics = instance.get("max_returned_metrics", DEFAULT_MAX_METRICS)
-        return data, tags, metrics, max_metrics, url
+        namespace = instance.get('namespace', DEFAULT_METRIC_NAMESPACE)
+        return data, tags, metrics, max_metrics, url, namespace
 
-    def get_gc_collection_histogram(self, data, tags, url):
+    def get_gc_collection_histogram(self, data, tags, url, namespace):
         num_gc = data.get("memstats", {}).get("NumGC")
         pause_hist = data.get("memstats", {}).get("PauseNs")
         last_gc_count = self._last_gc_count[url]
@@ -91,15 +92,15 @@
 
         for value in values:
             self.histogram(
-                self.normalize("memstats.PauseNs", METRIC_NAMESPACE, fix_case=True),
+                self.normalize("memstats.PauseNs", namespace, fix_case=True),
                 value, tags=tags)
 
     def check(self, instance):
-        data, tags, metrics, max_metrics, url = self._load(instance)
-        self.get_gc_collection_histogram(data, tags, url)
-        self.parse_expvar_data(data, tags, metrics, max_metrics)
+        data, tags, metrics, max_metrics, url, namespace = self._load(instance)
+        self.get_gc_collection_histogram(data, tags, url, namespace)
+        self.parse_expvar_data(data, tags, metrics, max_metrics, namespace)
 
-    def parse_expvar_data(self, data, tags, metrics, max_metrics):
+    def parse_expvar_data(self, data, tags, metrics, max_metrics, namespace):
         '''
         Report all the metrics based on the configuration in instance
         If a metric is not well configured or is not present in the payload,
@@ -135,7 +136,7 @@
                 if tag_by_path:
                     metric_tags.append("path:%s" % actual_path)
 
-                metric_name = alias or self.normalize(actual_path, METRIC_NAMESPACE, fix_case=True)
+                metric_name = alias or self.normalize(actual_path, namespace, fix_case=True)
 
                 try:
                     float(value)

{"golden_diff": "diff --git a/checks.d/go_expvar.py b/checks.d/go_expvar.py\n--- a/checks.d/go_expvar.py\n+++ b/checks.d/go_expvar.py\n@@ -24,7 +24,7 @@\n     RATE: AgentCheck.rate,\n }\n \n-METRIC_NAMESPACE = \"go_expvar\"\n+DEFAULT_METRIC_NAMESPACE = \"go_expvar\"\n \n \n # See http://golang.org/pkg/runtime/#MemStats\n@@ -71,9 +71,10 @@\n         data = self._get_data(url)\n         metrics = DEFAULT_METRICS + instance.get(\"metrics\", [])\n         max_metrics = instance.get(\"max_returned_metrics\", DEFAULT_MAX_METRICS)\n-        return data, tags, metrics, max_metrics, url\n+        namespace = instance.get('namespace', DEFAULT_METRIC_NAMESPACE)\n+        return data, tags, metrics, max_metrics, url, namespace\n \n-    def get_gc_collection_histogram(self, data, tags, url):\n+    def get_gc_collection_histogram(self, data, tags, url, namespace):\n         num_gc = data.get(\"memstats\", {}).get(\"NumGC\")\n         pause_hist = data.get(\"memstats\", {}).get(\"PauseNs\")\n         last_gc_count = self._last_gc_count[url]\n@@ -91,15 +92,15 @@\n \n         for value in values:\n             self.histogram(\n-                self.normalize(\"memstats.PauseNs\", METRIC_NAMESPACE, fix_case=True),\n+                self.normalize(\"memstats.PauseNs\", namespace, fix_case=True),\n                 value, tags=tags)\n \n     def check(self, instance):\n-        data, tags, metrics, max_metrics, url = self._load(instance)\n-        self.get_gc_collection_histogram(data, tags, url)\n-        self.parse_expvar_data(data, tags, metrics, max_metrics)\n+        data, tags, metrics, max_metrics, url, namespace = self._load(instance)\n+        self.get_gc_collection_histogram(data, tags, url, namespace)\n+        self.parse_expvar_data(data, tags, metrics, max_metrics, namespace)\n \n-    def parse_expvar_data(self, data, tags, metrics, max_metrics):\n+    def parse_expvar_data(self, data, tags, metrics, max_metrics, namespace):\n         '''\n         Report all the metrics based on the configuration in instance\n         If a metric is not well configured or is not present in the payload,\n@@ -135,7 +136,7 @@\n                 if tag_by_path:\n                     metric_tags.append(\"path:%s\" % actual_path)\n \n-                metric_name = alias or self.normalize(actual_path, METRIC_NAMESPACE, fix_case=True)\n+                metric_name = alias or self.normalize(actual_path, namespace, fix_case=True)\n \n                 try:\n                     float(value)\n", "issue": "[go_expvar] add ability to override default metric namespace\nBy default, the go_expvar check uses the `go_expvar` namespace. However, I'd much rather have these metrics available under the same namespace as my application metrics. To accomplish this, I'm thinking it would just be a `namespace` key within `init_config` that allows you to override the default value.\n\nLooking at the `go_expvar` package it seems fairly simple, however I thought I'd open an issue before trying to submit a patch.\n\n", "before_files": [{"content": "# stdlib\nfrom collections import defaultdict\nimport re\n\n# 3rd party\nimport requests\n\n# project\nfrom checks import AgentCheck\n\nDEFAULT_MAX_METRICS = 350\nPATH = \"path\"\nALIAS = \"alias\"\nTYPE = \"type\"\nTAGS = \"tags\"\n\nGAUGE = \"gauge\"\nRATE = \"rate\"\nDEFAULT_TYPE = GAUGE\n\n\nSUPPORTED_TYPES = {\n    GAUGE: AgentCheck.gauge,\n    RATE: AgentCheck.rate,\n}\n\nMETRIC_NAMESPACE = \"go_expvar\"\n\n\n# See http://golang.org/pkg/runtime/#MemStats\nDEFAULT_GAUGE_MEMSTAT_METRICS = [\n    # General statistics\n    \"Alloc\", \"TotalAlloc\",\n\n    # Main allocation heap statistics\n    \"HeapAlloc\", \"HeapSys\", \"HeapIdle\", \"HeapInuse\",\n    \"HeapReleased\", \"HeapObjects\",\n\n]\n\nDEFAULT_RATE_MEMSTAT_METRICS = [\n    # General statistics\n    \"Lookups\", \"Mallocs\", \"Frees\",\n\n    # Garbage collector statistics\n    \"PauseTotalNs\", \"NumGC\",\n]\n\nDEFAULT_METRICS = [{PATH: \"memstats/%s\" % path, TYPE: GAUGE} for path in DEFAULT_GAUGE_MEMSTAT_METRICS] +\\\n    [{PATH: \"memstats/%s\" % path, TYPE: RATE} for path in DEFAULT_RATE_MEMSTAT_METRICS]\n\n\nclass GoExpvar(AgentCheck):\n\n    def __init__(self, name, init_config, agentConfig, instances=None):\n        AgentCheck.__init__(self, name, init_config, agentConfig, instances)\n        self._last_gc_count = defaultdict(int)\n\n    def _get_data(self, url):\n        r = requests.get(url)\n        r.raise_for_status()\n        return r.json()\n\n    def _load(self, instance):\n        url = instance.get('expvar_url')\n        if not url:\n            raise Exception('GoExpvar instance missing \"expvar_url\" value.')\n\n        tags = instance.get('tags', [])\n        tags.append(\"expvar_url:%s\" % url)\n        data = self._get_data(url)\n        metrics = DEFAULT_METRICS + instance.get(\"metrics\", [])\n        max_metrics = instance.get(\"max_returned_metrics\", DEFAULT_MAX_METRICS)\n        return data, tags, metrics, max_metrics, url\n\n    def get_gc_collection_histogram(self, data, tags, url):\n        num_gc = data.get(\"memstats\", {}).get(\"NumGC\")\n        pause_hist = data.get(\"memstats\", {}).get(\"PauseNs\")\n        last_gc_count = self._last_gc_count[url]\n        if last_gc_count == num_gc:\n            # No GC has run. Do nothing\n            return\n        start = last_gc_count % 256\n        end = (num_gc + 255) % 256 + 1\n        if start < end:\n            values = pause_hist[start:end]\n        else:\n            values = pause_hist[start:] + pause_hist[:end]\n\n        self._last_gc_count[url] = num_gc\n\n        for value in values:\n            self.histogram(\n                self.normalize(\"memstats.PauseNs\", METRIC_NAMESPACE, fix_case=True),\n                value, tags=tags)\n\n    def check(self, instance):\n        data, tags, metrics, max_metrics, url = self._load(instance)\n        self.get_gc_collection_histogram(data, tags, url)\n        self.parse_expvar_data(data, tags, metrics, max_metrics)\n\n    def parse_expvar_data(self, data, tags, metrics, max_metrics):\n        '''\n        Report all the metrics based on the configuration in instance\n        If a metric is not well configured or is not present in the payload,\n        continue processing metrics but log the information to the info page\n        '''\n        count = 0\n        for metric in metrics:\n            path = metric.get(PATH)\n            metric_type = metric.get(TYPE, DEFAULT_TYPE)\n            metric_tags = list(metric.get(TAGS, []))\n            metric_tags += tags\n            alias = metric.get(ALIAS)\n\n            if not path:\n                self.warning(\"Metric %s has no path\" % metric)\n                continue\n\n            if metric_type not in SUPPORTED_TYPES:\n                self.warning(\"Metric type %s not supported for this check\" % metric_type)\n                continue\n\n            keys = path.split(\"/\")\n            values = self.deep_get(data, keys)\n\n            if len(values) == 0:\n                self.warning(\"No results matching path %s\" % path)\n                continue\n\n            tag_by_path = alias is not None\n\n            for traversed_path, value in values:\n                actual_path = \".\".join(traversed_path)\n                if tag_by_path:\n                    metric_tags.append(\"path:%s\" % actual_path)\n\n                metric_name = alias or self.normalize(actual_path, METRIC_NAMESPACE, fix_case=True)\n\n                try:\n                    float(value)\n                except ValueError:\n                    self.log.warning(\"Unreportable value for path %s: %s\" % (path, value))\n                    continue\n\n                if count >= max_metrics:\n                    self.warning(\"Reporting more metrics than the allowed maximum. \"\n                                 \"Please contact support@datadoghq.com for more information.\")\n                    return\n\n                SUPPORTED_TYPES[metric_type](self, metric_name, value, metric_tags)\n                count += 1\n\n    def deep_get(self, content, keys, traversed_path=None):\n        '''\n        Allow to retrieve content nested inside a several layers deep dict/list\n\n        Examples: -content: {\n                            \"key1\": {\n                                \"key2\" : [\n                                            {\n                                                \"name\"  : \"object1\",\n                                                \"value\" : 42\n                                            },\n                                            {\n                                                \"name\"  : \"object2\",\n                                                \"value\" : 72\n                                            }\n                                          ]\n                            }\n                        }\n                  -keys: [\"key1\", \"key2\", \"1\", \"value\"] would return [([\"key1\", \"key2\", \"1\", \"value\"], 72)]\n                  -keys: [\"key1\", \"key2\", \"1\", \"*\"] would return [([\"key1\", \"key2\", \"1\", \"value\"], 72), ([\"key1\", \"key2\", \"1\", \"name\"], \"object2\")]\n                  -keys: [\"key1\", \"key2\", \"*\", \"value\"] would return [([\"key1\", \"key2\", \"1\", \"value\"], 72), ([\"key1\", \"key2\", \"0\", \"value\"], 42)]\n        '''\n\n        if traversed_path is None:\n            traversed_path = []\n\n        if keys == []:\n            return [(traversed_path, content)]\n\n        key = keys[0]\n        regex = \"\".join([\"^\", key, \"$\"])\n        try:\n            key_rex = re.compile(regex)\n        except Exception:\n            self.warning(\"Cannot compile regex: %s\" % regex)\n            return []\n\n        results = []\n        for new_key, new_content in self.items(content):\n            if key_rex.match(new_key):\n                results.extend(self.deep_get(new_content, keys[1:], traversed_path + [str(new_key)]))\n        return results\n\n    def items(self, object):\n        if isinstance(object, list):\n            for new_key, new_content in enumerate(object):\n                yield str(new_key), new_content\n        elif isinstance(object, dict):\n            for new_key, new_content in object.iteritems():\n                yield str(new_key), new_content\n        else:\n            self.log.warning(\"Could not parse this object, check the json\"\n                             \"served by the expvar\")\n", "path": "checks.d/go_expvar.py"}], "after_files": [{"content": "# stdlib\nfrom collections import defaultdict\nimport re\n\n# 3rd party\nimport requests\n\n# project\nfrom checks import AgentCheck\n\nDEFAULT_MAX_METRICS = 350\nPATH = \"path\"\nALIAS = \"alias\"\nTYPE = \"type\"\nTAGS = \"tags\"\n\nGAUGE = \"gauge\"\nRATE = \"rate\"\nDEFAULT_TYPE = GAUGE\n\n\nSUPPORTED_TYPES = {\n    GAUGE: AgentCheck.gauge,\n    RATE: AgentCheck.rate,\n}\n\nDEFAULT_METRIC_NAMESPACE = \"go_expvar\"\n\n\n# See http://golang.org/pkg/runtime/#MemStats\nDEFAULT_GAUGE_MEMSTAT_METRICS = [\n    # General statistics\n    \"Alloc\", \"TotalAlloc\",\n\n    # Main allocation heap statistics\n    \"HeapAlloc\", \"HeapSys\", \"HeapIdle\", \"HeapInuse\",\n    \"HeapReleased\", \"HeapObjects\",\n\n]\n\nDEFAULT_RATE_MEMSTAT_METRICS = [\n    # General statistics\n    \"Lookups\", \"Mallocs\", \"Frees\",\n\n    # Garbage collector statistics\n    \"PauseTotalNs\", \"NumGC\",\n]\n\nDEFAULT_METRICS = [{PATH: \"memstats/%s\" % path, TYPE: GAUGE} for path in DEFAULT_GAUGE_MEMSTAT_METRICS] +\\\n    [{PATH: \"memstats/%s\" % path, TYPE: RATE} for path in DEFAULT_RATE_MEMSTAT_METRICS]\n\n\nclass GoExpvar(AgentCheck):\n\n    def __init__(self, name, init_config, agentConfig, instances=None):\n        AgentCheck.__init__(self, name, init_config, agentConfig, instances)\n        self._last_gc_count = defaultdict(int)\n\n    def _get_data(self, url):\n        r = requests.get(url)\n        r.raise_for_status()\n        return r.json()\n\n    def _load(self, instance):\n        url = instance.get('expvar_url')\n        if not url:\n            raise Exception('GoExpvar instance missing \"expvar_url\" value.')\n\n        tags = instance.get('tags', [])\n        tags.append(\"expvar_url:%s\" % url)\n        data = self._get_data(url)\n        metrics = DEFAULT_METRICS + instance.get(\"metrics\", [])\n        max_metrics = instance.get(\"max_returned_metrics\", DEFAULT_MAX_METRICS)\n        namespace = instance.get('namespace', DEFAULT_METRIC_NAMESPACE)\n        return data, tags, metrics, max_metrics, url, namespace\n\n    def get_gc_collection_histogram(self, data, tags, url, namespace):\n        num_gc = data.get(\"memstats\", {}).get(\"NumGC\")\n        pause_hist = data.get(\"memstats\", {}).get(\"PauseNs\")\n        last_gc_count = self._last_gc_count[url]\n        if last_gc_count == num_gc:\n            # No GC has run. Do nothing\n            return\n        start = last_gc_count % 256\n        end = (num_gc + 255) % 256 + 1\n        if start < end:\n            values = pause_hist[start:end]\n        else:\n            values = pause_hist[start:] + pause_hist[:end]\n\n        self._last_gc_count[url] = num_gc\n\n        for value in values:\n            self.histogram(\n                self.normalize(\"memstats.PauseNs\", namespace, fix_case=True),\n                value, tags=tags)\n\n    def check(self, instance):\n        data, tags, metrics, max_metrics, url, namespace = self._load(instance)\n        self.get_gc_collection_histogram(data, tags, url, namespace)\n        self.parse_expvar_data(data, tags, metrics, max_metrics, namespace)\n\n    def parse_expvar_data(self, data, tags, metrics, max_metrics, namespace):\n        '''\n        Report all the metrics based on the configuration in instance\n        If a metric is not well configured or is not present in the payload,\n        continue processing metrics but log the information to the info page\n        '''\n        count = 0\n        for metric in metrics:\n            path = metric.get(PATH)\n            metric_type = metric.get(TYPE, DEFAULT_TYPE)\n            metric_tags = list(metric.get(TAGS, []))\n            metric_tags += tags\n            alias = metric.get(ALIAS)\n\n            if not path:\n                self.warning(\"Metric %s has no path\" % metric)\n                continue\n\n            if metric_type not in SUPPORTED_TYPES:\n                self.warning(\"Metric type %s not supported for this check\" % metric_type)\n                continue\n\n            keys = path.split(\"/\")\n            values = self.deep_get(data, keys)\n\n            if len(values) == 0:\n                self.warning(\"No results matching path %s\" % path)\n                continue\n\n            tag_by_path = alias is not None\n\n            for traversed_path, value in values:\n                actual_path = \".\".join(traversed_path)\n                if tag_by_path:\n                    metric_tags.append(\"path:%s\" % actual_path)\n\n                metric_name = alias or self.normalize(actual_path, namespace, fix_case=True)\n\n                try:\n                    float(value)\n                except ValueError:\n                    self.log.warning(\"Unreportable value for path %s: %s\" % (path, value))\n                    continue\n\n                if count >= max_metrics:\n                    self.warning(\"Reporting more metrics than the allowed maximum. \"\n                                 \"Please contact support@datadoghq.com for more information.\")\n                    return\n\n                SUPPORTED_TYPES[metric_type](self, metric_name, value, metric_tags)\n                count += 1\n\n    def deep_get(self, content, keys, traversed_path=None):\n        '''\n        Allow to retrieve content nested inside a several layers deep dict/list\n\n        Examples: -content: {\n                            \"key1\": {\n                                \"key2\" : [\n                                            {\n                                                \"name\"  : \"object1\",\n                                                \"value\" : 42\n                                            },\n                                            {\n                                                \"name\"  : \"object2\",\n                                                \"value\" : 72\n                                            }\n                                          ]\n                            }\n                        }\n                  -keys: [\"key1\", \"key2\", \"1\", \"value\"] would return [([\"key1\", \"key2\", \"1\", \"value\"], 72)]\n                  -keys: [\"key1\", \"key2\", \"1\", \"*\"] would return [([\"key1\", \"key2\", \"1\", \"value\"], 72), ([\"key1\", \"key2\", \"1\", \"name\"], \"object2\")]\n                  -keys: [\"key1\", \"key2\", \"*\", \"value\"] would return [([\"key1\", \"key2\", \"1\", \"value\"], 72), ([\"key1\", \"key2\", \"0\", \"value\"], 42)]\n        '''\n\n        if traversed_path is None:\n            traversed_path = []\n\n        if keys == []:\n            return [(traversed_path, content)]\n\n        key = keys[0]\n        regex = \"\".join([\"^\", key, \"$\"])\n        try:\n            key_rex = re.compile(regex)\n        except Exception:\n            self.warning(\"Cannot compile regex: %s\" % regex)\n            return []\n\n        results = []\n        for new_key, new_content in self.items(content):\n            if key_rex.match(new_key):\n                results.extend(self.deep_get(new_content, keys[1:], traversed_path + [str(new_key)]))\n        return results\n\n    def items(self, object):\n        if isinstance(object, list):\n            for new_key, new_content in enumerate(object):\n                yield str(new_key), new_content\n        elif isinstance(object, dict):\n            for new_key, new_content in object.iteritems():\n                yield str(new_key), new_content\n        else:\n            self.log.warning(\"Could not parse this object, check the json\"\n                             \"served by the expvar\")\n", "path": "checks.d/go_expvar.py"}]}