← 文章 / 云原生与基础设施
signoz 1天前 · 2026-11-08 19:03:58 · 0 阅读

使用 OpenTelemetry 实现 Open WebUI 的可观测性与监控

通过 OpenTelemetry 对自托管的 Open WebUI 进行监控,可以实时掌握部署运行状况。Open WebUI 后端内置 OpenTelemetry,会自动埋点 FastAPI、SQLAlchemy 及其 HTTP 客户端,无需改动任何代码,就能针对 API 请求、数据库查询和对外调用输出 traces、metrics 和 logs。如果你还想获取每次 LLM 调用的 GenAI 遥测数据(模型、token 和成本),可以通过 Open WebUI Pipelines 可选地接入 OpenLIT。

在 SigNoz 中获得完整的 Open WebUI 可观测性后,你可以端到端追踪 API 请求、监控数据库和接口延迟、跟踪各模型的 LLM token 用量与成本、针对错误和延迟设置告警,从而保障部署的稳定性。

前置条件

  • 拥有有效 ingestion key 的 SigNoz Cloud 账号,或 自托管的 SigNoz 实例
  • 系统上已安装并运行 Docker 和 Docker Compose
  • 一个正在运行的 Open WebUI 部署(需为支持 OpenTelemetry 的较新版本)。如果还没有,请参考 Open WebUI 官方文档
  • 仅在配置可选的 LLM 遥测插件时需要:OpenAI API key(或其他 OpenAI 兼容的服务商)

用 OpenTelemetry 监控 Open WebUI

Open WebUI 的 OpenTelemetry 组件已打包在后端中,只需通过环境变量开启,无需额外安装埋点包。由于 Open WebUI 的 exporter 不会附加自定义请求头,所以它将 OTLP 数据发送到一个轻量级 OpenTelemetry Collector,由后者附上你的 SigNoz ingestion key 并转发数据。下面三个步骤会用 Docker Compose 把两者串联起来,并将数据接入 SigNoz。搞定之后,你还可以选择用 OpenLIT 添加 LLM 遥测,获取每次调用的模型、token 和成本数据。

步骤 1:配置 OpenTelemetry Collector

创建 otel-collector-config.yaml。该 Collector 接收来自 Open WebUI 和 OpenLIT 的 OTLP 数据,并使用你的 ingestion key 导出到 SigNoz。

`otel-collector-config.yaml`
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
 
processors:
  batch:
    timeout: 5s
 
exporters:
  otlp/signoz:
    endpoint: https://ingest.<region>.signoz.cloud:443
    tls:
      insecure: false
    headers:
      signoz-ingestion-key: <your-ingestion-key>
 
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp/signoz]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp/signoz]
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp/signoz]

请确认以下值:

为什么需要 Collector?

SigNoz Cloud 通过 signoz-ingestion-key 头部进行摄取身份验证。Open WebUI 初始化其 OTLP 导出器时不包含自定义头部,因此无法自行附加该密钥。Collector 代表 Open WebUI 添加了这一信息。如果您使用的是自托管 SigNoz,则可以将 Open WebUI 的导出器直接指向您的 SigNoz OTLP 端点,从而跳过此步骤。

第 2 步:使用 Docker Compose 启动服务栈

创建 docker-compose.yaml。它将在同一网络中运行 Open WebUI 和 Collector,Open WebUI 会将其原生 OTLP 数据导出到 Collector。

services:
  otel-collector:
    image: otel/opentelemetry-collector-contrib:latest
    command: ["--config=/etc/otel-collector-config.yaml"]
    volumes:
      - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro
    ports:
      - "4317:4317"
      - "4318:4318"
 
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    depends_on: [otel-collector]
    environment:
      ENABLE_OTEL: "true"
      ENABLE_OTEL_TRACES: "true"
      ENABLE_OTEL_METRICS: "true"
      ENABLE_OTEL_LOGS: "true"
      OTEL_SERVICE_NAME: "open-webui"
      OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector:4318"
      OTEL_OTLP_SPAN_EXPORTER: "http"
      OTEL_EXPORTER_OTLP_INSECURE: "true"
    ports:
      - "3000:8080"
    volumes:
      - open-webui-data:/app/backend/data
 
volumes:
  open-webui-data:

启动所有服务:

Copy
docker compose up -d

上文中的 Open WebUI 环境变量用于控制原生导出:

变量必填值作用
ENABLE_OTEL是true开启 Open WebUI 的 OpenTelemetry 功能。
ENABLE_OTEL_TRACES / ENABLE_OTEL_METRICS / ENABLE_OTEL_LOGS否true(默认 false)分别启用各类遥测信号。
OTEL_SERVICE_NAME否open-webuiOpen WebUI 上报的 service.name。
OTEL_EXPORTER_OTLP_ENDPOINT是http://otel-collector:4318Collector 的 OTLP HTTP 端点。
OTEL_OTLP_SPAN_EXPORTER否http(默认 grpc)为 traces 选择 OTLP/HTTP 导出器。
OTEL_EXPORTER_OTLP_INSECURE是true在本地网络中以明文 OTLP 连接 Collector。
使用自托管的 SigNoz?

大多数步骤完全相同。只需按照 Cloud → Self-Hosted 文档,修改 Collector 的导出端点并移除数据接入密钥请求头即可。

第 3 步:生成遥测数据

  1. 在 http://localhost:3000 打开 Open WebUI,创建第一个(管理员)账号。
  2. 浏览应用并发起一次对话,触发 API 调用。

