<commit_before># (C) Datadog, Inc. 2010-2016
# All rights reserved
# Licensed under Simplified BSD License (see LICENSE)

# stdlib
from collections import defaultdict
import re
import xml.parsers.expat # python 2.4 compatible

# project
from checks import AgentCheck
from utils.subprocess_output import get_subprocess_output


class BackendStatus(object):
    HEALTHY = 'healthy'
    SICK = 'sick'
    ALL = (HEALTHY, SICK)

    @classmethod
    def to_check_status(cls, status):
        if status == cls.HEALTHY:
            return AgentCheck.OK
        elif status == cls.SICK:
            return AgentCheck.CRITICAL
        return AgentCheck.UNKNOWN

class Varnish(AgentCheck):
    SERVICE_CHECK_NAME = 'varnish.backend_healthy'

    # XML parsing bits, a.k.a. Kafka in Code
    def _reset(self):
        self._current_element = ""
        self._current_metric = "varnish"
        self._current_value = 0
        self._current_str = ""
        self._current_type = ""

    def _start_element(self, name, attrs):
        self._current_element = name

    def _end_element(self, name, tags):
        if name == "stat":
            m_name = self.normalize(self._current_metric)
            if self._current_type in ("a", "c"):
                self.log.error("Varnish (rate) %s %d" % (m_name, long(self._current_value)))
                self.rate(m_name, long(self._current_value), tags=tags)
            elif self._current_type in ("i", "g"):
                self.gauge(m_name, long(self._current_value), tags=tags)
            else:
                # Unsupported data type, ignore
                self._reset()
                return # don't save

            # reset for next stat element
            self._reset()
        elif name in ("ident", "name") or (name == "type" and self._current_str != "MAIN"):
            self._current_metric += "." + self._current_str

    def _char_data(self, data):
        #self.log.debug("Data %s [%s]" % (data, self._current_element))
        data = data.strip()
        if len(data) > 0 and self._current_element != "":
            if self._current_element == "value":
                self._current_value = long(data)
            elif self._current_element == "flag":
                self._current_type = data
            else:
                self._current_str = data

    def check(self, instance):
        # Not configured? Not a problem.
        if instance.get("varnishstat", None) is None:
            raise Exception("varnishstat is not configured")
        tags = instance.get('tags', [])
        if tags is None:
            tags = []
        else:
            tags = list(set(tags))
        varnishstat_path = instance.get("varnishstat")
        name = instance.get('name')

        # Get version and version-specific args from varnishstat -V.
        version, use_xml = self._get_version_info(varnishstat_path)

        # Parse metrics from varnishstat.
        arg = '-x' if use_xml else '-1'
        cmd = [varnishstat_path, arg]

        if name is not None:
            cmd.extend(['-n', name])
            tags += [u'varnish_name:%s' % name]
        else:
            tags += [u'varnish_name:default']

        output, _, _ = get_subprocess_output(cmd, self.log)

        self._parse_varnishstat(output, use_xml, tags)

        # Parse service checks from varnishadm.
        varnishadm_path = instance.get('varnishadm')
        if varnishadm_path:
            # TODO: "debug.health" has been removed since varnish 4.1+. We
            # should check the version and use "backend.list -p" instead.
            secretfile_path = instance.get('secretfile', '/etc/varnish/secret')
            cmd = ['sudo', varnishadm_path, '-S', secretfile_path, 'debug.health']
            output, _, _ = get_subprocess_output(cmd, self.log)
            if output:
                self._parse_varnishadm(output)

    def _get_version_info(self, varnishstat_path):
        # Get the varnish version from varnishstat
        output, error, _ = get_subprocess_output([varnishstat_path, "-V"], self.log,
            raise_on_empty_output=False)

        # Assumptions regarding varnish's version
        use_xml = True
        version = 3

        m1 = re.search(r"varnish-(\d+)", output, re.MULTILINE)
        # v2 prints the version on stderr, v3 on stdout
        m2 = re.search(r"varnish-(\d+)", error, re.MULTILINE)

        if m1 is None and m2 is None:
            self.log.warn("Cannot determine the version of varnishstat, assuming 3 or greater")<commit_msg>[varnish] syncing check<commit_after># (C) Datadog, Inc. 2010-2016
