如何实现 Logtail 的状态监控与异常告警

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 作为日志服务的采集 agent,Logtail 一般位于业务数据链路的前段,为链路中的后续部分输送数据,因此,它的正常运行显得至关重要。经过多年的实战打磨,Logtail 在稳定性和性能上都已经比较出色,在机器、网络等环境不变的情况下,配置完成后基本不再需要进行任何运维。

前言

作为日志服务的采集 agent,Logtail 一般位于业务数据链路的前段,为链路中的后续部分输送数据,因此,它的正常运行显得至关重要。经过多年的实战打磨,Logtail 在稳定性和性能上都已经比较出色,在机器、网络等环境不变的情况下,配置完成后基本不再需要进行任何运维。但随着时间变化,环境不变基本是个伪命题,因此,对于一些敏感业务,仍旧存在着对 Logtail 进行状态监控和异常告警的需求。

本文将介绍如何通过日志服务提供的服务日志、告警以及 API 等功能来实现此需求。

Logtail 状态

总的来说,Logtail 状态分为以下三种:

  1. Logtail 自身状态,包括:

    • 是否正在运行?
    • 心跳是否正常?
    • 是否发生过重启?
    • CPU、内存、网络流量?
    • ...
  2. Logtail 采集状态,包括:

    • 当前应用的配置数量
    • 当前打开的文件数量
    • 原始数据的读取速率
    • 解析成功和解析失败的日志量
    • ...
  3. Logtail 错误信息,所有非正常状态的汇总,包括:

    • 读取文件失败
    • 解析日志失败
    • 发送失败
    • ...

Logtail 会对以上所述的三类状态进行记录和上报(不包含用户数据,仅记录错误诊断所需要的内容),对于一些量比较大的状态,它会在发送前进行聚合,比如时间窗口内同种类型的错误信息将被聚合。

服务日志

为了获取之前提及的 Logtail 状态信息,需要先开通服务日志功能,具体的开通步骤可以参考此文档。在开通时,需要注意所选择的存储位置,后续操作需要在该位置对应的 project 内进行操作。 在开通时只要不勾选操作日志,则此功能完全免费。

在开通此功能后,存储位置对应的 project 下会增加一个名为 internal-diagnostic\_log 的 logstore,日志服务会将相关的 Logtail 状态信息分发到该 logstore,其中包含了多种类型的日志,为了避免混淆,不同类型的日志具有不同的主题(\_\_topic\_\_ 字段)。在本文中,我们仅关注其中的三种数据,它们的主题分别是 logtail\_statuslogtail\_profile 以及 logtail\_alarm

除了 logstore 以外,对应 project 下还会创建两个名为 Logtail采集统计Logtail运行监控 的仪表盘,其中包含一些预先创建的图表,能够帮助我们了解当前的全局状态。

状态监控及告警配置

在简单地介绍了服务日志后,我们接下来将对如何使用服务日志进行讲解。从性质上来看,服务日志和用户日志没有区别,因此,基于服务日志进行监控及告警也需要通过日志服务的 日志查询告警 两个功能实现:先通过日志查询功能编写查询语句,从服务日志中分析提取我们需要的信息,然后对查询语句配置告警。

基于预设仪表盘配置告警

我们知道,仪表盘上的每个图表都关联了对应的查询语句,因此,如果预设的采集统计和运行监控两个仪表盘中已经有符合你要求的图表,你完全可以基于它关联的查询语句进行告警配置。

以下我们以 Logtail运行监控 仪表盘为例,介绍一下相关的操作步骤。如下图所示,该仪表盘整体上分为基础信息、采集错误以及资源占用三部分。

undefined

undefined

原始数据流量监控

在实际情况中,很多业务的流量都具有很明显的周期性,从而在正常情况下,其关联的日志或数据量也具有相应的周期性。基于这一特点,同比同一时段,突增或者突减的流量都可以在一定程度上视为异常。

仪表盘中预设了「原始数据流量」这一项,我们可以基于它配置告警对该指标进行监控,操作步骤如下:

  1. 鼠标悬停到该项数值上方,接着悬停在右上角出现的省略号上,点击弹出菜单的「查看分析详情」跳转到查询页面。
    1550061200925-c232f4a6-f214-4192-b4c1-9de8764e7791.png
  2. 查询页面中给出了该图表对应的查询语句,可以看到,该查询利用了同比函数对 logtail\_status 日志中的 send-bytes-ps 字段进行了分析。并且,查询范围选择了 5 分钟,同比为 86400(一天),即比较一天前同一时间范围内的查询结果。
    1550061584308-10769874-c4b6-4d27-9f09-9da849d1d2dc.png
  3. 查询结果返回的 inc 字段表示同比发生的变化,我们可以对其设置告警,当流量同比增长超过某个阈值时,进行告警。
    1550062266935-69e50c58-8336-4928-9b56-716a0b401638.png

