美文网首页程序员技术干货
Logstash输出到opentsdb碰到的问题及解决方案

Logstash输出到opentsdb碰到的问题及解决方案

作者: 何约什 | 来源:发表于2017-06-04 10:30 被阅读589次

    引子

    最近笔者在项目中用到了opentsdb,用于存放采集数据指标,并提供实时的图表、曲线展示功能。

    opentsdb提供了自己的指标收集工具tcollector,故事就要从这里说起。

    tcollector解决不了的事

    笔者编写了一个抓包程序,用于实时分析MySQL中的请求情况,每10秒会输出一行记录到日志文件中,数据内容包括:

    • 时间点
    • 查询次数,查询响应时长,查询错误次数,查询影响的行数
    • 插入次数,插入响应时长,插入错误次数,插入影响的行数
    • ......

    总之,指标我放到一个日志文件了,如果用tcollector去做的话,要采集这些指标就非常困难了。
    主要的实现思路和要解决的问题有:

    • 文件变化通知
    • 新的日志文件的发现和通知
    • 每个文件上次处理的位置的记录
    • 接到文件和目录变化通知后,需要根据文件上次处理的位置来读取新的数据,并输出到opentsdb
    • 解决tcollector重启问题,需要持久化每个文件上次处理的位置记录信息

    笔者开始确实写了一个版本出来,测试跑起来也没问题,但是批量上线后发现有大量的无法工作,笔者有些气馁了。因为大家都知道,上面的东西都是logstash的强项。

    于是决定用logstash来解决这个问题。

    logstash解决问题

    缺省情况下logstash是没有opentsdb的插件的,需要下载插件并进行安装,我们可以在github上找到logstash-output-opentsdb插件,并按照官方知道的安装方法,把logstash-output-opentsdb插件进行安装。因为logstash的每个官方插件的README文件都介绍了具体安装步骤,笔者这里就不赘述了。

    logstash-output-opentsdb插件存在的问题

    安装好了插件,笔者于是写好配置文件,启动logstash。

    output {
     
        opentsdb {
                host => "127.0.0.1"
                port => 4242
                metrics => [
                        "%{metris_name}",
                        "%{value}",
                        "ip",
                        "%{ip}",
                        "port",
                        "%{port}"
                ]
        }
    }
    
    

    数据果然进到logstash之中了,一起看起来都很简单顺畅,然而,大家可能也想到了一个问题,数据的时间戳呢???,我们并没有输入时间戳,那么插件是否帮我们正确的完成了呢?

    这里就不得不检查一下插件的代码,这里我只展示关键的部分:

          # The first part of the message
          message = ['put',
                     event.sprintf(name),
                     event.sprintf("%{+%s}"),
                     event.sprintf(value),
          ].join(" ")
    

    从上面的代码我们可以看出,该插件在每次输出metrics到opentsdb时,实时生成时间戳。这显然无法达到笔者的目的,而且在多数据日志抓取中,都会存在日志文件中已经有自己的时间戳,这时候希望输出到opentsdb的数据的时间戳是该日志中的时间戳。否则,一旦因为某些原因logstash重启,需要处理历史日志数据的时候,真实生成的时间戳数据就会与我们期望的大相近庭了。

    改造logstash-output-opentsdb插件

    从前面的代码看起来,我们除了改造以外,别无他法。

    首先,logstash本身自带了@timestamp,而且是一个通用的变量;
    其次,logstash提供了各种版本可以修改@timestamp的值;
    所以,笔者决定在输出的时候,直接输出@timestamp的值作为opentsdb指标的时间戳。

    改动的代码很简单,如下所示:

          # The first part of the message
          message = ['put',
                     event.sprintf(name),
                     event.get("@timestamp").to_i.to_s,
                     event.sprintf(value),
          ].join(" ")
    

    当然我们还需要捕获日志中的时间,方法很多,这里列举一个例子:

    grok {
      match => [ "message", "^%{NUMBER:@timestamp}" ]
    }
    

    上述改造后的logstash-output-opentsdbb插件,笔者已经在生产系统使用,同时上传到了笔者的github中,如果不想改造的话,可以直接下载使用。

    相关文章

      网友评论

        本文标题:Logstash输出到opentsdb碰到的问题及解决方案

        本文链接:https://www.haomeiwen.com/subject/scsvfxtx.html