OpenTelemetry WebSocket 监控终极方案:打通最后一公里

概述

OpenTelemetry,以下简称 OTEL,是由 CNCF 托管的“一站式可观测性标准”,把指标、链路、日志三大信号统一为单一 SDK/API,零侵入地采集从浏览器、移动端到后端、容器、云服务的全栈遥测数据,并支持 40+ 后端一键导出,让分布式系统的黑盒瞬间变透明。

OpenTelemetry-JS 是 OpenTelemetry 开源的 JavaScript/TypeScript 观测框架,可在浏览器与 Node.js 中无侵入地采集 Traces、Metrics、Logs,自动埋点 HTTP、Fetch、WebSocket、gRPC、数据库等调用链,一键导出至 Jaeger、Prometheus、Zipkin 等后端,实现前端到后端的统一可观测性。

本文章主要通过参考 opentelemetry-js 相关开源方案,经过代码编写以及前端业务自埋点改造,演示 OTEL 前端 Span 如何上报到观测云,以及基于 OTEL 的前端 Span 上报,如何实现在 WebSocket 应用场景的最后一公里探测的最佳实践。

众所周知,OTEL 的前端和后端都是通用的 Span 数据上报方式,而观测云又兼容 OTEL 协议并且 DataKit 开箱即用支持 OTEL Span 数据的上报,因此对于 WebSocket 应用,基于 OTEL 的后端与前端 Span 埋点监控可以在链路层面实现完整的端到端的监控。

前端 Span 上报观测云实践

功能特性

  • OpenTelemetry SDK 初始化
  • 基于 trace parent 创建 span
  • OTLP 协议数据导出
  • 批量 span 处理
  • 分布式追踪上下文传播
  • TypeScript 支持

代码说明

otel-span/
├── index.ts              # 主入口文件
├── create-span.ts        # OpenTelemetry span 创建逻辑
├── package.json          # 项目依赖配置
├── tsconfig.json         # TypeScript 配置
index.ts

index.ts 作为主入口文件

import { setupOTelSDK, createSpanWithTraceParent } from './create-span'

// 初始化 OpenTelemetry SDK
setupOTelSDK()

// 使用traceparent创建span, 可以在请求 request header中获取
const traceParent = '00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01'
const spanName = 'test-span'

console.log('开始创建 span...')
const span = createSpanWithTraceParent(traceParent, spanName)
console.log('span 创建完成!')

// 等待一段时间确保 span 被导出
setTimeout(() => {
  console.log('程序执行完成')
  process.exit(0)
}, 2000)

create-span.ts

create-span.ts 用于创建 span 逻辑

import { Resource } from '@opentelemetry/resources'
import { BatchSpanProcessor, WebTracerProvider } from '@opentelemetry/sdk-trace-web'
import { ZoneContextManager } from '@opentelemetry/context-zone'
import { trace, SpanContext, TraceFlags, context } from '@opentelemetry/api'
import { W3CTraceContextPropagator } from '@opentelemetry/core'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'

const setupOTelSDK = () => {
  const resource = Resource.default().merge(
    new Resource({
      'service.name': 'test',
    })
  )

  const tracerProvider = new WebTracerProvider({
    resource: resource,
  })

  const traceExporter = new OTLPTraceExporter({
    url: 'http://127.0.0.1:9529/otel/v1/traces',
    headers: {},
  })

  const spanProcessor = new BatchSpanProcessor(traceExporter, {
    // 可选配置参数
    maxExportBatchSize: 100, // 每批最多处理的span数量
    scheduledDelayMillis: 1000, // 定期导出的间隔时间(毫秒)
  })

  // propagation.setGlobalPropagator(new W3CTraceContextPropagator());
  // 设置上下文传播器
  const contextManager = new ZoneContextManager()
  tracerProvider.addSpanProcessor(spanProcessor)
  tracerProvider.register({
    contextManager,
    propagator: new W3CTraceContextPropagator(),
  })
  trace.setGlobalTracerProvider(tracerProvider)

}

const parseTraceParent = (traceParent: string) => {
  const parts = traceParent.split('-')
  if (parts.length !== 4) throw new Error('Invalid trace_parent format')
  if (parts[0] !== '00') throw new Error('Unsupported trace_parent version')

  const traceId = parts[1]
  const parentSpanId = parts[2]

  if (traceId.length !== 32) throw new Error('traceId must be 32 characters')
  if (parentSpanId.length !== 16) throw new Error('parentSpanId must be 16 characters')
  if (!isHex(traceId)) throw new Error('traceId contains invalid hex characters')
  if (!isHex(parentSpanId)) throw new Error('parentSpanId contains invalid hex characters')

  return [traceId, parentSpanId]
}