应用活动会产生 FastAPI、数据库和 HTTP 相关的 span。空闲实例几乎不产生数据,所以在查看 SigNoz 之前请先使用一下应用,并留出几秒钟的导出时间。至此,Open WebUI 的遥测数据已经进入 SigNoz。

使用 OpenLIT 添加 LLM 遥测(可选)

Open WebUI 的原生埋点可以捕获 API、数据库和 HTTP 的 span,但无法记录 token 用量、成本以及每次调用使用的模型。要捕获这些信息,需要运行一个 Open WebUI Pipelines 服务,并在其中使用经过 OpenLIT 埋点的 OpenAI 客户端。这会额外增加一个容器和一些手动配置,建议在前面的步骤正常上报数据之后再进行设置。

为何选择 OpenLIT,以及为什么采用 pipe 管道?

Open WebUI 的 Pipelines 框架支持两种插件类型:pipe(本身可作为可选择的模型)和 filter(包裹现有模型的入口/出口钩子,内置的 Langfuse 和 DataDog 集成即采用这种形式)。我们选用 pipe,因为 OpenLIT 能对其托管的 OpenAI 客户端进行自动化插桩,使每次调用都能输出完整的 gen_ai.* 遥测数据(包括模型、tokens、成本、提示与响应内容、首字延迟等),无需针对单个请求编写额外代码。OpenLIT 也原生支持 OpenTelemetry:它通过 OTLP 协议导出符合 gen_ai.* 语义约定标准的 span,可直接流经同一个 Collector 到达 SigNoz。相比之下,Langfuse 和 DataDog 的 filter 则将数据发送到各自的独立后端,而非通过 OTLP 流向 SigNoz。

创建 pipeline

新建文件 pipelines/openai_openlit_pipeline.py:

Copy
"""
title: OpenAI GenAI (OpenLIT)
requirements: openlit, openai
"""
import os
from typing import Generator, List, Union
 
from pydantic import BaseModel
 
 
class Pipeline:
    class Valves(BaseModel):
        OPENAI_API_KEY: str = ""
        OPENAI_MODEL: str = "gpt-4o-mini"
        OTLP_ENDPOINT: str = "http://otel-collector:4318"
 
    def __init__(self):
        self.id = "openai-genai"
        self.name = "OpenAI GenAI (OpenLIT)"
        self.valves = self.Valves(
            OPENAI_API_KEY=os.getenv("OPENAI_API_KEY", ""),
            OTLP_ENDPOINT=os.getenv("OTLP_ENDPOINT", "http://otel-collector:4318"),
        )
        self.client = None
 
    async def on_startup(self):
        import openlit
        from openai import OpenAI
 
        # 对 OpenAI 客户端进行插桩,并将 gen_ai.* span 导出至 Collector。
        openlit.init(otlp_endpoint=self.valves.OTLP_ENDPOINT, application_name="open-webui-llm")
        self.client = OpenAI(api_key=self.valves.OPENAI_API_KEY)
 
    def pipe(self, user_message: str, model_id: str, messages: List[dict], body: dict) -> Union[str, Generator]:
        resp = self.client.chat.completions.create(
            model=self.valves.OPENAI_MODEL,
            messages=messages,
            stream=True,
            stream_options={"include_usage": True},
        )
        for chunk in resp:
            if chunk.choices and chunk.choices[0].delta.content:
                yield chunk.choices[0].delta.content

添加 Pipelines 服务

把这个服务添加到第 2 步的 docker-compose.yaml 中,它会把 GenAI 遥测数据发送到同一个 Collector:

Copy
  pipelines:
    image: ghcr.io/open-webui/pipelines:main
    depends_on: [otel-collector]
    environment:
      OPENAI_API_KEY: ${OPENAI_API_KEY}
      OTLP_ENDPOINT: "http://otel-collector:4318"
    volumes:
      - ./pipelines:/app/pipelines
    ports:
      - "9099:9099"

然后在 open-webui 服务的 depends_on 里加上 pipelines,确保它在 Pipelines 服务启动之后再启动:

Copy
    depends_on: [otel-collector, pipelines]
配置 OpenAI API key

在重启整套服务之前,先配置 OPENAI_API_KEY 环境变量,这样 pipeline 才能调用 OpenAI。在 docker-compose.yaml 同级目录下创建一个 .env 文件(例如 OPENAI_API_KEY=<your-openai-api-key>)。Docker Compose 会自动读取该文件来填充 ${OPENAI_API_KEY},这样真实的密钥就不会出现在提交到代码库的 compose 文件里。

重启服务:

Copy
docker compose up -d

连接 pipeline

  1. 在 Open WebUI 中,进入 Admin Panel → Settings → Connections,添加一个 OpenAI 兼容连接,URL 填 http://pipelines:9099,API key 填 0p3n-w3bu!。
  2. 用 OpenAI GenAI (OpenLIT) 模型发起一个对话。

现在每次对话都会产生携带 gen_ai.* 属性(模型、token 用量、成本)的 GenAI span,归属于服务 open-webui-llm。

AI 可观测性

Open WebUI 原生的 HTTP 请求和数据库操作 span 不携带 GenAI 属性,因此不会出现在 AI Observability 中。本指南中的 OpenLIT pipeline 会添加能出现在 AI Observability 里的 LLM span。

在 SigNoz 中查看 Open WebUI 的 Traces

配置完成后,Open WebUI 会在服务 open-webui 下发出应用请求的 traces;如果你添加了 OpenLIT 步骤,还会在 open-webui-llm 下发出 LLM 调用的 traces。Traces 可以在 SigNoz 的 Traces 标签页中查看:

Open WebUI Trace 视图
原始来源: signoz

评论 (0)