Custom Runtime支持Loggie Agent日志扩展

Loggie是一个基于Golang的轻量级、高性能的云原生日志采集Agent。您可以在自定义运行时的函数中使用Loggie Agent从文件中采集日志,然后上传到日志服务SLS进行日志的存储和自定义分析。

前提条件

已创建日志项目和日志库。具体操作,请参见创建项目Project创建Logstore

重要

创建的日志项目必须和要创建的函数在相同地域。

操作步骤

步骤一:创建函数

  1. 登录函数计算控制台,在左侧导航栏,单击函数

  2. 在顶部菜单栏,选择地域,然后在函数页面,单击创建函数

  3. 创建函数页面,配置以下配置项,其他配置项使用默认值,然后单击创建。详细内容请参见创建函数

    • 创建函数的方式:Web函数

    • 基本设置:设置函数名称

    • 函数代码:配置函数的运行环境和代码相关信息。

      配置项

      示例

      运行环境

      Python 3.9

      代码上传方式

      选择通过文件夹上传代码。其中上传的文件夹名称为codecode目录下的文件为app.pyapp.py的代码示例内容如下。

      from flask import Flask
      from flask import request
      import logging
      import os
      
      REQUEST_ID_HEADER = 'x-fc-request-id'
      
      app = Flask(__name__)
      
      format_str = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
      logging.basicConfig(filename='/tmp/log/fc-flask.log', filemode='w', 
          format=format_str, encoding='utf-8', level=logging.DEBUG)
      @app.route("/invoke", methods = ["POST"])
      def hello_world():
          rid = request.headers.get(REQUEST_ID_HEADER)
          logger = logging.getLogger()
      
          print("FC Invoke Start RequestId: " + rid)
          logger.info("FC Invoke Start RequestId: " + rid)
      
          data = request.stream.read()
          print(str(data))
          logger.info("receive event: {}".format(str(data)))
          
          print("FC Invoke End RequestId: " + rid)
          logger.info("FC Invoke Start RequestId: " + rid)
          return "Hello, World!"
      
      if __name__ == '__main__':
          app.run(host='0.0.0.0',port=9000)
      说明

      您可以修改代码中配置的filename='/tmp/log/fc-flask.log'为指定的日志类型及日志位置,该配置需要和步骤二中的sources.paths路径保持一致。

      启动命令

      /code/bootstrap

      说明

      bootstrap文件在步骤二会创建。

      监听端口

      9000

步骤二:创建bootstrap文件作为启动命令

  1. 函数创建成功后,在代码页签使用WebIDE在code目录下创建bootstrap文件。

    bootstrap文件示例内容如下。

    #!/bin/bash
    
    # 1. 创建pipelines.yml文件
    mkdir -p /tmp/log /code/etc
    cat << EOF > /code/etc/pipelines.yml
    pipelines:
      - name: demo
        sources:
          - type: file
            name: fc-demo
            addonMeta: true
            fields:
              topic: "loggie"
            fieldsUnderRoot: true
            paths:
              - "/tmp/log/*.log"
        sink:
          type: sls
          endpoint: ${LOGGIE_SINK_SLS_ENDPOINT}
          accessKeyId: ${LOGGIE_SINK_SLS_ACCESS_ID}
          accessKeySecret: ${LOGGIE_SINK_SLS_ACCESS_SECRET}
          project: ${LOGGIE_SINK_SLS_PROJECT}
          logstore: ${LOGGIE_SINK_SLS_LOGSTORE}
          topic: ${LOGGIE_SINK_SLS_TOPIC}
    EOF
    
    # 2. 创建loggie.yml文件
    cat << EOF > /code/etc/loggie.yml
    EOF
    
    # 3. 启动Loggie Agent,作为后台进程运行
    /opt/bin/loggie -config.system=/code/etc/loggie.yml -config.pipeline=/code/etc/pipelines.yml > /tmp/loggie.log 2>&1 &
    
    # 4. 启动应用程序
    exec python app.py

    该脚本会执行的操作如下:

    1. 创建配置文件pipelines.ymlpipelines.yml为Pipeline配置文件。

      • sources

        用于指定日志的类型和日志所在位置。本示例展示如何采集/tmp/log目录下所有以.log结尾的文件中的日志。

        sources配置中的addonMeta表示添加默认的日志采集state元信息。更多关于sources的配置,请参见Source通用配置

      • sink

        用于指定日志服务相关信息。关于参数的说明,请参见配置参数说明脚本中的变量会在步骤四设置。

    2. 创建配置文件loggie.ymlloggie.yml为Loggie的系统配置文件。

      文件为空,表示为默认配置。本文示例采用默认配置方法,loggie.yml文件必须存在。文件不为空时,其具体参数请参见Loggie系统配置

    3. 启动Loggie Agent,作为后台进程运行。Loggie Agent运行日志会打印到/tmp/loggie.log

    4. 启动应用程序。本文示例使用Python运行,请按照实际情况填写。

  2. 设置bootstrap文件权限为可执行权限。

    在WebIDE中选择Terminal > New Terminal,执行chmod 777 bootstrap命令设置文件权限。

  3. 单击部署代码,完成代码的部署。