const isHex = (s: string) => {
  return /^[0-9a-fA-F]+$/.test(s)
}

const createSpanWithTraceParent = (traceParent: string, spanName: string) => {
  if (!traceParent) return
  const [traceId, parentSpanId] = parseTraceParent(traceParent)
  const tracer = trace.getTracer('Browser')
  // 创建SpanContext
  const spanContext: SpanContext = {
    traceId: traceId,
    spanId: parentSpanId,
    traceFlags: TraceFlags.SAMPLED,
    // traceState: new TraceState(),
    isRemote: true,
  }
  // 包装SpanContext为Span
  const parentSpan = trace.wrapSpanContext(spanContext)
  // 创建父级上下文 - 修正这一行
  const parentContext = trace.setSpan(context.active(), parentSpan)
  // 创建并启动子span
  const childSpan = tracer.startSpan(
    spanName,
    {
      // attributes: {
      //   "parsing time": `${10000/1000}μs`
      // }
    },
    parentContext
  )

  try {
    // console.info(`Child span started with trace_id: ${traceId}`);
    // 业务逻辑...
  } finally {
    childSpan.end()
  }
}

export { setupOTelSDK, createSpanWithTraceParent }

扩展说明

添加自定义属性

const childSpan = tracer.startSpan(
  spanName,
  {
    attributes: {
      'custom.attribute': 'value',
      'user.id': '12345',
      'operation.type': 'read'
    }
  },
  parentContext
)

添加事件

childSpan.addEvent('operation.started', {
  'input.size': inputSize
})

设置状态

childSpan.setStatus({
  code: SpanStatusCode.OK,
  message: 'Operation completed successfully'
})

上报测试

1、克隆或解压项目

https://github.com/lrwh/observable-demo/tree/main/otel-span

数据上报地址使用观测云的本地的 DataKit 为例。

2、安装依赖:npm install

3、开发模式试运行:npm run dev

数据上报服务名为“test”,span 名称为“test-span” 。

4、观测云 DataKit 数据接收与展示

WebSocket 应用场景实战

场景描述

某平台已实现基于 OTEL 的后端 Span 的上报,前端三端的监控是基于观测云的 SDK 进行了集成,也实现了一定意义上的前端RUM数据和和后端 OTEL 的链路数据关联,但是 WebSocket 长连接打破了传统的请求-响应模式,传统 HTTP 的 Trace 是请求粒度的,而 WebSocket 连接可能持续数小时,而且重点是 WebSocket 的 Server 端也会发起一些业务数据推送请求到客户端时,此时仅通过后端的 OTEL 链路无法确定数据什么时候推送到的客户端,以及客户端的渲染情况表现如何。

方案与原理

首先,观测云在三端客户端(web,安卓,IOS)通过自身的 SDK 集成,会生成基于 w3c_traceparent 的 Span,相关的 traceparent 上下文会传递到 WebSocket Server 后端链路 Span,当后端的 WebSocket Server 推业务请求数据到客户端时,会继续传播 traceparent 上下文给 OTEL 前端 Span,进而通过补充 OTEL 前端 Span 的最后一公里的数据上报,实现整个 websocket 通信的全链路监控以及链路不同阶段调用的耗时情况。

前端自埋点

  • 通过前端埋点来探测 WebSocket Server 端什么时间刚好把业务数据请求发送到客户端

如下图所示,在前端业务代码中定义时,后端传过来 data.traceparent,随后即执行核心业务代码创建 span 的操作,即上述“前端 Span 上报观测云“章节中类似主入口中的index.ts 的 createSpanWithTraceParent 方法。

const span = createSpanWithTraceParent(traceParent, spanName)

也即是最终会调用 create-span.ts 程序文件中的 createSpanWithTraceParent 方法。

  • 通过前端埋点来探测 WebSocket Server 端推送业务请求数据到客户端之后,客户端什么时候渲染完成

如下图,同理,也是 WebSocket Server 端 traceparent 数据传播到客户端,即调用 createSpanWithTraceParent(traceParent, spanName) 方法来实现。

更多自埋点类似原理,需要自行选择合适位置进行埋点。

效果展示

  • 拓扑展示

  • 链路展示

总结

基于 OTEL 前端 Span 的数据上报与自定义埋点改造,解决了 WebSocket 应用场景下 WebSocket Server 到客户端最后一公里的探测问题,从而使 WebSocket 应用的请求通信有了端到端的可观测,整个通信过程的性能耗细节一览无余。

相关推荐

技术实战:观测云告警到飞书群并精准@相关人

本文介绍观测云如何通过 Webhook 将告警推送至 DataFlux Func,完成消息格式转换并 @责任人,实现精准提醒。