除此之外,我们还可以根据业务的实际情况,修改查询语句中的一些参数,包括查询范围、同比时间、告警阈值等。

采集延迟监控

接下来我们看看对采集延迟的监控,这对于延迟敏感的业务很有帮助。通过类似地步骤,查看「采集延迟」这一图表对应的查询语句,如下图所示。

undefined

可以看到,此处该语句对 logtail\_alarm 日志进行了分析,当采集进度落后并持续一段时间后,Logtail 会向服务端发送 READ\_LOG\_DELAY\_ALARM 警告,因此,通过统计该警告的数量,即可得知当前是否有采集延迟的情况。

类似地,我们可以为该查询语句创建告警,当出现采集延迟警告时进行告警,如下图所示。

undefined

关于采集延迟,还可以借助 Logtail采集统计 仪表盘中的「采集延迟」和「平均采集延迟」两个图表来查看具体延迟的数据量大小。

undefined

CPU 监控

为了避免 Logtail 占用过多资源影响业务,我们有时候需要对它的 CPU 利用率进行监控。预设的仪表盘中提供了「平均CPU」这一图表,我们可以基于它来实现此监控需求,它的查询语句如下。

undefined

可以看到,其中使用了 avg 来计算平均值,类似地,我们可以根据需要把 avg 替换成 max/min 等其他聚合函数,在设置告警时,对 total 设置所需的比较阈值即可。

自定义查询语句

除了基于预设仪表盘以外,我们也可以通过自行编写查询语句来实现所需的目标。在此之前,我们需要先了解 logtail_statuslogtail_alarm 以及 logtail_profile 这三类日志中各个字段的含义。

以下我们简单地举一些使用这些日志字段的例子。

使用 project/logstore 字段

这三类日志都拥有一个 project 字段,因此,我们可以利用它来筛选出所关注的 project,比如说一个 Logtail 节点同时采集了多个 project 下的配置,如果有些 project 下的数据重要程度并不是特别高,则可以使用 not project:xxx 这样的查询语句将它们过滤掉。类似地,有些日志提供了 logstore 字段,能够帮助我们进一步地缩小关注范围。

使用 alarm_count 字段

在 logtail_alarm 日志中,有一个 alarm_count 字段,它表示在时间窗口(即相邻两次上报之间)内该类型错误的数量,我们可以基于它进行一些监控。

SEND\_QUOTA\_EXCEED\_ALARM 为例,它表示当前日志写入流量超出限制。对于正常业务来说,偶尔的流量突增可能会带来少量的此错误,因此可以忽略,但是一旦短时间内此错误数量(alarm_count)超过了一定阈值,则说明当前可能存在其他的问题,比如:

  • 业务出现问题,大量错误日志引起写入流量激增,需要排查问题。
  • 其他业务和此业务共享 project,占用了 project 整体的 quota,需要上调 project 级别的 quota。
  • ...

机器组状态监控(Logtail 心跳)

Logtail 上报服务日志采用的是匿名方式,无需鉴权,只要网络正常即可上报,但网络正常的情况下依旧可能因为鉴权等原因导致心跳失败,因此,我们无法通过服务日志来判断 Logtail 的心跳是否正常。

对于此需求,目前比较好的办法是通过机器组状态 API 来实现,该方法的基本思路是周期性地调用机器组状态 API,获取所监控的机器组下各个机器的最近心跳时间,然后与当前时间进行比较,当超过一定范围时,判定心跳超时。

以下是基于 CLI 的 Python 实现(出于篇幅,错误处理已省略)。

import commands
import time
import json

def ListMachines(projectName, machineGroupName):
    cliCmd = 'aliyunlog log list_machines --project_name={} --group_name={}'.format(
        projectName, machineGroupName)
    status, result = commands.getstatusoutput(cliCmd)
    return json.loads(result)

def AssertLogtailHeartbeat(projectName, machineGroupName, threshold):
    machines = ListMachines(projectName, machineGroupName).get('machines', None)
    if machines is None:
        return []
    currentTimestamp = int(time.time())
    print 'Current timestamp', currentTimestamp
    failedMachines = []
    for machine in machines:
        if currentTimestamp - machine['lastHeartbeatTime'] > threshold:
            failedMachines.append(machine)
    return failedMachines

if __name__ == '__main__':
    """
    Usage: python monitor.py <project_name> <machine_group_name> <threshold_in_seconds>
    """
    import sys
    failedMachines = AssertLogtailHeartbeat(sys.argv[1], sys.argv[2], int(sys.argv[3]))
    print 'Failed machines count: {}'.format(len(failedMachines))
    for m in failedMachines:
        print 'IP: {}, last heartbeat time: {}'.format(m['ip'], m['lastHeartbeatTime'])

参考以上代码,根据需要配置合理的阈值(公有云上 Logtail 默认心跳周期为 30s 左右,可适当增大阈值至 1-3 分钟),然后定期执行即可实现对机器组状态的监控。对于定期执行的环境,可以使用函数计算的定时触发进行构建。

