教程:日志记录和跟踪入门

简介

本教程介绍了从函数和过程处理程序代码中发出、收集和查询日志及跟踪数据的基础知识。

本教程使用 Snowsight Web 界面,不过您可以使用任何支持执行 SQL 的 Snowflake 客户端。有关 Snowsight 的更多信息,请参阅 工作表入门在 Snowsight 中管理和使用工作表

您将学习的内容

在本教程中,您将学习如何进行以下操作:

  • 创建事件表以存储日志和跟踪数据。

    Snowflake 会在表的预定义结构中收集日志和跟踪数据。

  • 从用户定义的函数 (UDF) 发出日志消息和跟踪数据。

    可使用专为处理程序语言设计的 API,从处理程序代码中发出日志消息和跟踪数据。

  • 通过查询事件表来查看收集到的日志和跟踪数据。

    可使用 SELECT 语句查询此表,以分析收集到的数据。

先决条件

  • 必须在同一个 SQL 命令会话中执行所有 SQL 命令,因为会话上下文是必需的。

    例如,要在 Snowsight 中执行此操作,请将所有代码粘贴到同一个工作表中。在从一个部分推进到另外一个部分时,每个部分都以前一个部分为基础。

  • 必须能够使用 ACCOUNTADMIN 角色。

    在本教程中,您将使用 ACCOUNTADMIN 角色执行所有步骤。但在一般情况下,您使用的角色具有专为正在执行的操作而定义的权限。例如,您可能有专为创建 UDFs 的开发者提供的角色,另外还有专为查询收集到的日志和跟踪数据的分析师提供的单独角色,以此类推。

    有关角色的更多信息,请参阅 切换活动角色访问控制注意事项

设置数据库、仓库和访问

在本部分中,您将创建本教程需要用到的仓库和数据库。您还会开始使用 ACCOUNTADMIN 角色,执行本教程中的部分语句时必须使用此角色。

您要创建一个数据库,稍后将在其中创建事件表和用户定义的函数。对于在本教程中创建的所有对象,均可在不再需要时予以删除,包括数据库和仓库在内。

要创建供本教程使用的数据库和仓库,请执行以下操作:

  1. 登录 Snowsight。

  2. 切换到 ACCOUNTADMIN 角色

  3. 打开 Projects » Worksheets

  4. 选择 + » SQL Worksheet

  5. 将新工作表重命名Logging-tracing tutorial

  6. 在新工作表中,粘贴并运行以下语句以创建数据库。这个新数据库仅用于本教程。

    CREATE OR REPLACE DATABASE tutorial_log_trace_db;
    
    Copy
  7. 粘贴并运行以下语句以创建仓库。这个新仓库仅用于本教程。

    CREATE OR REPLACE WAREHOUSE tutorial_log_trace_wh
      WAREHOUSE_TYPE = STANDARD
      WAREHOUSE_SIZE = XSMALL;
    
    Copy

在本部分中,您将准备本教程所需的部分。在下一部分中,您将创建事件表来存储日志和跟踪数据。

创建事件表

在本部分中,您将创建事件表。当处理程序代码发出日志消息和跟踪数据时,Snowflake 会将发出的数据保存在事件表行之中。您可以查询事件表以分析数据。

必须创建事件表以收集日志和跟踪数据。事件表始终使用 Snowflake 定义的 预定义结构

重要

要完成本部分,您需要能使用 ACCOUNTADMIN 角色,这是更改账户时所必需的,这样新事件表才能是该账户的活动事件表。

要创建事件表,并使其成为账户的活动事件表,请执行以下操作:

  1. 粘贴并运行以下语句,以创建事件表。

    CREATE OR REPLACE EVENT TABLE tutorial_event_table;
    
    Copy

    Snowflake 在此表中存储日志和跟踪数据。

  2. 粘贴并运行以下语句以更改账户,使您创建的事件表成为该账户的活动事件表。

    ALTER ACCOUNT SET EVENT_TABLE = tutorial_log_trace_db.public.tutorial_event_table;
    
    Copy

    此语句将新事件表设置为 Snowflake 应该用于以下用途的表:存储源自当前账户中处理程序的日志消息和跟踪数据。在一个账户中,您只能有一个活动事件表。

在本部分中,您创建了一个事件表。在下一部分中,您将开始发出 Snowflake 存储在表中的日志消息。

发出日志消息

在本部分中,您将使用发出日志消息的 Python 处理程序代码,创建一个用户定义的函数 (UDF)。在代码发出日志消息时,Snowflake 会收集消息数据并将其存储在您创建的事件表中。

Snowflake 支持通过 APIs 记录来自每种受支持的处理程序语言的消息。对于使用 Python 编写的处理程序,您可以使用 Python 标准库中的 logging 模块。