观测云的博客 346

基于 OpenTelemetry 实现 LangChain 观测云全链路可观测

文章介绍基于 OpenTelemetry 为 LangChain 应用构建 Zero-Code 全链路可观测方案,无需修改业务代码即可自动采集工作流、Prompt 与模型调用链路,帮助快速定位性能瓶颈与故障,并分析模型输入输出及 Token 消耗。

观测云的博客 343

Spring AI + Spring AI Alibaba 接入观测云最佳实践

文章介绍 Spring AI 与 Spring AI Alibaba 应用接入观测云的实践方案,通过 OpenTelemetry 自动采集 Agent、LLM 与 Tool 调用链路,实现性能、Token、模型及工具调用的统一观测,提升 AI 应用故障排查与性能优化效率。

观测云的博客 462

观测云 Agent 输出质量评估上线!智能体答得好不好别再靠感觉

观测云上线Agent质量评估系统,支持Prompt Eval和Schema Eval,自动检测输出质量与结构,提升智能化服务可靠性。

观测云的博客 665

观测云产品更新 | Agent 监测、故障中心、应用性能监测、日志、基础设施等

观测云新增AI API计费、告警策略优化、Agent Skills提升、故障作战室、LangChain兼容、性能监测与日志优化等功能。

观测云的博客 361

AI时代的用户访问监测:观测云带你身临其境体验用户与前端UI交互旅程

观测云 RUM 通过真实用户访问数据呈现应用整体体验情况。在应用列表和分析看板中,团队可以查看用户访问量、页面性能、错误情况等关键指标,判断问题影响范围。

观测云的博客 297

观测云全新上线「全局工作区」:进一步统一数据查询

观测云全局工作区上线,支持多模块Tab切换,提升故障排查效率。

观测云的博客 412

Fastjson 高危 RCE(CVE-2026-16723):如何用观测云快速发现并完成修复

本文针对 Fastjson 高危 RCE 漏洞 CVE‑2026‑16723,剖析其影响与利用条件,指出 Maven 静态排查的局限。观测云依托 ddtrace 运行时数据,完成漏洞检测定位告警修复闭环,提供升级、应急防护、迁移 fastjson2 处置方案。

观测云的博客 450

观测云应用性能监测 :帮助团队定位性能瓶颈

观测云 APM 将应用运行过程中的关键性能信息连接起来,帮助团队从发现异常服务,到定位请求链路,再到深入分析代码性能,逐步还原问题发生的过程。

观测云的博客 354

基于 DataFlux Func 构建 Vibe Coding 运行底座

DataFlux Func 可以作为 Vibe Coding 的运行底座。Func 本身提供脚本管理、函数执行、定时任务、函数 API、连接器、环境变量和运行日志等能力;MCP 则让 AI Agent 能够以标准化方式连接 Func,把“写代码”和“运行代码”的链路打通。这套实践不限定某一个 AI 客户端。只要客户端支持 MCP 或具备等价的工具接入能力,例如 Cursor、Claude Desktop、OpenCode、Codex 等,都可以按相同思路接入 Func。

观测云的博客 303

AI时代日志分析:观测云让你从海量日志中找到关键线索

观测云日志围绕日志采集、处理、存储、查询分析以及异常定位等场景,将分散在不同来源的日志信息集中管理。通过 Pipeline 对日志进行解析和结构化处理,通过 GuanceDB 3.1 支撑海量数据存储与分析,帮助团队将原始日志转化为可查询、可分析的数据基础。

观测云的博客 198

AI时代基础设施监控:观测云让你的系统指标清晰可见

通过统一的数据视角,将基础设施、应用和业务信息连接起来,让工程团队从发现问题、分析原因到定位影响范围,形成更加完整的问题排查路径。

观测云的博客 182

观测云会话重放:把玩家游戏中的那一秒卡顿完整回放给研发团队

观测云 Browser SDK 3.3.7 WebGL / WebGL2 Session Replay,让游戏画面、用户操作、错误和性能数据回到同一条时间轴。

观测云的博客 335

观测云集成飞书 SSO 最佳实践

本文介绍如何基于 OIDC 协议,通过飞书集成平台、飞书开放平台两大渠道对接观测云实现 SSO 单点登录的完整方案,清晰区分了两大飞书平台的能力差异、适用场景与配置规范,形成了一套完整、可落地的跨系统身份集成流程。

观测云的博客 217

观测云 AI Agent Teams 安全能力漏扫与修复实践场景