# All rights reserved
# Licensed under Simplified BSD License (see LICENSE)

# stdlib
from collections import defaultdict
import re
import xml.parsers.expat # python 2.4 compatible

# project
from checks import AgentCheck
from utils.subprocess_output import get_subprocess_output


class BackendStatus(object):
    HEALTHY = 'healthy'
    SICK = 'sick'
    ALL = (HEALTHY, SICK)

    @classmethod
    def to_check_status(cls, status):
        if status == cls.HEALTHY:
            return AgentCheck.OK
        elif status == cls.SICK:
            return AgentCheck.CRITICAL
        return AgentCheck.UNKNOWN

class Varnish(AgentCheck):
    SERVICE_CHECK_NAME = 'varnish.backend_healthy'

    # XML parsing bits, a.k.a. Kafka in Code
    def _reset(self):
        self._current_element = ""
        self._current_metric = "varnish"
        self._current_value = 0
        self._current_str = ""
        self._current_type = ""

    def _start_element(self, name, attrs):
        self._current_element = name

    def _end_element(self, name, tags):
        if name == "stat":
            m_name = self.normalize(self._current_metric)
            if self._current_type in ("a", "c"):
                self.rate(m_name, long(self._current_value), tags=tags)
            elif self._current_type in ("i", "g"):
                self.gauge(m_name, long(self._current_value), tags=tags)
            else:
                # Unsupported data type, ignore
                self._reset()
                return # don't save

            # reset for next stat element
            self._reset()
        elif name in ("ident", "name") or (name == "type" and self._current_str != "MAIN"):
            self._current_metric += "." + self._current_str

    def _char_data(self, data):
        self.log.debug("Data %s [%s]" % (data, self._current_element))
        data = data.strip()
        if len(data) > 0 and self._current_element != "":
            if self._current_element == "value":
                self._current_value = long(data)
            elif self._current_element == "flag":
                self._current_type = data
            else:
                self._current_str = data

    def check(self, instance):
        # Not configured? Not a problem.
        if instance.get("varnishstat", None) is None:
            raise Exception("varnishstat is not configured")
        tags = instance.get('tags', [])
        if tags is None:
            tags = []
        else:
            tags = list(set(tags))
        varnishstat_path = instance.get("varnishstat")
        name = instance.get('name')

        # Get version and version-specific args from varnishstat -V.
        version, use_xml = self._get_version_info(varnishstat_path)

        # Parse metrics from varnishstat.
        arg = '-x' if use_xml else '-1'
        cmd = [varnishstat_path, arg]

        if name is not None:
            cmd.extend(['-n', name])
            tags += [u'varnish_name:%s' % name]
        else:
            tags += [u'varnish_name:default']

        output, _, _ = get_subprocess_output(cmd, self.log)

        self._parse_varnishstat(output, use_xml, tags)

        # Parse service checks from varnishadm.
        varnishadm_path = instance.get('varnishadm')
        if varnishadm_path:
            secretfile_path = instance.get('secretfile', '/etc/varnish/secret')
            cmd = ['sudo', varnishadm_path, '-S', secretfile_path, 'debug.health']
            output, _, _ = get_subprocess_output(cmd, self.log)
            if output:
                self._parse_varnishadm(output)

    def _get_version_info(self, varnishstat_path):
        # Get the varnish version from varnishstat
        output, error, _ = get_subprocess_output([varnishstat_path, "-V"], self.log,
            raise_on_empty_output=False)

        # Assumptions regarding varnish's version
        use_xml = True
        version = 3

        m1 = re.search(r"varnish-(\d+)", output, re.MULTILINE)
        # v2 prints the version on stderr, v3 on stdout
        m2 = re.search(r"varnish-(\d+)", error, re.MULTILINE)

        if m1 is None and m2 is None:
            self.log.warn("Cannot determine the version of varnishstat, assuming 3 or greater")
{'fraction_non_alphanumeric': 0.10671531182305324, 'fraction_numerical': 0.005016531752365751, 'mean_word_length': 2.2143642359838767, 'pattern_counts': {'":': 8, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1629162', 'n_tokens_mistral': 2723, 'n_tokens_neox': 2579, 'n_words': 675}