设为首页 收藏本站
查看: 3986|回复: 0

[经验分享] zabbix优化之LLD Filter Multi-macro

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-8-6 08:56:27 | 显示全部楼层 |阅读模式
提出问题:
    zabbix对文件系统的监控是通过LLD实现的,zabbix首先通过Discovery rule发现所有的文件系统名称和类型,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
shell# zabbix_get -s 127.0.0.1 -k vfs.fs.discovery
{
       "data":[
              {
                     "{#FSNAME}":"/",
                     "{#FSTYPE}":"rootfs"
              },
              {
                     "{#FSNAME}":"/proc",
                     "{#FSTYPE}":"proc"
              },
              {
                     "{#FSNAME}":"/sys",
                     "{#FSTYPE}":"sysfs"
              },
              {
                     "{#FSNAME}":"/dev",
                     "{#FSTYPE}":"devtmpfs"
              },
              {
                     "{#FSNAME}":"/dev/pts",
                     "{#FSTYPE}":"devpts"
              },
              {
                     "{#FSNAME}":"/dev/shm",
                     "{#FSTYPE}":"tmpfs"
              },
              {
                     "{#FSNAME}":"/",
                     "{#FSTYPE}":"ext4"
              },
              {
                     "{#FSNAME}":"/proc/bus/usb",
                     "{#FSTYPE}":"usbfs"
              },
              {
                     "{#FSNAME}":"/boot",
                     "{#FSTYPE}":"ext4"
              },
              {
                     "{#FSNAME}":"/data",
                     "{#FSTYPE}":"ext4"
              },
              {
                     "{#FSNAME}":"/proc/sys/fs/binfmt_misc",
                     "{#FSTYPE}":"binfmt_misc"
              }
       ]
}



    然后通过在Discovery rule中配置的宏过滤规则(Filter Macro),把不需要监控的文件系统类型过滤掉,见下图。