要创建发出日志消息的 UDF,请执行以下操作:

  1. 粘贴并运行以下语句,以将日志级别设置为 INFO

    ALTER SESSION SET LOG_LEVEL = INFO;
    
    Copy

    这指定了 Snowflake 在 UDF 运行时应该获取的日志消息的严重性。在这种情况下,该级别允许捕获从信息 (INFO) 到最高严重性 (FATAL) 的所有消息。

  2. 粘贴并运行以下语句以创建用户定义的函数。

    CREATE OR REPLACE FUNCTION log_trace_data()
    RETURNS VARCHAR
    LANGUAGE PYTHON
    RUNTIME_VERSION = 3.8
    HANDLER = 'run'
    AS $$
    import logging
    logger = logging.getLogger("tutorial_logger")
    
    def run():
      logger.info("Logging from Python function.")
      return "SUCCESS"
    $$;
    
    Copy

    代码中突出显示的行执行以下操作:

    • 导入 Python logging 模块,以供处理程序代码使用。

    • 创建一个日志记录程序,它会公开您的代码将用于在日志中记录消息的接口。

    • 它会在 INFO 级别记录一条消息。

  3. 粘贴并运行以下语句来执行刚刚创建的函数。

    SELECT log_trace_data();
    
    Copy

    这会产生以下输出。此外,在函数执行时,它发出了一条日志消息,而 Snowflake 在事件表中收集了该消息。

    --------------------
    | LOG_TRACE_DATA() |
    --------------------
    | SUCCESS          |
    --------------------
    

在本部分中,您从 UDF 发出了一条日志消息。在下一部分中,您将查询事件表以检索与该消息相关的数据。

查询日志消息

在本部分中,您将在事件表中查询上一部分中运行的 UDF 发出的日志消息数据。

备注

处理程序代码发出的日志或跟踪数据可能需要几秒钟时间才能记录到事件表中。如未立即看到结果,请在几秒钟后重试。

Snowflake 使用 预定义的事件表列,来收集和存储以下类型的日志和跟踪数据:

  • 您从处理程序代码发出的数据,例如日志消息和跟踪事件数据。

    您可以在 RECORD_TYPE、RECORD、RECORD_ATTRIBUTES 等列中找到这些数据。

  • 与发出日志或跟踪数据的 上下文相关的数据,例如时间戳、发出数据的处理程序方法的名称等。

    您可以在 RESOURCE_ATTRIBUTES、TIMESTAMP 和 SCOPE 等列中找到这些数据。

要查询事件表以获得日志消息数据,请执行以下操作:

  1. 粘贴并运行以下语句,以查询事件表。

    SELECT
      TIMESTAMP AS time,
      RESOURCE_ATTRIBUTES['snow.executable.name'] as executable,
      RECORD['severity_text'] AS severity,
      VALUE AS message
    FROM
      tutorial_log_trace_db.public.tutorial_event_table
    WHERE
      RECORD_TYPE = 'LOG'
      AND SCOPE['name'] = 'tutorial_logger';
    
    Copy

    有些列包含以键值对表示的结构化数据。在此查询中,您可以使用 方括号表示法 在列中指定属性键,例如 RECORD['severity_text']

    您还可以使用方括号表示法 (SCOPE['name']),指定仅选择符合以下条件的列值:使用您在处理程序代码中创建的 Python 日志记录器 tutorial_logger 发出日志条目的列。

  2. 查看输出。

    -----------------------------------------------------------------------------------------------------------
    | TIME                | EXECUTABLE                           | SEVERITY | MESSAGE                         |
    -----------------------------------------------------------------------------------------------------------
    | 2023-04-19 22:00:49 | "LOG_TRACE_DATA():VARCHAR(16777216)" | "INFO"   | "Logging from Python function." |
    -----------------------------------------------------------------------------------------------------------
    

    输出展示了 事件表的预定义列 如何分别包含所收集数据的各个部分。对于 EXECUTABLESEVERITY 值,您已使用方括号表示法来指定所需值对应的属性。

    输出列

    描述

    TIME

    条目的创建时间(来自 TIMESTAMP 列)。

    EXECUTABLE

    UDF 名称和参数(来自 RESOURCE_ATTRIBUTES 列的 snow.executable.name 属性)。

    SEVERITY

    日志条目严重性(来自 RECORD 列的 severity_text 属性)。

    MESSAGE

    日志消息(来自 VALUE 列)。

在本部分中,您使用了一条 SELECT 语句来查询日志数据。在下一部分中,您将更新 UDF,以使其发出跟踪数据。

发出追踪数据

在本部分中,您将更新 UDF 处理程序代码,使其也能发出跟踪数据。在代码发出跟踪数据时,Snowflake 会收集数据,并将其存储在您创建的事件表中。

跟踪数据具有结构化特性,包括按 Span 分组的事件数据,以及以键值对形式获取的数据,与日志数据通常支持的详细程度相比,这使您可以更详细地了解代码活动。

Snowflake 支持通过 APIs 从每种支持的处理程序语言发出跟踪数据。对于使用 Python 编写的处理程序,可以使用 Snowflake telemetry 包。

