Пример #1
0
    def should_run(cls, confd_path):
        """
    Return a tuple (jmx_check_configured, java_bin_path)

    jmx_check_configured: boolean that shows that either one of the 
    check in JMX_CHECKS is enabled or there is a configured check 
    that have the "is_jmx" flag enabled in its init_config

    java_bin_path: is the path to the java executable. It was 
    previously set in the "instance" part of the yaml file of the
    jmx check. So we need to parse yaml files to get it.
    We assume that this value is alwayws the same for every jmx check
    so we can return the first value returned
    """

        jmx_check_configured = False
        java_bin_path = None

        for conf in glob.glob(os.path.join(confd_path, '*.yaml')):

            if jmx_check_configured and java_bin_path is not None:
                return (jmx_check_configured, java_bin_path)

            check_name = os.path.basename(conf).split('.')[0]

            if os.path.exists(conf):
                f = open(conf)
                try:
                    check_config = yaml.load(f.read(), Loader=yLoader)
                    assert check_config is not None
                    f.close()
                except Exception:
                    f.close()
                    log.error("Unable to parse yaml config in %s" % conf)
                    continue

                init_config = check_config.get('init_config', {})
                if init_config is None:
                    init_config = {}
                instances = check_config.get('instances', [])
                if instances is None:
                    instances = []

                if instances:
                    if type(instances) != list or len(instances) == 0:
                        continue

                    if java_bin_path is None:
                        if init_config and init_config.get('java_bin_path'):
                            # We get the java bin path from the yaml file for backward compatibility purposes
                            java_bin_path = check_config.get('init_config').get('java_bin_path')

                        for instance in instances:
                            if instance and instance.get('java_bin_path'):
                                java_bin_path = instance.get('java_bin_path')
                    
                    if init_config.get('is_jmx') or check_name in JMX_CHECKS:
                        jmx_check_configured = True

        return (jmx_check_configured, java_bin_path)
Пример #2
0
    def should_run(cls, confd_path):
        """
    Return a tuple (jmx_check_configured, java_bin_path)

    jmx_check_configured: boolean that shows that either one of the 
    check in JMX_CHECKS is enabled or there is a configured check 
    that have the "is_jmx" flag enabled in its init_config

    java_bin_path: is the path to the java executable. It was 
    previously set in the "instance" part of the yaml file of the
    jmx check. So we need to parse yaml files to get it.
    We assume that this value is alwayws the same for every jmx check
    so we can return the first value returned
    """

        jmx_check_configured = False
        java_bin_path = None

        for conf in glob.glob(os.path.join(confd_path, '*.yaml')):

            if jmx_check_configured and java_bin_path is not None:
                return (jmx_check_configured, java_bin_path)

            check_name = os.path.basename(conf).split('.')[0]

            if os.path.exists(conf):
                f = open(conf)
                try:
                    check_config = yaml.load(f.read(), Loader=yLoader)
                    assert check_config is not None
                    f.close()
                except Exception:
                    f.close()
                    log.error("Unable to parse yaml config in %s" % conf)
                    continue

                init_config = check_config.get('init_config', {})
                if init_config is None:
                    init_config = {}
                instances = check_config.get('instances', [])
                if instances is None:
                    instances = []

                if instances:
                    if type(instances) != list or len(instances) == 0:
                        continue

                    if java_bin_path is None:
                        if init_config and init_config.get('java_bin_path'):
                            # We get the java bin path from the yaml file for backward compatibility purposes
                            java_bin_path = check_config.get('init_config').get('java_bin_path')

                        for instance in instances:
                            if instance and instance.get('java_bin_path'):
                                java_bin_path = instance.get('java_bin_path')
                    
                    if init_config.get('is_jmx') or check_name in JMX_CHECKS:
                        jmx_check_configured = True

        return (jmx_check_configured, java_bin_path)
Пример #3
0
def check_yaml(conf_path):
    f = open(conf_path)
    check_name = os.path.basename(conf_path).split('.')[0]
    try:
        check_config = yaml.load(f.read(), Loader=yLoader)
        assert 'init_config' in check_config, "No 'init_config' section found"
        assert 'instances' in check_config, "No 'instances' section found"

        valid_instances = True
        if check_config['instances'] is None or not isinstance(
                check_config['instances'], list):
            valid_instances = False
        else:
            for i in check_config['instances']:
                if not isinstance(i, dict):
                    valid_instances = False
                    break
        if not valid_instances:
            raise Exception(
                'You need to have at least one instance defined in the YAML file for this check'
            )
        else:
            return check_config
    finally:
        f.close()