步骤三:添加官方公共层Loggie Agent

  1. 单击配置页签,选择左侧页签,在区域单击编辑

  2. 在编辑函数层面板,选择添加层 > 添加官方公共层,配置Loggie Agent。

    关于Loggie Agent公共层的相关信息如下。

    层名称

    兼容的运行时

    层版本

    ARN

    Loggie Agent

    自定义运行时

    本文示例使用层版本1。

    acs:fc:{region}:official:layers/Loggie13x/versions/1

  3. 单击部署,完成Loggie Agent层的添加。

步骤四:设置环境变量

  1. 配置页签,选择左侧环境变量页签,单击编辑

  2. 在编辑函数环境变量面板,添加如下环境变量。关于如何配置环境变量,请参见配置环境变量

    • 设置环境变量FC_EXTENSION_SLS_LOGGIE=true

      添加该环境变量后,在一次函数调用结束时,不会立刻冻结函数实例,会等待10s再冻结函数实例,以确保Loggie Agent扩展成功上报日志。

      重要

      函数计算在调用结束至冻结前的等待时长会产生费用,收费策略与实例调用阶段的计费逻辑相同。具体信息,请参见产品计费

    • 设置pipelines.yml文件中的环境变量,包括LOGGIE_SINK_SLS_ENDPOINTLOGGIE_SINK_SLS_ACCESS_IDLOGGIE_SINK_SLS_ACCESS_SECRETLOGGIE_SINK_SLS_PROJECTLOGGIE_SINK_SLS_LOGSTORELOGGIE_SINK_SLS_TOPIC

      环境变量

      说明

      LOGGIE_SINK_SLS_ENDPOINT

      日志服务的服务入口。更多信息,请参见服务入口

      LOGGIE_SINK_SLS_ACCESS_ID

      阿里云AccessKey ID。如何获取AccessKey ID,请参见访问密钥

      LOGGIE_SINK_SLS_ACCESS_SECRET

      阿里云AccessKey Secret。如何获取AccessKey Secret,请参见访问密钥

      LOGGIE_SINK_SLS_PROJECT

      目标Logstore所在的Project。

      LOGGIE_SINK_SLS_LOGSTORE

      用于存储日志的Logstore。

      LOGGIE_SINK_SLS_TOPIC

      日志主题,自定义设置。

  3. 单击部署。函数配置更新后,可以支持将函数执行日志通过Loggie上传到日志服务。

步骤四:验证结果

  1. 代码页签,单击测试函数,通过控制台调试函数。

    配置完成后,首次调试日志可能会有一些延迟,建议多调用几次。

  2. 登录日志服务控制台,按照pipelines.yml文件中配置的地域、Project和Logstore查询日志。示例如下。

    image

    • body:日志信息。

    • state.*:日志采集state元信息,其中hostname为函数运行所在的实例ID。

问题排查

Loggie Agent独立运行在函数实例中,函数计算平台无法感知Loggie Agent是否正常,Loggie Agent运行异常也不会影响函数的正常执行。

如果在日志服务中无法查询到Loggie Agent相关日志时(会有秒级的延时),可参考以下流程进行排查。

函数运行正常

如果函数运行正常,在调用后函数实例会存活一段时间(一般是几分钟),可以登录实例查看Loggie Agent的运行状态和日志信息。关于登录实例的具体操作,请参见实例命令行操作

  • 如果没有日志信息,可以在命令行尝试启动Loggie Agent。

  • 如果Loggie有日志信息,根据日志信息排查。

    • 确认pipelines.yml文件是否配置正确。

    • 确认是否成功启动SLS sink配置。日志类似pipeline sink(sink/sls)-0 invoke loop start

    • 确认是否获取到日志文件。日志类似start collect file: /tmp/log/fc-flask.log。如果没有类似日志,按照pipelines.yml文件配置中的paths路径,确认是否有日志文件产生。

说明

首次接入SLS Logstore可能会有一定延时,如果日志一切正常,可以多次触发调用函数,等待几分钟后再查询日志。

函数运行失败

Loggie Agent作为外部扩展,一般不会影响函数的正常运行,可以先将Loggie Agent启动逻辑移除,排查函数运行是否正常。如果出现进程异常退出或者执行超时的报错,可以尝试调大内存或CPU规格。

相关文档

  • 在本文示例中,Loggie采集到日志后原样上传,没有经过任何加工处理。如果需要对日志数据加工后再上传,例如解析JSON格式、移除DEBUG日志等,可以在pipelines.yml中添加Interceptor配置,具体请参见Loggie-Interceptor

  • 如果您希望通过Serverless Devs工具部署一个由Custom-Python3.9事件类型实现的将采集日志文件上报到日志服务的函数,请参见示例应用程序(python3.9 flask)