wKiom1PgmASiAQ60AAG6zTObBA8466.jpg
    上图是zabbix默认的配置,通过宏{#FSTYPE}和正则表达式“File systems for discovery”过滤文件系统类型。
wKioL1Pgmv7Q6SIrAACShme3-RY046.jpg
    现在问题来了,如果我想同时根据{#FSNAME}这个宏过滤掉一些我不关心的文件系统,该怎么办?
分析问题:
    zabbix在Discovery rule中只能过滤单个宏,不支持多宏过滤的写法,因此上述需求就无法实现了。
    但是通过修改zabbix底层C代码,可以支持多宏过滤的。
规定参数写法:
    Macro 多个宏变量之间用逗号分隔;
    Regexp 正则表达式名前面加'@',多个表达式之间也用逗号分隔;

    相同位置的宏变量和正则表达式是对应的,即第一个宏对应第一个正则表达式,第二个宏对应第二个正则表达式...
    填写方式如下:

    wKioL1PgnaKQZtlBAAEzwYakods346.jpg
解决方法:
    建议先在自己的测试环境中修改,测试成功后再应用到生产环境。   

    第一步,下载附件,改名为lld.c。如果你的zabbix版本是2.2.5,下载源码安装包,解压:
1
shell# tar xvzf zabbix-2.2.5.tar.gz



    第二步,把上面下载的lld.c文件覆盖掉zabbix原始lld.c文件,zabbix2.2.2及以上版本可直接覆盖:
1
shell# \cp lld.c zabbix-2.2.5/src/libs/zbxdbhigh/lld.c



    第三步,编译zabbix server:
1
2
3
shell# cd zabbix-2.2.5
shell# ./configure --prefix=/etc/zabbix --with-mysql --with-net-snmp --with-libcurl --with-openipmi --with-ssh2 --enable-server
shell# make



    没有报错的话,编译成功~见下图
wKiom1Pgon-gQXg4AAKvS5VwzxY657.jpg
    第四步,停掉zabbix server服务,备份zabbix_server主程序

1
2
shell# /etc/init.d/zabbix-server stop
shell# cp /usr/sbin/zabbix_server /usr/sbin/zabbix_server.bak



    第五步,将编译好的zabbix_server覆盖原zabbix_server主程序,启动zabbix server服务
1
2
shell# cp src/zabbix_server/zabbix_server /usr/sbin/zabbix_server
shell# /etc/init.d/zabbix-server start



测试结果:
    第一步:只过滤{#FSTYPE},配置Discovery rule如下:
wKiom1PgsfvAURxHAAHxRs__tAI739.jpg
监控间隔设置120秒,"Keep lost resources period"设置为0,方便观察结果。
"Filter Macro"填写"{#FSTYPE}";"Regexp"填写"@File systems for discovery"。
查看监控项组Filesystems下的监控项:
wKiom1PgswjgY9_gAAJo7WR_WtI038.jpg
    第二步:同时过滤{#FSTYPE}和{#FSNAME},使{#FSNAME}过滤掉boot目录
    先创建正则表达式"Filter file system name":
wKioL1PgtOuD4GeNAAKKX2EsB24463.jpg
    配置Discovery rule:
wKiom1PgtO3wik67AAES2Rrw0t4439.jpg
"Filter Macro"填写"{#FSTYPE},{#FSNAME}";
"Regexp"填写"@File systems for discovery,@Filter file system name"。
注意:这里是英文的逗号','。

大约120秒后,查看监控项组Filesystems下的监控项:
wKioL1PgtlLzAQSYAAHqmFwDMUk213.jpg
发现boot目录已经被过滤掉了。测试完成。
=====================================================================================================

附:lld.c主要修改部分截图,右侧是优化后的
wKiom1PguvzD1fdaAA7DtHubbpE997.jpg
[url=]优化后的lld.c[/url]
[url=]/*
** Zabbix
** Copyright (C) 2001-2014 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
**/

#include "lld.h"
#include "db.h"
#include "log.h"
#include "events.h"
#include "zbxalgo.h"
#include "zbxserver.h"
#include "zbxregexp.h"

static int    lld_check_record(struct zbx_json_parse *jp_row, const char *f_macro, const char *f_regexp,
        zbx_vector_ptr_t *regexps)
{
    const char    *__function_name = "lld_check_record";

    char        *value = NULL;
    size_t        value_alloc = 0;
    int        res = SUCCEED;

    zabbix_log(LOG_LEVEL_DEBUG, "In %s() jp_row:'%.*s'", __function_name,
            jp_row->end - jp_row->start + 1, jp_row->start);

    if (SUCCEED == zbx_json_value_by_name_dyn(jp_row, f_macro, &value, &value_alloc))
        res = regexp_match_ex(regexps, value, f_regexp, ZBX_CASE_SENSITIVE);

    zbx_free(value);

    zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res));

    return res;
}

static int    lld_rows_get(char *value, char *filter, zbx_vector_ptr_t *lld_rows, char **error)
{
    const char        *__function_name = "lld_rows_get";

    struct zbx_json_parse    jp, jp_data, jp_row;
    char            *f_macros_all = NULL, *f_regexps_all = NULL;
    char            *f_macros = NULL, *f_regexps = NULL;
    char            *f_macros_n = NULL, *f_regexps_n = NULL;
    char            *f_macro = NULL, *f_regexp = NULL;
    const char        *p;
    zbx_vector_ptr_t    regexps;
    zbx_lld_row_t        *lld_row;
    int            ret = FAIL, filter_out = FAIL;

    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

    if (SUCCEED != zbx_json_open(value, &jp))
    {
        *error = zbx_strdup(*error, "Value should be a JSON object.");
        goto out;
    }

    /* {"data":[{"{#IFNAME}":"eth0"},{"{#IFNAME}":"lo"},...]} */
    /*         ^-------------------------------------------^  */
    if (SUCCEED != zbx_json_brackets_by_name(&jp, ZBX_PROTO_TAG_DATA, &jp_data))
    {
        *error = zbx_dsprintf(*error, "Cannot find the \"%s\" array in the received JSON object.",
                ZBX_PROTO_TAG_DATA);
        goto out;
    }

    zbx_vector_ptr_create(&regexps);

    if (NULL != (f_regexps_all= strchr(filter, ':')))
    {
        f_macros_all= filter;
        *f_regexps_all++ = '\0';

        zabbix_log(LOG_LEVEL_DEBUG, "%s() f_macros_all:'%s' f_regexps_all:'%s'", __function_name, f_macros_all, f_regexps_all);
    }

    f_macros = zbx_malloc(NULL, strlen(f_macros_all) + 1);
    f_regexps = zbx_malloc(NULL, strlen(f_regexps_all) + 1);

    p = NULL;
    /* {"data":[{"{#IFNAME}":"eth0"},{"{#IFNAME}":"lo"},...]} */
    /*          ^                                             */
    while (NULL != (p = zbx_json_next(&jp_data, p)))
    {
        /* {"data":[{"{#IFNAME}":"eth0"},{"{#IFNAME}":"lo"},...]} */
        /*          ^------------------^                          */
        if (FAIL == zbx_json_brackets_open(p, &jp_row))
            continue;

        f_macros_n = f_macros;
        f_regexps_n = f_regexps;
        zbx_strlcpy(f_macros_n, f_macros_all, strlen(f_macros_all) + 1);
        zbx_strlcpy(f_regexps_n, f_regexps_all, strlen(f_regexps_all) + 1);

        while (NULL != f_macros_n && NULL != f_regexps_n)
        {
            f_macro = f_macros_n;
            if(NULL != (f_macros_n = strchr(f_macros_n, ',')))
                *f_macros_n++ = '\0';

            f_regexp = f_regexps_n;
            if(NULL != (f_regexps_n = strchr(f_regexps_n, ',')))
                *f_regexps_n++ = '\0';

            if ('@' == *f_regexp)
                DCget_expressions_by_name(&regexps, f_regexp + 1);

            zabbix_log(LOG_LEVEL_DEBUG, "%s() f_macro:'%s' f_regexp:'%s'", __function_name, f_macro, f_regexp);
            if (NULL != f_macro && SUCCEED != lld_check_record(&jp_row, f_macro, f_regexp, &regexps))
            {
                filter_out = SUCCEED;
                break;
            }
        }

        if (filter_out == SUCCEED)
        {
            filter_out = FAIL;
            continue;
        }

        lld_row = zbx_malloc(NULL, sizeof(zbx_lld_row_t));
        memcpy(&lld_row->jp_row, &jp_row, sizeof(struct zbx_json_parse));
        zbx_vector_ptr_create(&lld_row->item_links);

        zbx_vector_ptr_append(lld_rows, lld_row);
    }

    zbx_free(f_macros);
    zbx_free(f_regexps);
    zbx_regexp_clean_expressions(&regexps);
    zbx_vector_ptr_destroy(&regexps);

    ret = SUCCEED;
out:
    zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

    return ret;
}

static void    lld_item_link_free(zbx_lld_item_link_t *item_link)
{
    zbx_free(item_link);
}

static void    lld_row_free(zbx_lld_row_t *lld_row)
{
    zbx_vector_ptr_clean(&lld_row->item_links, (zbx_mem_free_func_t)lld_item_link_free);
    zbx_vector_ptr_destroy(&lld_row->item_links);
    zbx_free(lld_row);
}

/******************************************************************************
*                                                                            *
* Function: lld_process_discovery_rule                                       *
*                                                                            *
* Purpose: add or update items, triggers and graphs for discovery item       *
*                                                                            *
* Parameters: lld_ruleid - [IN] discovery item identificator from database   *
*             value      - [IN] received value from agent                    *
*                                                                            *
******************************************************************************/
void    lld_process_discovery_rule(zbx_uint64_t lld_ruleid, char *value, zbx_timespec_t *ts)
{
    const char        *__function_name = "lld_process_discovery_rule";

    DB_RESULT        result;
    DB_ROW            row;
    zbx_uint64_t        hostid = 0;
    char            *discovery_key = NULL, *filter = NULL, *error = NULL, *db_error = NULL, *error_esc;
    unsigned char        state = 0;
    unsigned short        lifetime;
    zbx_vector_ptr_t    lld_rows;
    char            *sql = NULL;
    size_t            sql_alloc = 128, sql_offset = 0;
    const char        *sql_start = "update items set ", *sql_continue = ",";

    zabbix_log(LOG_LEVEL_DEBUG, "In %s() itemid:" ZBX_FS_UI64, __function_name, lld_ruleid);

    zbx_vector_ptr_create(&lld_rows);
    sql = zbx_malloc(sql, sql_alloc);

    result = DBselect(
            "select hostid,key_,state,filter,error,lifetime"
            " from items"
            " where itemid=" ZBX_FS_UI64,
            lld_ruleid);

    if (NULL != (row = DBfetch(result)))
    {
        char    *lifetime_str;

        ZBX_STR2UINT64(hostid, row[0]);
        discovery_key = zbx_strdup(discovery_key, row[1]);
        state = (unsigned char)atoi(row[2]);
        filter = zbx_strdup(filter, row[3]);
        db_error = zbx_strdup(db_error, row[4]);

        lifetime_str = zbx_strdup(NULL, row[5]);
        substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL,
                &lifetime_str, MACRO_TYPE_COMMON, NULL, 0);
        if (SUCCEED != is_ushort(lifetime_str, &lifetime))
        {
            zabbix_log(LOG_LEVEL_WARNING, "cannot process lost resources for the discovery rule \"%s:%s\":"
                    " \"%s\" is not a valid value",
                    zbx_host_string(hostid), discovery_key, lifetime_str);
            lifetime = 3650;    /* max value for the field */
        }
        zbx_free(lifetime_str);
    }
    else
        zabbix_log(LOG_LEVEL_WARNING, "invalid discovery rule ID [" ZBX_FS_UI64 "]", lld_ruleid);
    DBfree_result(result);

    if (0 == hostid)
        goto clean;

    zabbix_log(LOG_LEVEL_WARNING, "%s() discovery_key:'%s' filter:'%s'", __function_name, discovery_key, filter);
    if (SUCCEED != lld_rows_get(value, filter, &lld_rows, &error))
        goto error;

    error = zbx_strdup(error, "");

    lld_update_items(hostid, lld_ruleid, &lld_rows, &error, lifetime, ts->sec);
    lld_update_triggers(hostid, lld_ruleid, &lld_rows, &error);
    lld_update_graphs(hostid, lld_ruleid, &lld_rows, &error);
    lld_update_hosts(lld_ruleid, &lld_rows, &error, lifetime, ts->sec);

    if (ITEM_STATE_NOTSUPPORTED == state)
    {
        zabbix_log(LOG_LEVEL_WARNING,  "discovery rule [" ZBX_FS_UI64 "][%s] became supported",
                lld_ruleid, zbx_host_key_string(lld_ruleid));

        add_event(0, EVENT_SOURCE_INTERNAL, EVENT_OBJECT_LLDRULE, lld_ruleid, ts, ITEM_STATE_NORMAL,
                NULL, NULL, 0, 0);
        process_events();

        zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sstate=%d", sql_start, ITEM_STATE_NORMAL);
        sql_start = sql_continue;
    }
error:
    if (NULL != error && 0 != strcmp(error, db_error))
    {
        error_esc = DBdyn_escape_string_len(error, ITEM_ERROR_LEN);

        zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%serror='%s'", sql_start, error_esc);
        sql_start = sql_continue;

        zbx_free(error_esc);
    }

    if (sql_start == sql_continue)
    {
        zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where itemid=" ZBX_FS_UI64, lld_ruleid);

        DBbegin();

        DBexecute("%s", sql);

        DBcommit();
    }
clean:
    zbx_free(error);
    zbx_free(db_error);
    zbx_free(filter);
    zbx_free(discovery_key);
    zbx_free(sql);

    zbx_vector_ptr_clean(&lld_rows, (zbx_mem_free_func_t)lld_row_free);
    zbx_vector_ptr_destroy(&lld_rows);

    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
}[/url]


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-23285-1-1.html 上篇帖子: Zabbix自动化之low level discovery遇到的问题 下篇帖子: zabbix监控Used Memory
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表