Пример #4
0
def get_jmx_status():
    """This function tries to read the jmxfetch status file which is a yaml file
    located in the same directory as the jmxfetch jar file.
    Its format is as the following:
    
    ###

    timestamp: 1377303057441
    instances:
          cassandra_localhost: {message: null, metric_count: 40}
          tomcat: {message: null, metric_count: 57}
          instance_name: {message: 'Cannot connect to instance localhost:3033. Is a JMX Server running at this address?', metric_count: 0}

    ###
    """
    check_statuses = []
    path = os.path.join(tempfile.gettempdir(), "jmx_status.yaml")
    if not os.path.exists(path):
        log.debug("There is no jmx_status file at: %s" % path)
        return []

    try:
        jmx_stats = yaml.load(file(path))

        status_age = time.time() - jmx_stats.get('timestamp')/1000 # JMX timestamp is saved in milliseconds
        jmx_instances = jmx_stats.get('instances', {})

        if status_age > 60:
            check_statuses.append(CheckStatus("jmx", [InstanceStatus(
                                                0, 
                                                STATUS_ERROR, 
                                                error="JMXfetch didn't return any metrics during the last minute"
                                                )], 0, 0))
            return check_statuses

        for instance, info in jmx_instances.iteritems():
            message = info.get('message', None)
            metric_count = info.get('metric_count', 0)
            status = info.get('status')

            if status == STATUS_ERROR:
                instance_status = InstanceStatus(0, STATUS_ERROR, error=message)

            elif status == STATUS_WARNING:
                instance_status = InstanceStatus(0, STATUS_WARNING, warnings=[message])

            elif status == STATUS_OK:
                instance_status = InstanceStatus(0, STATUS_OK)

            check_status = CheckStatus(instance, [instance_status], metric_count, 0)
            check_statuses.append(check_status)

        return check_statuses

    except Exception, e:
        log.exception("Couldn't load latest jmx status")
        return []
Пример #5
0
    def should_run(cls, confd_path, checks_list):
        """
    Return a tuple (jmx_checks, invalid_checks, java_bin_path, java_options)

    jmx_checks: list of yaml files that are jmx checks 
    (they have the is_jmx flag enabled or they are in JMX_CHECKS)
    and that have at least one instance configured

    invalid_checks: dictionary whose keys are check names that are JMX checks but
    they have a bad configuration. Values of the dictionary are exceptions generated 
    when checking the configuration

    java_bin_path: is the path to the java executable. It was 
    previously set in the "instance" part of the yaml file of the
    jmx check. So we need to parse yaml files to get it.
    We assume that this value is alwayws the same for every jmx check
    so we can return the first value returned

    java_options: is string contains options that will be passed to java_bin_path
    We assume that this value is alwayws the same for every jmx check
    so we can return the first value returned
    """

        jmx_checks = []
        java_bin_path = None
        java_options = None
        invalid_checks = {}

        for conf in glob.glob(os.path.join(confd_path, '*.yaml')):

            java_bin_path_is_set = java_bin_path is not None
            java_options_is_set = java_options is not None
            filename = os.path.basename(conf)
            check_name = filename.split('.')[0]

            if os.path.exists(conf):
                f = open(conf)
                try:
                    check_config = yaml.load(f.read(), Loader=yLoader)
                    assert check_config is not None
                    f.close()
                except Exception:
                    f.close()
                    log.error("Unable to parse yaml config in %s" % conf)
                    continue

                try:
                    is_jmx, check_java_bin_path, check_java_options = JMXFetch.is_jmx_check(check_config, check_name, checks_list)
                    if is_jmx:
                        jmx_checks.append(filename)
                        if java_bin_path is None and check_java_bin_path is not None:
                            java_bin_path = check_java_bin_path
                        if java_options is None and check_java_options is not None:
                            java_options = check_java_options
                except InvalidJMXConfiguration, e:
                    log.error("%s check is not a valid jmx configuration: %s" % (check_name, e))
                    invalid_checks[check_name] = e
Пример #6
0
    def should_run(cls, confd_path, checks_list):
        """
    Return a tuple (jmx_checks, invalid_checks, java_bin_path, java_options)

    jmx_checks: list of yaml files that are jmx checks
    (they have the is_jmx flag enabled or they are in JMX_CHECKS)
    and that have at least one instance configured

    invalid_checks: dictionary whose keys are check names that are JMX checks but
    they have a bad configuration. Values of the dictionary are exceptions generated
    when checking the configuration

    java_bin_path: is the path to the java executable. It was
    previously set in the "instance" part of the yaml file of the
    jmx check. So we need to parse yaml files to get it.
    We assume that this value is alwayws the same for every jmx check
    so we can return the first value returned

    java_options: is string contains options that will be passed to java_bin_path
    We assume that this value is alwayws the same for every jmx check
    so we can return the first value returned
    """

        jmx_checks = []
        java_bin_path = None
        java_options = None
        invalid_checks = {}

        for conf in glob.glob(os.path.join(confd_path, '*.yaml')):
            filename = os.path.basename(conf)
            check_name = filename.split('.')[0]

            if os.path.exists(conf):
                f = open(conf)
                try:
                    check_config = yaml.load(f.read(), Loader=yLoader)
                    assert check_config is not None
                    f.close()
                except Exception:
                    f.close()
                    log.error("Unable to parse yaml config in %s" % conf)
                    continue

                try:
                    is_jmx, check_java_bin_path, check_java_options = JMXFetch.is_jmx_check(
                        check_config, check_name, checks_list)
                    if is_jmx:
                        jmx_checks.append(filename)
                        if java_bin_path is None and check_java_bin_path is not None:
                            java_bin_path = check_java_bin_path
                        if java_options is None and check_java_options is not None:
                            java_options = check_java_options
                except InvalidJMXConfiguration, e:
                    log.error("%s check is not a valid jmx configuration: %s" %
                              (check_name, e))
                    invalid_checks[check_name] = e