除了检查以外,我们还需要在发现失败机器时进行告警。对于这个需求,我们无需自行构建一套告警系统和通知渠道,可直接通过以下步骤复用日志服务的告警功能:

  1. 创建一个专门用于告警的 logstore。
  2. 当检查发现失败机器时,利用 CLI/SDK/API 向该 logstore 中写入一条日志(CLI 可以参考 put_logs 命令)。
  3. 为该 logstore 配置告警,当发现日志时(查询语句 * | select count(*) as c,告警表达式 c > 0),进行告警。

至此,我们完成了一个通过 CLI 访问日志服务 API 来实现对机器组状态监控的示例,你可以进一步地修改这个示例来实现对多个机器组乃至特定机器状态的监控。

小结

在本文中,我们首先简要介绍了服务日志中与 Logtail 状态相关的一些日志类型,然后从操作步骤上讲解了如何基于预设仪表盘以及自定义查询语句实现对 Logtail 的状态监控并设置异常告警,最后,我们补充了通过机器组状态 API 实现对 Logtail 心跳进行检查的示例。

更多阅读

  1. 服务日志功能简介
  2. Logtail 日志采集错误类型
  3. 日志服务 CLI 使用文档
  4. 欢迎加入钉钉群进行讨论交流

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
JSON 监控 Dubbo
基于SkyWalking的分布式跟踪系统 - 异常告警
基于SkyWalking的分布式跟踪系统 - 异常告警
313 0
|
Prometheus Kubernetes 监控
当 Pod 崩溃后如何在报警信息中获取对应的日志信息?
当 Pod 崩溃后如何在报警信息中获取对应的日志信息?
|
JSON 运维 Kubernetes
K8s场景下Logtail组件可观测方案升级-Logtail事件监控发布
SLS针对Logtail本身以及Logtail的管控组件alibaba-log-controller,采用K8s事件的方式,将处理流程中的关键事件透出,从而让用户能够更清楚的感知其中发生的异常。
549 0
K8s场景下Logtail组件可观测方案升级-Logtail事件监控发布
|
监控 Go 开发工具
EMQ
|
SQL JSON Prometheus
使用 Prometheus 监控 eKuiper 规则运行状态
本文介绍了eKuiper中的规则状态指标以及如何使用Prometheus监控这些状态指标,用户可以基于此进一步探索Prometheus的更多高级功能,更好地实现eKuiper的运维。
EMQ
205 0
|
JSON 应用服务中间件 数据处理
SLS告警最佳实践——在通知中引用日志内容
在配置告警通知的时候,通常我们需要知道告警的触发详情。例如Nginx访问错误告警,我们需要知道错误的HTTP Status 分布,错误的机器IP等信息,并且需要将这些信息体现在通知中,以便在接收到告警通知后,能够一目了然地知道发生了什么事情。那么在创建告警规则的时候,我们就需要进行合理的配置,使得告警在触发后,可以将这些信息放在合适的位置发送给通知服务,从而在通知模板里可以被引用到,从而被正确地通知。
503 0
|
存储 弹性计算 运维
SLS新版告警入门-监控主机CPU异常
随着用户量的增加,后台服务经常需要部署在多台服务器或者集群中来提高性能和增强可用性,在提供服务的过程中,由于程序bug或者业务徒增导致CPU飙高,如果CPU持续飙高,可能会导致机器down机,对服务造成不可用。 本文以此为背景,在主机监控时序数据中,配置SLS告警,来监控主机CPU飙高,并且在CPU飙高时发出告警到钉钉机器人。
607 0
|
存储 监控 机器人
Logtail 心跳监控最佳实践
作为采集 agent,logtail 所采集的日志可能会就被用于对应用程序进行监控/告警,所以保证它自身处于正常状态对整个系统的稳定显得尤为重要。在之前的[《全方位 Logtail 状态监控》](https://yq.aliyun.com/articles/691336)中,我们曾介绍了关于监控 Logtail 各类状态的方法,包括基本的链路状态、资源使用情况等。
1758 0
|
机器学习/深度学习 SQL 运维
异常行为监控
用户系统中如果出现任何的异常数据,比如一个运维系统的CPU消耗突然增高,比如平台突然有大量不良信息产生,比如有用户大量薅羊毛,这些行为都是平台的异常指标。如果能通过机器学习的方式帮助用户针对各种异常指标做预防和实时预警,将大大建设平台方的风险。
3224 0
异常行为监控
|
弹性计算 监控 机器人
用自定义监控实现 GPU 异常状况的检查与报警
## 应用场景 ## * 阿里云的云监控已原生支持 GPU 实例,可参考:[云监控实现GPU云服务器的GPU监控和报警](https://yq.aliyun.com/articles/610219) * 小概率场景中,GPU 卡会处于异常状态( 例如因[显存校验失败](https://docs.
1668 0