We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Support for varnish instances by name
We have several varnish instances on one server. Each has a name and can be referenced with `-n name` via the command line tools.

```
-n  Specifies the name of the varnishd instance to get logs from. If -n is not specified, the host name is used.
```

(from https://www.varnish-cache.org/docs/3.0/reference/varnishstat.html)

It would be nice if the name could be specified in the yaml and the check would use it automatically. I've tried adding `-n name` to the bin location but that fails.

I'll probably try to add this later when I have a chance, unless someone else can do it quickly.

<!---
@huboard:{"order":770.0}
-->


--- 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/varnish.py`
Content:
```
1 import xml.parsers.expat # python 2.4 compatible
2 import re
3 import subprocess
4 
5 from checks import AgentCheck
6 
7 class Varnish(AgentCheck):
8     # XML parsing bits, a.k.a. Kafka in Code
9     def _reset(self):
10         self._current_element = ""
11         self._current_metric = "varnish"
12         self._current_value = 0
13         self._current_str = ""
14         self._current_type = ""
15 
16     def _start_element(self, name, attrs):
17         self._current_element = name
18 
19     def _end_element(self, name):
20         if name == "stat":
21             m_name = self.normalize(self._current_metric)
22             if self._current_type in ("a", "c"):
23                 self.rate(m_name, long(self._current_value))
24             elif self._current_type in ("i", "g"):
25                 self.gauge(m_name, long(self._current_value))
26             else:
27                 # Unsupported data type, ignore
28                 self._reset()
29                 return # don't save
30 
31             # reset for next stat element
32             self._reset()
33         elif name in ("type", "ident", "name"):
34             self._current_metric += "." + self._current_str
35 
36     def _char_data(self, data):
37         self.log.debug("Data %s [%s]" % (data, self._current_element))
38         data = data.strip()
39         if len(data) > 0 and self._current_element != "":
40             if self._current_element == "value":
41                 self._current_value = long(data)
42             elif self._current_element == "flag":
43                 self._current_type = data
44             else:
45                 self._current_str = data
46 
47     def check(self, instance):
48         """Extract stats from varnishstat -x
49 
50         The text option (-1) is not reliable enough when counters get large.
51         VBE.media_video_prd_services_01(10.93.67.16,,8080).happy18446744073709551615
52 
53         2 types of data, "a" for counter ("c" in newer versions of varnish), "i" for gauge ("g")
54         https://github.com/varnish/Varnish-Cache/blob/master/include/tbl/vsc_fields.h
55 
56         Bitmaps are not supported.
57 
58         <varnishstat>
59             <stat>
60                 <name>fetch_304</name>
61                 <value>0</value>
62                 <flag>a</flag>
63                 <description>Fetch no body (304)</description>
64             </stat>
65             <stat>
66                 <name>n_sess_mem</name>
67                 <value>334</value>
68                 <flag>i</flag>
69                 <description>N struct sess_mem</description>
70             </stat>
71             <stat>
72                 <type>LCK</type>
73                 <ident>vcl</ident>
74                 <name>creat</name>
75                 <value>1</value>
76                 <flag>a</flag>
77                 <description>Created locks</description>
78             </stat>
79         </varnishstat>
80         """
81         # Not configured? Not a problem.
82         if instance.get("varnishstat", None) is None:
83             raise Exception("varnishstat is not configured")
84         tags = instance.get('tags', [])
85 
86         # Get the varnish version from varnishstat
87         output, error = subprocess.Popen([instance.get("varnishstat"), "-V"],
88                                          stdout=subprocess.PIPE,
89                                          stderr=subprocess.PIPE).communicate()
90 
91         # Assumptions regarding varnish's version
92         use_xml = True
93         arg = "-x" # varnishstat argument
94         version = 3
95 
96         m1 = re.search(r"varnish-(\d+)", output, re.MULTILINE)
97         # v2 prints the version on stderr, v3 on stdout
98         m2 = re.search(r"varnish-(\d+)", error, re.MULTILINE)
99 
100         if m1 is None and m2 is None:
101             self.log.warn("Cannot determine the version of varnishstat, assuming 3 or greater")
102             self.warning("Cannot determine the version of varnishstat, assuming 3 or greater")
103         else:
104             if m1 is not None:
105                 version = int(m1.group(1))
106             elif m2 is not None:
107                 version = int(m2.group(1))
108 
109         self.log.debug("Varnish version: %d" % version)
110 
111         # Location of varnishstat
112         if version <= 2:
113             use_xml = False
114             arg = "-1"
115 
116         output, error = subprocess.Popen([instance.get("varnishstat"), arg],
117                                          stdout=subprocess.PIPE,
118                                          stderr=subprocess.PIPE).communicate()
119         if error and len(error) > 0:
120             self.log.error(error)
121         self._parse_varnishstat(output, use_xml, tags)
122 
123     def _parse_varnishstat(self, output, use_xml, tags=None):
124         tags = tags or []
125         if use_xml:
126             p = xml.parsers.expat.ParserCreate()
127             p.StartElementHandler = self._start_element
128             p.EndElementHandler = self._end_element
129             p.CharacterDataHandler = self._char_data
130             self._reset()
131             p.Parse(output, True)
132         else:
133             for line in output.split("\n"):
134                 self.log.debug("Parsing varnish results: %s" % line)
135                 fields = line.split()
136                 if len(fields) < 3:
137                     break
138                 name, gauge_val, rate_val = fields[0], fields[1], fields[2]
139                 metric_name = self.normalize(name, prefix="varnish")
140 
141                 # Now figure out which value to pick
142                 if rate_val.lower() in ("nan", "."):
143                     # col 2 matters
144                     self.log.debug("Varnish (gauge) %s %d" % (metric_name, int(gauge_val)))
145                     self.gauge(metric_name, int(gauge_val))
146                 else:
147                     # col 3 has a rate (since restart)
148                     self.log.debug("Varnish (rate) %s %d" % (metric_name, int(gauge_val)))
149                     self.rate(metric_name, float(gauge_val))
150 
151     @staticmethod
152     def parse_agent_config(agentConfig):
153         if not agentConfig.get('varnishstat'):
154             return False
155 
156         return {
157             'instances': [{'varnishstat': agentConfig.get('varnishstat')}]
158         }
159
```
--- 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/varnish.py b/checks.d/varnish.py
--- a/checks.d/varnish.py
+++ b/checks.d/varnish.py
@@ -82,6 +82,7 @@
         if instance.get("varnishstat", None) is None:
             raise Exception("varnishstat is not configured")
         tags = instance.get('tags', [])
+        name = instance.get('name')
 
         # Get the varnish version from varnishstat
         output, error = subprocess.Popen([instance.get("varnishstat"), "-V"],
@@ -113,9 +114,19 @@
             use_xml = False
             arg = "-1"
 
-        output, error = subprocess.Popen([instance.get("varnishstat"), arg],
-                                         stdout=subprocess.PIPE,
-                                         stderr=subprocess.PIPE).communicate()
+        cmd = [instance.get("varnishstat"), arg]
+        if name is not None:
+            cmd.extend(['-n', name])
+            tags += [u'varnish_name:%s' % name]
+        else:
+            tags += [u'varnish_name:default']
+        try:
+            proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+                                         stderr=subprocess.PIPE)
+            output, error = proc.communicate()
+        except Exception:
+            self.log.error(u"Failed to run %s" % repr(cmd))
+            raise
         if error and len(error) > 0:
             self.log.error(error)
         self._parse_varnishstat(output, use_xml, tags)
@@ -142,11 +153,11 @@
                 if rate_val.lower() in ("nan", "."):
                     # col 2 matters
                     self.log.debug("Varnish (gauge) %s %d" % (metric_name, int(gauge_val)))
-                    self.gauge(metric_name, int(gauge_val))
+                    self.gauge(metric_name, int(gauge_val), tags=tags)
                 else:
                     # col 3 has a rate (since restart)
                     self.log.debug("Varnish (rate) %s %d" % (metric_name, int(gauge_val)))
-                    self.rate(metric_name, float(gauge_val))
+                    self.rate(metric_name, float(gauge_val), tags=tags)
 
     @staticmethod
     def parse_agent_config(agentConfig):

{"golden_diff": "diff --git a/checks.d/varnish.py b/checks.d/varnish.py\n--- a/checks.d/varnish.py\n+++ b/checks.d/varnish.py\n@@ -82,6 +82,7 @@\n         if instance.get(\"varnishstat\", None) is None:\n             raise Exception(\"varnishstat is not configured\")\n         tags = instance.get('tags', [])\n+        name = instance.get('name')\n \n         # Get the varnish version from varnishstat\n         output, error = subprocess.Popen([instance.get(\"varnishstat\"), \"-V\"],\n@@ -113,9 +114,19 @@\n             use_xml = False\n             arg = \"-1\"\n \n-        output, error = subprocess.Popen([instance.get(\"varnishstat\"), arg],\n-                                         stdout=subprocess.PIPE,\n-                                         stderr=subprocess.PIPE).communicate()\n+        cmd = [instance.get(\"varnishstat\"), arg]\n+        if name is not None:\n+            cmd.extend(['-n', name])\n+            tags += [u'varnish_name:%s' % name]\n+        else:\n+            tags += [u'varnish_name:default']\n+        try:\n+            proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,\n+                                         stderr=subprocess.PIPE)\n+            output, error = proc.communicate()\n+        except Exception:\n+            self.log.error(u\"Failed to run %s\" % repr(cmd))\n+            raise\n         if error and len(error) > 0:\n             self.log.error(error)\n         self._parse_varnishstat(output, use_xml, tags)\n@@ -142,11 +153,11 @@\n                 if rate_val.lower() in (\"nan\", \".\"):\n                     # col 2 matters\n                     self.log.debug(\"Varnish (gauge) %s %d\" % (metric_name, int(gauge_val)))\n-                    self.gauge(metric_name, int(gauge_val))\n+                    self.gauge(metric_name, int(gauge_val), tags=tags)\n                 else:\n                     # col 3 has a rate (since restart)\n                     self.log.debug(\"Varnish (rate) %s %d\" % (metric_name, int(gauge_val)))\n-                    self.rate(metric_name, float(gauge_val))\n+                    self.rate(metric_name, float(gauge_val), tags=tags)\n \n     @staticmethod\n     def parse_agent_config(agentConfig):\n", "issue": "Support for varnish instances by name\nWe have several varnish instances on one server. Each has a name and can be referenced with `-n name` via the command line tools.\n\n```\n-n  Specifies the name of the varnishd instance to get logs from. If -n is not specified, the host name is used.\n```\n\n(from https://www.varnish-cache.org/docs/3.0/reference/varnishstat.html)\n\nIt would be nice if the name could be specified in the yaml and the check would use it automatically. I've tried adding `-n name` to the bin location but that fails.\n\nI'll probably try to add this later when I have a chance, unless someone else can do it quickly.\n\n<!---\n@huboard:{\"order\":770.0}\n-->\n\n", "before_files": [{"content": "import xml.parsers.expat # python 2.4 compatible\nimport re\nimport subprocess\n\nfrom checks import AgentCheck\n\nclass Varnish(AgentCheck):\n    # XML parsing bits, a.k.a. Kafka in Code\n    def _reset(self):\n        self._current_element = \"\"\n        self._current_metric = \"varnish\"\n        self._current_value = 0\n        self._current_str = \"\"\n        self._current_type = \"\"\n\n    def _start_element(self, name, attrs):\n        self._current_element = name\n\n    def _end_element(self, name):\n        if name == \"stat\":\n            m_name = self.normalize(self._current_metric)\n            if self._current_type in (\"a\", \"c\"):\n                self.rate(m_name, long(self._current_value))\n            elif self._current_type in (\"i\", \"g\"):\n                self.gauge(m_name, long(self._current_value))\n            else:\n                # Unsupported data type, ignore\n                self._reset()\n                return # don't save\n\n            # reset for next stat element\n            self._reset()\n        elif name in (\"type\", \"ident\", \"name\"):\n            self._current_metric += \".\" + self._current_str\n\n    def _char_data(self, data):\n        self.log.debug(\"Data %s [%s]\" % (data, self._current_element))\n        data = data.strip()\n        if len(data) > 0 and self._current_element != \"\":\n            if self._current_element == \"value\":\n                self._current_value = long(data)\n            elif self._current_element == \"flag\":\n                self._current_type = data\n            else:\n                self._current_str = data\n\n    def check(self, instance):\n        \"\"\"Extract stats from varnishstat -x\n\n        The text option (-1) is not reliable enough when counters get large.\n        VBE.media_video_prd_services_01(10.93.67.16,,8080).happy18446744073709551615\n\n        2 types of data, \"a\" for counter (\"c\" in newer versions of varnish), \"i\" for gauge (\"g\")\n        https://github.com/varnish/Varnish-Cache/blob/master/include/tbl/vsc_fields.h\n\n        Bitmaps are not supported.\n\n        <varnishstat>\n            <stat>\n                <name>fetch_304</name>\n                <value>0</value>\n                <flag>a</flag>\n                <description>Fetch no body (304)</description>\n            </stat>\n            <stat>\n                <name>n_sess_mem</name>\n                <value>334</value>\n                <flag>i</flag>\n                <description>N struct sess_mem</description>\n            </stat>\n            <stat>\n                <type>LCK</type>\n                <ident>vcl</ident>\n                <name>creat</name>\n                <value>1</value>\n                <flag>a</flag>\n                <description>Created locks</description>\n            </stat>\n        </varnishstat>\n        \"\"\"\n        # Not configured? Not a problem.\n        if instance.get(\"varnishstat\", None) is None:\n            raise Exception(\"varnishstat is not configured\")\n        tags = instance.get('tags', [])\n\n        # Get the varnish version from varnishstat\n        output, error = subprocess.Popen([instance.get(\"varnishstat\"), \"-V\"],\n                                         stdout=subprocess.PIPE,\n                                         stderr=subprocess.PIPE).communicate()\n\n        # Assumptions regarding varnish's version\n        use_xml = True\n        arg = \"-x\" # varnishstat argument\n        version = 3\n\n        m1 = re.search(r\"varnish-(\\d+)\", output, re.MULTILINE)\n        # v2 prints the version on stderr, v3 on stdout\n        m2 = re.search(r\"varnish-(\\d+)\", error, re.MULTILINE)\n\n        if m1 is None and m2 is None:\n            self.log.warn(\"Cannot determine the version of varnishstat, assuming 3 or greater\")\n            self.warning(\"Cannot determine the version of varnishstat, assuming 3 or greater\")\n        else:\n            if m1 is not None:\n                version = int(m1.group(1))\n            elif m2 is not None:\n                version = int(m2.group(1))\n\n        self.log.debug(\"Varnish version: %d\" % version)\n\n        # Location of varnishstat\n        if version <= 2:\n            use_xml = False\n            arg = \"-1\"\n\n        output, error = subprocess.Popen([instance.get(\"varnishstat\"), arg],\n                                         stdout=subprocess.PIPE,\n                                         stderr=subprocess.PIPE).communicate()\n        if error and len(error) > 0:\n            self.log.error(error)\n        self._parse_varnishstat(output, use_xml, tags)\n\n    def _parse_varnishstat(self, output, use_xml, tags=None):\n        tags = tags or []\n        if use_xml:\n            p = xml.parsers.expat.ParserCreate()\n            p.StartElementHandler = self._start_element\n            p.EndElementHandler = self._end_element\n            p.CharacterDataHandler = self._char_data\n            self._reset()\n            p.Parse(output, True)\n        else:\n            for line in output.split(\"\\n\"):\n                self.log.debug(\"Parsing varnish results: %s\" % line)\n                fields = line.split()\n                if len(fields) < 3:\n                    break\n                name, gauge_val, rate_val = fields[0], fields[1], fields[2]\n                metric_name = self.normalize(name, prefix=\"varnish\")\n\n                # Now figure out which value to pick\n                if rate_val.lower() in (\"nan\", \".\"):\n                    # col 2 matters\n                    self.log.debug(\"Varnish (gauge) %s %d\" % (metric_name, int(gauge_val)))\n                    self.gauge(metric_name, int(gauge_val))\n                else:\n                    # col 3 has a rate (since restart)\n                    self.log.debug(\"Varnish (rate) %s %d\" % (metric_name, int(gauge_val)))\n                    self.rate(metric_name, float(gauge_val))\n\n    @staticmethod\n    def parse_agent_config(agentConfig):\n        if not agentConfig.get('varnishstat'):\n            return False\n\n        return {\n            'instances': [{'varnishstat': agentConfig.get('varnishstat')}]\n        }\n", "path": "checks.d/varnish.py"}], "after_files": [{"content": "import xml.parsers.expat # python 2.4 compatible\nimport re\nimport subprocess\n\nfrom checks import AgentCheck\n\nclass Varnish(AgentCheck):\n    # XML parsing bits, a.k.a. Kafka in Code\n    def _reset(self):\n        self._current_element = \"\"\n        self._current_metric = \"varnish\"\n        self._current_value = 0\n        self._current_str = \"\"\n        self._current_type = \"\"\n\n    def _start_element(self, name, attrs):\n        self._current_element = name\n\n    def _end_element(self, name):\n        if name == \"stat\":\n            m_name = self.normalize(self._current_metric)\n            if self._current_type in (\"a\", \"c\"):\n                self.rate(m_name, long(self._current_value))\n            elif self._current_type in (\"i\", \"g\"):\n                self.gauge(m_name, long(self._current_value))\n            else:\n                # Unsupported data type, ignore\n                self._reset()\n                return # don't save\n\n            # reset for next stat element\n            self._reset()\n        elif name in (\"type\", \"ident\", \"name\"):\n            self._current_metric += \".\" + self._current_str\n\n    def _char_data(self, data):\n        self.log.debug(\"Data %s [%s]\" % (data, self._current_element))\n        data = data.strip()\n        if len(data) > 0 and self._current_element != \"\":\n            if self._current_element == \"value\":\n                self._current_value = long(data)\n            elif self._current_element == \"flag\":\n                self._current_type = data\n            else:\n                self._current_str = data\n\n    def check(self, instance):\n        \"\"\"Extract stats from varnishstat -x\n\n        The text option (-1) is not reliable enough when counters get large.\n        VBE.media_video_prd_services_01(10.93.67.16,,8080).happy18446744073709551615\n\n        2 types of data, \"a\" for counter (\"c\" in newer versions of varnish), \"i\" for gauge (\"g\")\n        https://github.com/varnish/Varnish-Cache/blob/master/include/tbl/vsc_fields.h\n\n        Bitmaps are not supported.\n\n        <varnishstat>\n            <stat>\n                <name>fetch_304</name>\n                <value>0</value>\n                <flag>a</flag>\n                <description>Fetch no body (304)</description>\n            </stat>\n            <stat>\n                <name>n_sess_mem</name>\n                <value>334</value>\n                <flag>i</flag>\n                <description>N struct sess_mem</description>\n            </stat>\n            <stat>\n                <type>LCK</type>\n                <ident>vcl</ident>\n                <name>creat</name>\n                <value>1</value>\n                <flag>a</flag>\n                <description>Created locks</description>\n            </stat>\n        </varnishstat>\n        \"\"\"\n        # Not configured? Not a problem.\n        if instance.get(\"varnishstat\", None) is None:\n            raise Exception(\"varnishstat is not configured\")\n        tags = instance.get('tags', [])\n        name = instance.get('name')\n\n        # Get the varnish version from varnishstat\n        output, error = subprocess.Popen([instance.get(\"varnishstat\"), \"-V\"],\n                                         stdout=subprocess.PIPE,\n                                         stderr=subprocess.PIPE).communicate()\n\n        # Assumptions regarding varnish's version\n        use_xml = True\n        arg = \"-x\" # varnishstat argument\n        version = 3\n\n        m1 = re.search(r\"varnish-(\\d+)\", output, re.MULTILINE)\n        # v2 prints the version on stderr, v3 on stdout\n        m2 = re.search(r\"varnish-(\\d+)\", error, re.MULTILINE)\n\n        if m1 is None and m2 is None:\n            self.log.warn(\"Cannot determine the version of varnishstat, assuming 3 or greater\")\n            self.warning(\"Cannot determine the version of varnishstat, assuming 3 or greater\")\n        else:\n            if m1 is not None:\n                version = int(m1.group(1))\n            elif m2 is not None:\n                version = int(m2.group(1))\n\n        self.log.debug(\"Varnish version: %d\" % version)\n\n        # Location of varnishstat\n        if version <= 2:\n            use_xml = False\n            arg = \"-1\"\n\n        cmd = [instance.get(\"varnishstat\"), arg]\n        if name is not None:\n            cmd.extend(['-n', name])\n            tags += [u'varnish_name:%s' % name]\n        else:\n            tags += [u'varnish_name:default']\n        try:\n            proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,\n                                         stderr=subprocess.PIPE)\n            output, error = proc.communicate()\n        except Exception:\n            self.log.error(u\"Failed to run %s\" % repr(cmd))\n            raise\n        if error and len(error) > 0:\n            self.log.error(error)\n        self._parse_varnishstat(output, use_xml, tags)\n\n    def _parse_varnishstat(self, output, use_xml, tags=None):\n        tags = tags or []\n        if use_xml:\n            p = xml.parsers.expat.ParserCreate()\n            p.StartElementHandler = self._start_element\n            p.EndElementHandler = self._end_element\n            p.CharacterDataHandler = self._char_data\n            self._reset()\n            p.Parse(output, True)\n        else:\n            for line in output.split(\"\\n\"):\n                self.log.debug(\"Parsing varnish results: %s\" % line)\n                fields = line.split()\n                if len(fields) < 3:\n                    break\n                name, gauge_val, rate_val = fields[0], fields[1], fields[2]\n                metric_name = self.normalize(name, prefix=\"varnish\")\n\n                # Now figure out which value to pick\n                if rate_val.lower() in (\"nan\", \".\"):\n                    # col 2 matters\n                    self.log.debug(\"Varnish (gauge) %s %d\" % (metric_name, int(gauge_val)))\n                    self.gauge(metric_name, int(gauge_val), tags=tags)\n                else:\n                    # col 3 has a rate (since restart)\n                    self.log.debug(\"Varnish (rate) %s %d\" % (metric_name, int(gauge_val)))\n                    self.rate(metric_name, float(gauge_val), tags=tags)\n\n    @staticmethod\n    def parse_agent_config(agentConfig):\n        if not agentConfig.get('varnishstat'):\n            return False\n\n        return {\n            'instances': [{'varnishstat': agentConfig.get('varnishstat')}]\n        }\n", "path": "checks.d/varnish.py"}]}