Пример #7
0
    def from_yaml(cls, path_to_yaml=None, agentConfig=None, yaml_text=None, check_name=None):
        """
        A method used for testing your check without running the agent.
        """
        from util import yaml, yLoader
        if path_to_yaml:
            check_name = os.path.basename(path_to_yaml).split('.')[0]
            try:
                f = open(path_to_yaml)
            except IOError:
                raise Exception('Unable to open yaml config: %s' % path_to_yaml)
            yaml_text = f.read()
            f.close()

        config = yaml.load(yaml_text, Loader=yLoader)
        check = cls(check_name, config.get('init_config') or {}, agentConfig or {})

        return check, config.get('instances', [])
Пример #8
0
def check_yaml(conf_path):
    f = open(conf_path)
    try:
        check_config = yaml.load(f.read(), Loader=yLoader)
        assert 'init_config' in check_config, "No 'init_config' section found"
        assert 'instances' in check_config, "No 'instances' section found"

        valid_instances = True
        if check_config['instances'] is None or not isinstance(check_config['instances'], list):
            valid_instances = False
        else:
            for i in check_config['instances']:
                if not isinstance(i, dict):
                    valid_instances = False
                    break
        if not valid_instances:
            raise Exception('You need to have at least one instance defined in the YAML file for this check')
        else:
            return check_config
    finally:
        f.close()
Пример #9
0
    def from_yaml(cls,
                  path_to_yaml=None,
                  agentConfig=None,
                  yaml_text=None,
                  check_name=None):
        """
        A method used for testing your check without running the agent.
        """
        from util import yaml, yLoader
        if path_to_yaml:
            check_name = os.path.basename(path_to_yaml).split('.')[0]
            try:
                f = open(path_to_yaml)
            except IOError:
                raise Exception('Unable to open yaml config: %s' %
                                path_to_yaml)
            yaml_text = f.read()
            f.close()

        config = yaml.load(yaml_text, Loader=yLoader)
        check = cls(check_name,
                    config.get('init_config') or {}, agentConfig or {})

        return check, config.get('instances', [])
Пример #10
0
def load_check_directory(agentConfig):
    ''' Return the checks from checks.d. Only checks that have a configuration
    file in conf.d will be returned. '''
    from util import yaml, yLoader
    from checks import AgentCheck

    checks = []

    log = logging.getLogger('checks')
    osname = getOS()
    checks_path = get_checksd_path(osname)
    confd_path = get_confd_path(osname)
    check_glob = os.path.join(checks_path, '*.py')

    # Update the python path before the import
    sys.path.append(checks_path)

    # For backwards-compatability with old style checks, we have to load every
    # checks.d module and check for a corresponding config OR check if the old
    # config will "activate" the check.
    #
    # Once old-style checks aren't supported, we'll just read the configs and
    # import the corresponding check module
    for check in glob.glob(check_glob):
        check_name = os.path.basename(check).split('.')[0]
        try:
            check_module = __import__(check_name)
        except:
            log.exception('Unable to import check module %s.py from checks.d' % check_name)
            continue

        check_class = None
        classes = inspect.getmembers(check_module, inspect.isclass)
        for name, clsmember in classes:
            if clsmember == AgentCheck:
                continue
            if issubclass(clsmember, AgentCheck):
                check_class = clsmember
                if AgentCheck in clsmember.__bases__:
                    continue
                else:
                    break

        if not check_class:
            log.error('No check class (inheriting from AgentCheck) found in %s.py' % check_name)
            continue

        # Check if the config exists OR we match the old-style config
        conf_path = os.path.join(confd_path, '%s.yaml' % check_name)
        if os.path.exists(conf_path):
            f = open(conf_path)
            try:
                check_config = yaml.load(f.read(), Loader=yLoader)
                assert check_config is not None
                f.close()
            except:
                f.close()
                log.exception("Unable to parse yaml config in %s" % conf_path)
                continue
        elif hasattr(check_class, 'parse_agent_config'):
            # FIXME: Remove this check once all old-style checks are gone
            check_config = check_class.parse_agent_config(agentConfig)
            if not check_config:
                continue
        else:
            log.debug('No conf.d/%s.yaml found for checks.d/%s.py' % (check_name, check_name))
            continue

        # Look for the per-check config, which *must* exist
        if not check_config.get('instances'):
            log.error("Config %s is missing 'instances'" % conf_path)
            continue

        # Accept instances as a list, as a single dict, or as non-existant
        instances = check_config.get('instances', {})
        if type(instances) != type([]):
            instances = [instances]

        # Init all of the check's classes with
        init_config = check_config.get('init_config', {})
        # init_config: in the configuration triggers init_config to be defined
        # to None.
        if init_config is None:
            init_config = {}

        init_config['instances_number'] = len(instances)
        check_class = check_class(check_name, init_config=init_config,
            agentConfig=agentConfig)

        # Add custom pythonpath(s) if available
        if 'pythonpath' in check_config:
            pythonpath = check_config['pythonpath']
            if not isinstance(pythonpath, list):
                pythonpath = [pythonpath]
            sys.path.extend(pythonpath)

        log.debug('Loaded check.d/%s.py' % check_name)
        checks.append({
            'name': check_name,
            'instances': check_config['instances'],
            'class': check_class
        })

    log.info('checks.d checks: %s' % [c['name'] for c in checks])
    return checks