要更新 UDF 以发送跟踪数据,请执行以下操作:

  1. 粘贴并运行以下语句,以指定应获取哪些跟踪数据。

    ALTER SESSION SET TRACE_LEVEL = ON_EVENT;
    
    Copy

    这会将跟踪级别设置为 ON_EVENT。这指定了仅应获取您自己的代码显式发出的跟踪数据。

  2. 粘贴并运行以下语句,以创建一个 UDF 来发出跟踪数据。

    CREATE OR REPLACE FUNCTION log_trace_data()
    RETURNS VARCHAR
    LANGUAGE PYTHON
    PACKAGES = ('snowflake-telemetry-python')
    RUNTIME_VERSION = 3.8
    HANDLER = 'run'
    AS $$
    import logging
    logger = logging.getLogger("tutorial_logger")
    from snowflake import telemetry
    
    def run():
      telemetry.set_span_attribute("example.proc.run", "begin")
      telemetry.add_event("event_with_attributes", {"example.key1": "value1", "example.key2": "value2"})
      logger.info("Logging from Python function.")
      return "SUCCESS"
    $$;
    
    Copy

    通过运行此代码,即可将之前创建的函数替换为添加代码,以发出跟踪数据的函数。突出显示的行执行以下操作:

    • snowflake-telemetry-python`(其中包含 :code:`telemetry 包)添加到 UDF 的执行环境中。

    • 导入 telemetry 包,以便您可以调用其函数。

    • 将一个属性及属性值设置为 Snowflake 在代码运行时创建的 Span。

      Span 代表一个过程的执行单元或 UDF 的执行单元,您可以在其中添加多个事件。

    • 添加一个事件(具有其自己的属性),将其作为 Span 的一部分进行记录。

  3. 粘贴并运行以下语句来执行刚刚创建的函数。

    SELECT log_trace_data();
    
    Copy

    这会产生以下输出。此外,在函数执行时,它发出了跟踪数据,而 Snowflake 在事件表中收集了该跟踪数据。

    --------------------
    | LOG_TRACE_DATA() |
    --------------------
    | SUCCESS          |
    --------------------
    

在本部分中,您从 UDF 发出了跟踪数据。在下一部分中,您将查询事件表以检索与该跟踪相关的数据。

查询追踪消息

在本部分中,您将在事件表中查询上一部分中运行的 UDF 发出的跟踪数据。

备注

处理程序代码发出的日志或跟踪数据可能需要几秒钟时间才能记录到事件表中。如未立即看到结果,请在几秒钟后重试。

您编写的查询将检索与该函数发出的事件相关的上下文信息。该上下文包括发出它的函数的名称。

要查询事件表以获得跟踪数据,请执行以下操作:

  1. 粘贴并运行以下语句,以在事件表中查询跟踪数据。

    SELECT
      TIMESTAMP AS time,
      RESOURCE_ATTRIBUTES['snow.executable.name'] AS handler_name,
      RECORD['name'] AS event_name,
      RECORD_ATTRIBUTES AS attributes
    FROM
      tutorial_log_trace_db.public.tutorial_event_table
    WHERE
      RECORD_TYPE = 'SPAN_EVENT'
      AND HANDLER_NAME LIKE 'LOG_TRACE_DATA%';
    
    Copy

    有些列包含以键值对表示的结构化数据。为此,您可以使用 :ref:`方括号表示法 <label-bracket_notation_when_querying_semistructured_data>`在列中选择属性值,如代码中所示。

  2. 查看输出。

    -----------------------------------------------------------------------------------------------------------------------------------------------------
    | TIME                    | HANDLER_NAME                         | EVENT_NAME              | ATTRIBUTES                                             |
    -----------------------------------------------------------------------------------------------------------------------------------------------------
    | 2023-05-10 20:49:35.080 | "LOG_TRACE_DATA():VARCHAR(16777216)" | "event_with_attributes" | { "example.key1": "value1", "example.key2": "value2" } |
    -----------------------------------------------------------------------------------------------------------------------------------------------------
    

    输出展示了 事件表的预定义列 如何分别包含所收集数据的各个部分。对于 EXECUTABLESEVERITY 值,您已使用方括号表示法来指定所需值对应的属性。

    输出列

    描述

    TIME

    条目的创建时间(来自 TIMESTAMP 列)。

    HANDLER_NAME

    UDF 名称和参数(来自 RESOURCE_ATTRIBUTES 列的 snow.executable.name 属性)。

    EVENT_NAME

    通过 add_event 函数添加的事件的名称(来自 RECORD 列的 name 属性)。

    ATTRIBUTES

    为事件添加的附带属性(来自 RECORD_ATTRIBUTES 列)。

在本部分中,您在事件表中查询了您编写的 UDF 发出的跟踪数据。在最后一部分中,您将获得一些链接,其指向与本教程中执行的操作相关的信息。

了解详情

您已成功完成!做得很好。

在本教程中,您获得了端到端视图,以了解如何从处理程序代码中发出日志和跟踪数据、存储这些数据,然后查询所存储的数据。在此过程中,您执行了以下操作:

语言: 中文