一句话标准:这个 Agent 不能只是“会扫”,而要像一名资深 AppSec 工程师一样,知道问题在哪里、为什么危险、先修哪个、怎么安全地修、修完如何证明真的修好了漏洞扫描不是终点,修复闭环才是安全能力真正落地的标志。观测云 AI Agent Teams 的最佳实践,是让 Agent 在安全团队、研发团队和运维团队之间承担“证据整理、优先级判断、修复建议、协同跟踪、复测复盘”的工作,同时把扫描只读、修复审批、官方依据、脱敏输出和证据关闭作为治理底线。

观测云的博客 381

零码改造!Go 语言应用上报观测云完整最佳实践

本文详解 OpenTelemetry 标准协议接入观测云 DataKit 实操,零码无侵入搭建可观测体系,实现日志、调用链路联动分析。

观测云的博客 357

观测云产品更新 | Agent Teams、Agent 监测、日志、基础设施等

本期更新主要为观测云更新和 DataKit 更新。

观测云的博客 366

观测云 AI 智能体为什么能精准排查并修复故障?把排障经验写进 Runbook

立刻在观测云免费开通 Obsy AI 智能服务,体验 Obsy AI Copilot 和 AI Agent Teams 强大的故障排查能力;开通观测 Agent Teams,让 观测 AI 智能体团队 7×24 安全的在你生产环境里跑起来,

观测云的博客 543

万卡级算力集群 GPU 监控:基于观测云全链路观测实践

本文介绍如何通过观测云监控万卡级算力集群 GPU,与应用性能 Trace、业务日志、基础设施指标在统一平台中实现全栈关联与跨层下钻,真正构建起从硬件到业务的完整观测链路。

观测云的博客 489

观测云基于 AI Agent Teams 能力的场景实践

本文通过三个场景实践,介绍观测云 AI Agent Teams 如何将可观测性数据、智能分析与自动化运维能力深度结合,帮助用户更快发现问题、定位问题并解决问题。

观测云的博客 581

观测云产品更新 | Agent Teams、Agent 监测、统一目录、基础设施、应用性能监测等

观测云新增企业微信消息渠道、任务管理优化、容器化部署、Agent监测升级、分析看板改进、时间轴视图、联动变更、拓扑筛选、日志优化、性能监测等功能。

观测云的博客 238

观测云入选 OpenTelemetry 官方 Vendors

观测云面向 OpenTelemetry 构建的原生接入与可观测能力,正式进入全球 OpenTelemetry 生态视野。

观测云的博客 453

当 Agent 写代码快过人类审查:软件工程的信任链必须重建

下一阶段的软件工程,不是让人类追着每一行 AI 代码跑,而是让 Agent 提交证据,并让线上系统持续产生可用于纠错的信号。

观测云的博客 357

带你用观测 AI 智能体:自主分析与修复故障

观测云通过 Guance AI Agent Teams,为业务调查与恢复提供了统一的数据基座、受控的执行边界、结构化的证据输出。

观测云的博客 221

观测云正式支持 Qoder 可观测

在「观测云控制台」-「Agent 监测」,点击右上角「接入 Agent」,选择「Qoder」即可快速接入。

观测云的博客 296

带你用观测 AI 智能体:接入你的工作群聊

观测云通过 Guance AI Agent Teams,为生产侧的可观测 Agent 提供了统一的数据基座:日志、指标、Trace、事件,全部统一采集、统一标签、统一存储。

观测云的博客 204

观测云正式支持 Claude Code 可观测

在「观测云控制台」-「Agent 监测」,点击右上角「接入 Agent」,选择「Claude Code」即可快速接入。

观测云的博客 337

观测云产品更新 | Obsy AI、Agent Teams、Agent 监测、安全监测、故障中心等

本期更新主要为观测云更新和 DataKit 更新。详情见官网文档:https://docs.guance.com/release-notes/

观测云的博客 233

带你用观测 AI 智能体:与本地 Coding Agent 协作排障

观测云通过 Guance AI Agent Teams,为生产侧的可观测 Agent 提供了统一的数据基座日志、指标、Trace、事件,全部统一采集、统一标签、统一存储。

观测云的博客 383

观测云 6 月产品升级报告 | 观测 AI Agent Teams 全面升级、观测云安全功能强化、拨测与跨空间协同能力增强

2026 年 6 月,我们收到不少用户反馈。我们把这些声音,一条条变成了产品更新,以下是本月最值得关注的 9 大升级亮点,每一个都为了让你的观测体验更顺滑、更贴合实际业务场景。

观测云的博客 368
上一篇: 观测云接收 OpenTelemetry Collector 数据最佳实践
下一篇: Ceph 可观测性最佳实践
观测云
观测云 上海驻云信息科技有限公司官方账号 上海驻云信息科技有限公司官方账号
博客等级 码龄5年 2589粉丝 560原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值