Пример #11
0
                check_class = clsmember
                if AgentCheck in clsmember.__bases__:
                    continue
                else:
                    break

        if not check_class:
            log.error('No check class (inheriting from AgentCheck) found in %s.py' % check_name)
            continue

        # Check if the config exists OR we match the old-style config
        conf_path = os.path.join(confd_path, '%s.yaml' % check_name)
        if os.path.exists(conf_path):
            f = open(conf_path)
            try:
                check_config = yaml.load(f.read(), Loader=yLoader)
                assert check_config is not None
                f.close()
            except Exception:
                f.close()
                log.exception("Unable to parse yaml config in %s" % conf_path)
                continue
        elif hasattr(check_class, 'parse_agent_config'):
            # FIXME: Remove this check once all old-style checks are gone
            try:
                check_config = check_class.parse_agent_config(agentConfig)
            except Exception, e:
                continue
            if not check_config:
                continue
            d = [
Пример #12
0
def get_jmx_status():
    """This function tries to read the jmxfetch status file which is a yaml file
    located in the same directory as the jmxfetch jar file.
    Its format is as the following:
    
    ###

    timestamp: 1377303057441
    instances:
          cassandra_localhost: {message: null, metric_count: 40}
          tomcat: {message: null, metric_count: 57}
          instance_name: {message: 'Cannot connect to instance localhost:3033. Is a JMX Server running at this address?', metric_count: 0}

    ###
    """
    check_statuses = []
    path = os.path.join(tempfile.gettempdir(), "jmx_status.yaml")
    if not os.path.exists(path):
        log.debug("There is no jmx_status file at: %s" % path)
        return []

    try:
        jmx_stats = yaml.load(file(path))

        status_age = time.time() - jmx_stats.get(
            'timestamp') / 1000  # JMX timestamp is saved in milliseconds
        jmx_instances = jmx_stats.get('instances', {})

        if status_age > 60:
            check_statuses.append(
                CheckStatus("jmx", [
                    InstanceStatus(
                        0,
                        STATUS_ERROR,
                        error=
                        "JMXfetch didn't return any metrics during the last minute"
                    )
                ], 0, 0))
            return check_statuses

        for instance, info in jmx_instances.iteritems():
            message = info.get('message', None)
            metric_count = info.get('metric_count', 0)
            status = info.get('status')

            if status == STATUS_ERROR:
                instance_status = InstanceStatus(0,
                                                 STATUS_ERROR,
                                                 error=message)

            elif status == STATUS_WARNING:
                instance_status = InstanceStatus(0,
                                                 STATUS_WARNING,
                                                 warnings=[message])

            elif status == STATUS_OK:
                instance_status = InstanceStatus(0, STATUS_OK)

            check_status = CheckStatus(instance, [instance_status],
                                       metric_count, 0)
            check_statuses.append(check_status)

        return check_statuses

    except Exception, e:
        log.exception("Couldn't load latest jmx status")
        return []
Пример #13
0
def load_check_directory(agentConfig):
    ''' Return the initialized checks from checks.d, and a mapping of checks that failed to
    initialize. Only checks that have a configuration
    file in conf.d will be returned. '''
    from util import yaml, yLoader
    from checks import AgentCheck

    initialized_checks = {}
    init_failed_checks = {}

    osname = get_os()
    checks_paths = (glob.glob(os.path.join(path, '*.py')) for path
                    in [agentConfig['additional_checksd'], get_checksd_path(osname)])
    confd_path = get_confd_path(osname)

    # For backwards-compatability with old style checks, we have to load every
    # checks.d module and check for a corresponding config OR check if the old
    # config will "activate" the check.
    #
    # Once old-style checks aren't supported, we'll just read the configs and
    # import the corresponding check module
    for check in itertools.chain(*checks_paths):
        check_name = os.path.basename(check).split('.')[0]
        if check_name in initialized_checks or check_name in init_failed_checks:
            log.debug('Skipping check %s because it has already been loaded from another location', check)
            continue
        try:
            check_module = imp.load_source('checksd_%s' % check_name, check)
        except Exception, e:
            traceback_message = traceback.format_exc()
            init_failed_checks[check_name] = {'error':e, 'traceback':traceback_message}
            log.exception('Unable to import check module %s.py from checks.d' % check_name)
            continue

        check_class = None
        classes = inspect.getmembers(check_module, inspect.isclass)
        for _, clsmember in classes:
            if clsmember == AgentCheck:
                continue
            if issubclass(clsmember, AgentCheck):
                check_class = clsmember
                if AgentCheck in clsmember.__bases__:
                    continue
                else:
                    break

        if not check_class:
            log.error('No check class (inheriting from AgentCheck) found in %s.py' % check_name)
            continue

        # Check if the config exists OR we match the old-style config
        conf_path = os.path.join(confd_path, '%s.yaml' % check_name)
        if os.path.exists(conf_path):
            f = open(conf_path)
            try:
                check_config = yaml.load(f.read(), Loader=yLoader)
                assert check_config is not None
                f.close()
            except:
                f.close()
                log.exception("Unable to parse yaml config in %s" % conf_path)
                continue
        elif hasattr(check_class, 'parse_agent_config'):
            # FIXME: Remove this check once all old-style checks are gone
            try:
                check_config = check_class.parse_agent_config(agentConfig)
            except Exception, e:
                continue
            if not check_config:
                continue
            d = [
                "Configuring %s in datadog.conf is deprecated." % (check_name),
                "Please use conf.d. In a future release, support for the",
                "old style of configuration will be dropped.",
            ]
            log.warn(" ".join(d))
Пример #14
0
def load_check_directory(agentConfig):
    ''' Return the checks from checks.d. Only checks that have a configuration
    file in conf.d will be returned. '''
    from util import yaml, yLoader
    from checks import AgentCheck

    checks = []

    log = logging.getLogger('checks')
    osname = getOS()
    checks_path = get_checksd_path(osname)
    confd_path = get_confd_path(osname)
    check_glob = os.path.join(checks_path, '*.py')

    # Update the python path before the import
    sys.path.append(checks_path)

    # For backwards-compatability with old style checks, we have to load every
    # checks.d module and check for a corresponding config OR check if the old
    # config will "activate" the check.
    #
    # Once old-style checks aren't supported, we'll just read the configs and
    # import the corresponding check module
    for check in glob.glob(check_glob):
        check_name = os.path.basename(check).split('.')[0]
        try:
            check_module = __import__(check_name)
        except:
            log.exception('Unable to import check module %s.py from checks.d' %
                          check_name)
            continue

        check_class = None
        classes = inspect.getmembers(check_module, inspect.isclass)
        for name, clsmember in classes:
            if clsmember == AgentCheck:
                continue
            if issubclass(clsmember, AgentCheck):
                check_class = clsmember
                if AgentCheck in clsmember.__bases__:
                    continue
                else:
                    break

        if not check_class:
            log.error(
                'No check class (inheriting from AgentCheck) found in %s.py' %
                check_name)
            continue

        # Check if the config exists OR we match the old-style config
        conf_path = os.path.join(confd_path, '%s.yaml' % check_name)
        if os.path.exists(conf_path):
            f = open(conf_path)
            try:
                check_config = yaml.load(f.read(), Loader=yLoader)
                assert check_config is not None
                f.close()
            except:
                f.close()
                log.exception("Unable to parse yaml config in %s" % conf_path)
                continue
        elif hasattr(check_class, 'parse_agent_config'):
            # FIXME: Remove this check once all old-style checks are gone
            check_config = check_class.parse_agent_config(agentConfig)
            if not check_config:
                continue
        else:
            log.debug('No conf.d/%s.yaml found for checks.d/%s.py' %
                      (check_name, check_name))
            continue

        # Look for the per-check config, which *must* exist
        if not check_config.get('instances'):
            log.error("Config %s is missing 'instances'" % conf_path)
            continue

        # Accept instances as a list, as a single dict, or as non-existant
        instances = check_config.get('instances', {})
        if type(instances) != type([]):
            instances = [instances]

        # Init all of the check's classes with
        init_config = check_config.get('init_config', {})
        # init_config: in the configuration triggers init_config to be defined
        # to None.
        if init_config is None:
            init_config = {}

        init_config['instances_number'] = len(instances)
        check_class = check_class(check_name,
                                  init_config=init_config,
                                  agentConfig=agentConfig)

        # Add custom pythonpath(s) if available
        if 'pythonpath' in check_config:
            pythonpath = check_config['pythonpath']
            if not isinstance(pythonpath, list):
                pythonpath = [pythonpath]
            sys.path.extend(pythonpath)

        log.debug('Loaded check.d/%s.py' % check_name)
        checks.append({
            'name': check_name,
            'instances': check_config['instances'],
            'class': check_class
        })

    log.info('checks.d checks: %s' % [c['name'] for c in checks])
    return checks
Пример #15
0
def check_yaml_syntax(content):
    try:
        yaml.load(content, Loader=yLoader)
    except Exception, e:
        warning_popup("Unable to parse yaml: \n %s" % str(e))
        raise
Пример #16
0
def check_yaml_syntax(content):
    try:
        yaml.load(content, Loader=yLoader)
    except Exception, e:
        warning_popup("Unable to parse yaml: \n %s" % str(e))
        raise
Пример #17
0
def get_jmx_status():
    """This function tries to read the 2 jmxfetch status file which are yaml file
    located in the temp directory.

    There are 2 files:
        - One generated by the Agent itself, for jmx checks that can't be initialized because
        there are missing stuff.
        Its format is as following:

        ###
        invalid_checks:
              jmx: !!python/object/apply:jmxfetch.InvalidJMXConfiguration [You need to have at
                              least one instance defined in the YAML file for this check]
        timestamp: 1391040927.136523
        ###

        - One generated by jmxfetch that return information about the collection of metrics
        its format is as following:

        ###
        timestamp: 1391037347435
        checks:
          failed_checks:
            jmx:
            - {message: Unable to create instance. Please check your yaml file, status: ERROR}
          initialized_checks:
            tomcat:
            - {message: null, status: OK, metric_count: 7, instance_name: jmx-remihakim.fr-3000}
        ###
    """
    check_statuses = []
    java_status_path = os.path.join(tempfile.gettempdir(), "jmx_status.yaml")
    python_status_path = os.path.join(tempfile.gettempdir(), "jmx_status_python.yaml")
    if not os.path.exists(java_status_path) and not os.path.exists(python_status_path):
        log.debug("There is no jmx_status file at: %s or at: %s" % (java_status_path, python_status_path))
        return []

    check_data = defaultdict(lambda: defaultdict(list))
    try:
        if os.path.exists(java_status_path):
            java_jmx_stats = yaml.load(file(java_status_path))

            status_age = time.time() - java_jmx_stats.get('timestamp')/1000 # JMX timestamp is saved in milliseconds
            jmx_checks = java_jmx_stats.get('checks', {})

            if status_age > 60:
                check_statuses.append(CheckStatus("jmx", [InstanceStatus(
                                                    0,
                                                    STATUS_ERROR,
                                                    error="JMXfetch didn't return any metrics during the last minute"
                                                    )]))
            else:

                for check_name, instances in jmx_checks.get('failed_checks', {}).iteritems():
                    for info in instances:
                        message = info.get('message', None)
                        metric_count = info.get('metric_count', 0)
                        status = info.get('status')
                        instance_name = info.get('instance_name', None)
                        check_data[check_name]['statuses'].append(get_jmx_instance_status(instance_name, status, message, metric_count))
                        check_data[check_name]['metric_count'].append(metric_count)

                for check_name, instances in jmx_checks.get('initialized_checks', {}).iteritems():
                    for info in instances:
                        message = info.get('message', None)
                        metric_count = info.get('metric_count', 0)
                        status = info.get('status')
                        instance_name = info.get('instance_name', None)
                        check_data[check_name]['statuses'].append(get_jmx_instance_status(instance_name, status, message, metric_count))
                        check_data[check_name]['metric_count'].append(metric_count)

                for check_name, data in check_data.iteritems():
                    check_status = CheckStatus(check_name, data['statuses'], sum(data['metric_count']))
                    check_statuses.append(check_status)

        if os.path.exists(python_status_path):
            python_jmx_stats = yaml.load(file(python_status_path))
            jmx_checks = python_jmx_stats.get('invalid_checks', {})
            for check_name, excep in jmx_checks.iteritems():
                check_statuses.append(CheckStatus(check_name, [], init_failed_error=excep))


        return check_statuses

    except Exception:
        log.exception("Couldn't load latest jmx status")
        return []
Пример #18
0
def load_check_directory(agentConfig):
    ''' Return the checks from checks.d. Only checks that have a configuration
    file in conf.d will be returned. '''
    from util import yaml, yLoader
    from checks import AgentCheck

    checks = []

    osname = getOS()
    checks_path = get_checksd_path(osname)
    confd_path = get_confd_path(osname)
    check_glob = os.path.join(checks_path, '*.py')

    # Update the python path before the import
    sys.path.append(checks_path)

    # For backwards-compatability with old style checks, we have to load every
    # checks.d module and check for a corresponding config OR check if the old
    # config will "activate" the check.
    #
    # Once old-style checks aren't supported, we'll just read the configs and
    # import the corresponding check module
    for check in glob.glob(check_glob):
        check_name = os.path.basename(check).split('.')[0]
        try:
            check_module = __import__(check_name)
        except:
            log.exception('Unable to import check module %s.py from checks.d' % check_name)
            continue

        check_class = None
        classes = inspect.getmembers(check_module, inspect.isclass)
        for name, clsmember in classes:
            if clsmember == AgentCheck:
                continue
            if issubclass(clsmember, AgentCheck):
                check_class = clsmember
                if AgentCheck in clsmember.__bases__:
                    continue
                else:
                    break

        if not check_class:
            log.error('No check class (inheriting from AgentCheck) found in %s.py' % check_name)
            continue

        # Check if the config exists OR we match the old-style config
        conf_path = os.path.join(confd_path, '%s.yaml' % check_name)
        if os.path.exists(conf_path):
            f = open(conf_path)
            try:
                check_config = yaml.load(f.read(), Loader=yLoader)
                assert check_config is not None
                f.close()
            except:
                f.close()
                log.exception("Unable to parse yaml config in %s" % conf_path)
                continue
        elif hasattr(check_class, 'parse_agent_config'):
            # FIXME: Remove this check once all old-style checks are gone
            try:
                check_config = check_class.parse_agent_config(agentConfig)
            except Exception, e:
                continue
            if not check_config:
                continue
            d = [
                "Configuring %s in datadog.conf is deprecated." % (check_name),
                "Please use conf.d. In a future release, support for the",
                "old style of configuration will be dropped.",
            ]
            log.warn(" ".join(d))

        else:
            log.debug('No conf.d/%s.yaml found for checks.d/%s.py' % (check_name, check_name))
            continue

        # Look for the per-check config, which *must* exist
        if not check_config.get('instances'):
            log.error("Config %s is missing 'instances'" % conf_path)
            continue

        # Accept instances as a list, as a single dict, or as non-existant
        instances = check_config.get('instances', {})
        if type(instances) != type([]):
            instances = [instances]

        # Init all of the check's classes with
        init_config = check_config.get('init_config', {})
        # init_config: in the configuration triggers init_config to be defined
        # to None.
        if init_config is None:
            init_config = {}


        instances = check_config['instances']
        try:
            c = check_class(check_name, init_config=init_config,
                            agentConfig=agentConfig, instances=instances)
        except TypeError, e:
            # Backwards compatibility for checks which don't support the
            # instances argument in the constructor.
            c = check_class(check_name, init_config=init_config,
                            agentConfig=agentConfig)
            c.instances = instances
Пример #19
0
def get_jmx_status():
    """This function tries to read the 2 jmxfetch status file which are yaml file
    located in the temp directory.

    There are 2 files:
        - One generated by the Agent itself, for jmx checks that can't be initialized because
        there are missing stuff.
        Its format is as following:

        ###
        invalid_checks:
              jmx: !!python/object/apply:jmxfetch.InvalidJMXConfiguration [You need to have at
                              least one instance defined in the YAML file for this check]
        timestamp: 1391040927.136523
        ###

        - One generated by jmxfetch that return information about the collection of metrics
        its format is as following:
    
        ###
        timestamp: 1391037347435
        checks:
          failed_checks:
            jmx:
            - {message: Unable to create instance. Please check your yaml file, status: ERROR}
          initialized_checks:
            tomcat:
            - {message: null, status: OK, metric_count: 7, instance_name: jmx-remihakim.fr-3000}
        ###
    """
    check_statuses = []
    java_status_path = os.path.join(tempfile.gettempdir(), "jmx_status.yaml")
    python_status_path = os.path.join(tempfile.gettempdir(), "jmx_status_python.yaml")
    if not os.path.exists(java_status_path) and not os.path.exists(python_status_path):
        log.debug("There is no jmx_status file at: %s or at: %s" % (java_status_path, python_status_path))
        return []

    check_data = defaultdict(lambda: defaultdict(list))
    try:
        if os.path.exists(java_status_path):
            java_jmx_stats = yaml.load(file(java_status_path))

            status_age = time.time() - java_jmx_stats.get('timestamp')/1000 # JMX timestamp is saved in milliseconds
            jmx_checks = java_jmx_stats.get('checks', {})

            if status_age > 60:
                check_statuses.append(CheckStatus("jmx", [InstanceStatus(
                                                    0, 
                                                    STATUS_ERROR, 
                                                    error="JMXfetch didn't return any metrics during the last minute"
                                                    )], 0, 0))
            else:

                for check_name, instances in jmx_checks.get('failed_checks', {}).iteritems():
                    for info in instances:
                        message = info.get('message', None)
                        metric_count = info.get('metric_count', 0)
                        status = info.get('status')
                        instance_name = info.get('instance_name', None)
                        check_data[check_name]['statuses'].append(get_jmx_instance_status(instance_name, status, message, metric_count))
                        check_data[check_name]['metric_count'].append(metric_count)
               
                for check_name, instances in jmx_checks.get('initialized_checks', {}).iteritems():
                    for info in instances:
                        message = info.get('message', None)
                        metric_count = info.get('metric_count', 0)
                        status = info.get('status')
                        instance_name = info.get('instance_name', None)
                        check_data[check_name]['statuses'].append(get_jmx_instance_status(instance_name, status, message, metric_count))
                        check_data[check_name]['metric_count'].append(metric_count)

                for check_name, data in check_data.iteritems():
                    check_status = CheckStatus(check_name, data['statuses'], sum(data['metric_count']), 0)
                    check_statuses.append(check_status)

        if os.path.exists(python_status_path):
            python_jmx_stats = yaml.load(file(python_status_path))
            jmx_checks = python_jmx_stats.get('invalid_checks', {})
            for check_name, excep in jmx_checks.iteritems():
                check_statuses.append(CheckStatus(check_name, [], 0, 0, init_failed_error=excep))


        return check_statuses

    except Exception, e:
        log.exception("Couldn't load latest jmx status")
        return []
Пример #20
0
def load_check_directory(agentConfig):
    ''' Return the initialized checks from checks.d, and a mapping of checks that failed to
    initialize. Only checks that have a configuration
    file in conf.d will be returned. '''
    from util import yaml, yLoader
    from checks import AgentCheck

    initialized_checks = {}
    init_failed_checks = {}

    osname = get_os()
    checks_paths = (
        glob.glob(os.path.join(path, '*.py')) for path in
        [agentConfig['additional_checksd'],
         get_checksd_path(osname)])
    confd_path = get_confd_path(osname)

    # For backwards-compatability with old style checks, we have to load every
    # checks.d module and check for a corresponding config OR check if the old
    # config will "activate" the check.
    #
    # Once old-style checks aren't supported, we'll just read the configs and
    # import the corresponding check module
    for check in itertools.chain(*checks_paths):
        check_name = os.path.basename(check).split('.')[0]
        if check_name in initialized_checks or check_name in init_failed_checks:
            log.debug(
                'Skipping check %s because it has already been loaded from another location',
                check)
            continue
        try:
            check_module = imp.load_source('checksd_%s' % check_name, check)
        except Exception, e:
            traceback_message = traceback.format_exc()
            init_failed_checks[check_name] = {
                'error': e,
                'traceback': traceback_message
            }
            log.exception('Unable to import check module %s.py from checks.d' %
                          check_name)
            continue

        check_class = None
        classes = inspect.getmembers(check_module, inspect.isclass)
        for name, clsmember in classes:
            if clsmember == AgentCheck:
                continue
            if issubclass(clsmember, AgentCheck):
                check_class = clsmember
                if AgentCheck in clsmember.__bases__:
                    continue
                else:
                    break

        if not check_class:
            log.error(
                'No check class (inheriting from AgentCheck) found in %s.py' %
                check_name)
            continue

        # Check if the config exists OR we match the old-style config
        conf_path = os.path.join(confd_path, '%s.yaml' % check_name)
        if os.path.exists(conf_path):
            f = open(conf_path)
            try:
                check_config = yaml.load(f.read(), Loader=yLoader)
                assert check_config is not None
                f.close()
            except:
                f.close()
                log.exception("Unable to parse yaml config in %s" % conf_path)
                continue
        elif hasattr(check_class, 'parse_agent_config'):
            # FIXME: Remove this check once all old-style checks are gone
            try:
                check_config = check_class.parse_agent_config(agentConfig)
            except Exception, e:
                continue
            if not check_config:
                continue
            d = [
                "Configuring %s in datadog.conf is deprecated." % (check_name),
                "Please use conf.d. In a future release, support for the",
                "old style of configuration will be dropped.",
            ]
            log.warn(" ".join(d))
Пример #21
0
    def should_run(cls, confd_path):
        """
    Return a tuple (jmx_checks, java_bin_path)

    jmx_checks: list of yaml files that are jmx checks 
    (they have the is_jmx flag enabled or they are in JMX_CHECKS)
    and that have at least one instance configured

    java_bin_path: is the path to the java executable. It was 
    previously set in the "instance" part of the yaml file of the
    jmx check. So we need to parse yaml files to get it.
    We assume that this value is alwayws the same for every jmx check
    so we can return the first value returned

    java_options: is string contains options that will be passed to java_bin_path
    We assume that this value is alwayws the same for every jmx check
    so we can return the first value returned
    """

        jmx_checks = []
        java_bin_path = None
        java_options = None

        for conf in glob.glob(os.path.join(confd_path, '*.yaml')):

            java_bin_path_is_set = java_bin_path is not None
            java_options_is_set = java_options is not None

            check_name = os.path.basename(conf).split('.')[0]

            if os.path.exists(conf):
                f = open(conf)
                try:
                    check_config = yaml.load(f.read(), Loader=yLoader)
                    assert check_config is not None
                    f.close()
                except Exception:
                    f.close()
                    log.error("Unable to parse yaml config in %s" % conf)
                    continue

                init_config = check_config.get('init_config', {})
                if init_config is None:
                    init_config = {}
                instances = check_config.get('instances', [])
                if instances is None:
                    instances = []

                if instances:
                    if type(instances) != list or len(instances) == 0:
                        continue

                    if java_bin_path is None:
                        if init_config and init_config.get('java_bin_path'):
                            # We get the java bin path from the yaml file for backward compatibility purposes
                            java_bin_path = init_config.get('java_bin_path')

                        else:
                            for instance in instances:
                                if instance and instance.get('java_bin_path'):
                                    java_bin_path = instance.get('java_bin_path')

                    if java_options is None:
                        if init_config and init_config.get('java_options'):
                            java_options = init_config.get('java_options')
                        else:
                            for instance in instances:
                                if instance and instance.get('java_options'):
                                    java_options = instance.get('java_options')

                    if init_config.get('is_jmx') or check_name in JMX_CHECKS:
                        jmx_checks.append(os.path.basename(conf))

        return (jmx_checks, java_bin_path, java_options)