
后端Web框架WebSocket【免费下载链接】phoenix_live_viewRich, real-time user experiences with server-rendered HTML项目地址https://gitcode.com/gh_mirrors/ph/phoenix_live_view点击查看免费下载Phoenix LiveView 通过 Erlang/Elixir 生态标准的telemetry为骨架逐一拆解全部 16 类事件的触发时机、测量值与元数据字段并结合仓库源码与测试用例说明底层实现与消费方式读完即可在自己的 Phoenix 应用中接入指标采集、慢请求分析与错误告警。事件总览LiveView 与 LiveComponent 的可观测点LiveView 当前暴露的遥测事件覆盖了两大实体Phoenix.LiveViewLiveView 本体与Phoenix.LiveComponent有状态组件。整体上事件名遵循[:phoenix, :live_view, 阶段, 结果]与[:phoenix, :live_component, 阶段, 结果]的命名约定其中结果统一为以下三种:start—— 回调被调用之前立即派发measurement 为%{system_time: System.monotonic_time}用于记录开始时刻:stop—— 回调成功完成时派发measurement 为%{duration: native_time}用于计算耗时:exception—— 回调抛出异常时派发measurement 同为%{duration: native_time}metadata 额外包含kind异常种类通常为:error与reason异常的具体 term。这种start/stop/exception三段式设计与:telemetry.span/3的语义完全对应。以:phoenix, :live_view, :mount为例源码 lib/phoenix_live_view/utils.ex#L350-L366 中的maybe_call_live_view_mount!/5正是用:telemetry.span([:phoenix, :live_view, :mount], metadata, fn - ... end)包裹了对mount/3的调用:telemetry.span( [:phoenix, :live_view, :mount], %{socket: socket, params: params, session: session, uri: uri}, fn - socket case Lifecycle.mount(params, session, socket) do {:cont, %Socket{} socket} when exported? - view.mount(params, session, socket) {_, %Socket{} socket} - {:ok, socket} end | handle_mount_result!({view, :mount, 3}) {socket, %{socket: socket, params: params, session: session, uri: uri}} end )可以看到:telemetry.span的第二个参数事件 metadata与回调返回值中的 metadata 保持一致从而保证:start、:stop、:exception三个事件携带完全相同的上下文信息便于按同一socket或params关联配对。LiveView 生命周期事件[:phoenix, :live_view, :mount, :start|:stop|:exception]由Phoenix.LiveView在mount/3回调前后派发覆盖断开连接时的静态挂载与建立连接后的 Live 挂载两种路径Phoenix.LiveView.Socket中的connected?/1可区分二者。三类事件的字段如下事件measurementmetadata:start%{system_time: System.monotonic_time}socket、params、session、uri:stop%{duration: native_time}socket、params、session、uri:exception%{duration: native_time}socket、kind、reason、params、session、urimetadata 各字段含义socketPhoenix.LiveView.Socket.t结构可从中读取view、transport_pid连接建立后为 pid静态挂载时为nil等状态params路由参数unsigned_params当 LiveView未挂载在路由器上例如以render/1方式直接渲染时该值为原子:not_mounted_at_routersession会话数据 mapuri当前请求/连接的完整 URI 字符串或nil。在 test/phoenix_live_view/integrations/telemetry_test.exs 中可以看到对:mount事件的完整断言静态挂载时socket.transport_pid为nilLive 挂载时则为真实 pidparams精确对应查询字符串解析结果/thermo?foobar得到%{foo bar}uri为完整 URL 而非仅路径。当mount/3抛出异常测试中通过/errors?crash_onconnected_mount触发时:exception事件的kind :error、reason为%RuntimeError{}且params、session、uri依然完整保留。[:phoenix, :live_view, :handle_params, :start|:stop|:exception]在handle_params/3回调执行前后派发通常由客户端发起导航push_patch、push_navigate或首次连接时触发。metadata 为%{ socket: Phoenix.LiveView.Socket.t, params: unsigned_params, uri: String.t() }与:mount事件不同handle_params事件不带session字段。底层实现在 lib/phoenix_live_view/utils.ex#L457-L482 的call_handle_params!/5中同样以:telemetry.span([:phoenix, :live_view, :handle_params], ...)包裹调用值得注意的是handle_params/3返回{:noreply, socket}之外的任何值都会抛出ArgumentError该异常同样会被:telemetry.span捕获并派发:exception事件。[:phoenix, :live_view, :handle_event, :start|:stop|:exception]由 LiveView 的handle_event/3回调触发即浏览器端任意一次phx-click、phx-submit、phx-change等事件经过 WebSocket 通道到达服务端后开始处理时。metadata 为%{ socket: Phoenix.LiveView.Socket.t, event: String.t(), params: unsigned_params }其中event是事件名字符串如saveparams是事件携带的表单/点击参数。实现位于 lib/phoenix_live_view/channel.ex#L567-L593 的view_handle_event/3Lifecycle.handle_event/3先对事件做前置处理例如lv:clear-flash这类内建事件会走专门分支随后再调用开发者定义的socket.view.handle_event/3整个流程包裹在:telemetry.span([:phoenix, :live_view, :handle_event], ...)中支持{:noreply, socket}与{:reply, reply, socket}两种返回。测试用例 test/phoenix_live_view/integrations/telemetry_test.exs#L143-L193 验证了成功与崩溃两条路径render_submit(view, :save, %{temp: 20})会先收到:startevent save、params %{temp 20}随后收到:stop而触发崩溃的事件则收到:exceptionkind :error、reason为捕获到的RuntimeError。[:phoenix, :live_view, :render, :start|:stop|:exception]在一次渲染开始前派发。需要特别说明的是一次渲染可能同时调用Phoenix.LiveView.render/1与Phoenix.LiveComponent.render/1回调因此这个事件覆盖 LiveView 与 LiveComponent 两种渲染场景。基础 metadata 为%{ socket: Phoenix.LiveView.Socket.t, force?: boolean, changed?: boolean }force?是否为强制渲染例如初始渲染changed?assigns 是否有变化导致需要重新渲染。当本次渲染属于组件渲染时metadata 还会额外附加三个字段%{ component: module, id: term, cid: integer }component是组件模块id是组件在模板中的 DOM id如chriscid是组件在 LiveView 进程内分配的整数标识符。实现位于 lib/phoenix_live_view/diff.ex#L252-L267只有当changed?为真时才会以:telemetry.span([:phoenix, :live_view, :render], metadata, ...)包裹渲染若 assigns 未变化changed?为假则直接执行渲染、不派发事件。测试 test/phoenix_live_view/integrations/telemetry_test.exs#L279-L310 通过组件渲染崩溃op: crash-render触发:badarith验证了:start与:exception的组件元数据component Phoenix.LiveViewTest.Support.StatefulComponent、id chris、cid为整数、force?为假。LiveComponent 生命周期事件[:phoenix, :live_component, :update, :start|:stop|:exception]在update/2或update_many/1回调执行前后派发。:start的 metadata%{ socket: Phoenix.LiveView.Socket.t, component: atom, assigns_sockets: [{map(), Phoenix.LiveView.Socket.t}] }注意这里的component类型标注为atom即组件模块名。:stop事件在:start基础上额外包含sockets字段%{ socket: Phoenix.LiveView.Socket.t, component: atom, assigns_sockets: [{map(), Phoenix.LiveView.Socket.t}], sockets: [Phoenix.LiveView.Socket.t] }sockets是更新完成后得到的更新过的 socket 列表。:exception事件的 metadata 与:start相同另加kind与reason。值得注意的细节一次update/2调用可能对应多次派发即一个:start事件可能覆盖对多个 socket 的调用这在 guides/server/telemetry.md 与源码 lib/phoenix_live_view/diff.ex#L308-L335 中均有体现——update_component/3以:telemetry.span([:phoenix, :live_component, :update], telemetry_metadata, ...)包裹Utils.maybe_call_update!/3而maybe_call_update!会优先选择组件导出的update_many/1见 lib/phoenix_live_view/utils.ex#L487-L497此时一次事件对应多个组件的批量更新。测试 test/phoenix_live_view/integrations/telemetry_test.exs#L312-L345 验证了assigns_sockets中每一项是{assigns_map, component_socket}二元组且:stop的sockets中的更新后 socket 与:start的组件 socket 不是同一结构updated_component_socket ! component_socket并保留了myself: cid。[:phoenix, :live_component, :handle_event, :start|:stop|:exception]与 LiveView 的handle_event对应由 LiveComponent 的handle_event/3回调触发。metadata 为%{ socket: Phoenix.LiveView.Socket.t, component: atom, event: String.t(), params: unsigned_params }比 LiveView 版本多出component字段用于标识是哪个组件处理了该事件。实现位于 lib/phoenix_live_view/channel.ex#L858 附近同样采用:telemetry.span([:phoenix, :live_component, :handle_event], ...)包裹。测试 test/phoenix_live_view/integrations/telemetry_test.exs#L220-L277 通过点击#chris元素触发transform事件断言component Phoenix.LiveViewTest.Support.StatefulComponent并在op: boom时捕获reason {:case_clause, boom}的:exception事件。[:phoenix, :live_component, :destroyed]组件被销毁后派发没有 measurement即空 map%{}metadata 为%{ socket: Phoenix.LiveView.Socket.t, component: atom, cid: integer(), live_view_socket: Phoenix.LiveView.Socket.t }与前几个事件不同它多出cid被销毁组件的标识与live_view_socket宿主 LiveView 的 socket因为此时组件 socket 可能已不可用。该事件不使用:telemetry.span/3而是直接通过:telemetry.execute([:phoenix, :live_component, :destroyed], %{}, metadata)派发见 lib/phoenix_live_view/channel.ex#L1703-L1708发生在delete_components/2遍历删除组件时。可以用它来统计组件销毁数量、回收资源或追踪组件生命周期。内置 LoggerLiveView 自带的遥测消费者LiveView 内部自带一个遥测消费者Phoenix.LiveView.Logger它在 LiveView 启动时自动安装默认将 8 个:start/:stop事件mount、handle_params、handle_event含 LiveView 与 LiveComponent 两个版本接入日志系统见 lib/phoenix_live_view/logger.ex#L47-L62def install do handlers %{ [:phoenix, :live_view, :mount, :start] __MODULE__.lv_mount_start/4, [:phoenix, :live_view, :mount, :stop] __MODULE__.lv_mount_stop/4, [:phoenix, :live_view, :handle_params, :start] __MODULE__.lv_handle_params_start/4, [:phoenix, :live_view, :handle_params, :stop] __MODULE__.lv_handle_params_stop/4, [:phoenix, :live_view, :handle_event, :start] __MODULE__.lv_handle_event_start/4, [:phoenix, :live_view, :handle_event, :stop] __MODULE__.lv_handle_event_stop/4, [:phoenix, :live_component, :handle_event, :start] __MODULE__.lc_handle_event_start/4, [:phoenix, :live_component, :handle_event, :stop] __MODULE__.lc_handle_event_stop/4 } for {key, fun} - handlers do :telemetry.attach({__MODULE__, key}, key, fun, %{}) end end它使用:telemetry.attach/4挂载处理函数日志默认级别为:debug且仅在connected?(socket)即 Live 连接建立后为真时输出因此静态渲染断开连接阶段不会产生 mount/handle 日志。开发者可以通过模块级配置按 LiveView 单独调整use Phoenix.LiveView, log: :debug # 覆盖默认日志级别 use Phoenix.LiveView, log: false # 关闭该 LiveView 的日志此外若启用了参数过滤Phoenix.LiveView.Logger会基于Phoenix.Logger的配置对日志中的参数做过滤见 lib/phoenix_live_view/logger.ex#L35-L38。上述行为均有对应测试覆盖见 test/phoenix_live_view/integrations/telemetry_test.exs#L348-L369。实战如何消费遥测事件telemetry是 Erlang/Elixir 生态的标准可观测性接口消费方式与任何 telemetry 事件一致用:telemetry.attach/4注册处理器。以统计 LiveView 事件处理耗时为例一个典型的最小处理器如下:telemetry.attach( my-app-lv-handle-event-duration, [:phoenix, :live_view, :handle_event, :stop], fn _event, %{duration: duration}, %{socket: socket, event: event}, _config - # 将耗时写入 Metrics / Prometheus / OpenTelemetry 等后端 MyApp.Metrics.record_lv_handle_event_duration(socket.view, event, duration) end, %{} )需要注意几点实践原则配对事件:start的 measurement 是system_time:stop/:exception的 measurement 是durationnative_time单位即System.monotonic_time的刻度通常为纳秒两者需按 metadata 中的socket关联才能计算“从开始到结束”的完整链路耗时。异常事件只订阅:stop会漏掉:exception场景监控告警应同时订阅:exception其kind/reason可直接用于错误归类。组件渲染判别:render事件若带component/id/cid字段即为组件渲染可按组件维度拆分性能数据。批量更新语义:live_component, :update事件一次可能覆盖多个 socketassigns_sockets列表统计次数时不要假设每次事件只有一个组件更新。仓库的 test/phoenix_live_view/integrations/telemetry_test.exs 中使用的attach_telemetry/1测试辅助函数来自 test/support/telemetry_test_helpers.ex也是用:telemetry.attach实现的可作参考。由于这些事件遵循:telemetry.span/3的标准语义也可以直接接入如telemetry_metrics、opentelemetry_telemetry等现成库将 LiveView 的挂载、事件、渲染耗时统一纳入应用级指标与追踪系统。事件速查表事件阶段measurementmetadata 关键字段[:phoenix, :live_view, :mount, ...]挂载system_time/durationsocket、params或:not_mounted_at_router、session、uri、异常时kind/reason[:phoenix, :live_view, :handle_params, ...]URL 参数处理system_time/durationsocket、params、uri、异常时kind/reason[:phoenix, :live_view, :handle_event, ...]客户端事件处理system_time/durationsocket、event、params、异常时kind/reason[:phoenix, :live_view, :render, ...]渲染含组件渲染system_time/durationsocket、force?、changed?、组件渲染时component/id/cid、异常时kind/reason[:phoenix, :live_component, :update, ...]组件更新system_time/durationsocket、component、assigns_sockets、:stop另含sockets、异常时kind/reason[:phoenix, :live_component, :handle_event, ...]组件事件处理system_time/durationsocket、component、event、params、异常时kind/reason[:phoenix, :live_component, :destroyed]组件销毁无socket、component、cid、live_view_socket围绕这套事件体系你可以为 LiveView 应用搭建完整的可观测性链路用:mount系列监控挂载成功率与耗时、用:handle_event系列定位慢交互与异常事件、用:render系列区分force?/changed?量化渲染开销、用:live_component系列追踪组件级更新与销毁。这些事件均来自当前仓库源码的实际派发点lib/phoenix_live_view/utils.ex、lib/phoenix_live_view/channel.ex、lib/phoenix_live_view/diff.ex并在 test/phoenix_live_view/integrations/telemetry_test.exs 中有系统性的行为验证你可以放心地在生产环境依赖这些事件。赞分享后端Web框架WebSocket【免费下载链接】phoenix_live_viewRich, real-time user experiences with server-rendered HTML项目地址https://gitcode.com/gh_mirrors/ph/phoenix_live_view点击查看免费下载相关推荐Cypress 内部遥测Telemetry机制解析基于 OpenTelemetry 的 packages/telemetry 实践指南Cypress 内部遥测Telemetry机制解析基于 OpenTelemetry 的 packages/telemetry 实践指南 导读 packa测试质量保障前端接口测试微信防撤回突然失效RevokeMsgPatcher 3步修复 weixin.dll 新文件微信防撤回突然失效RevokeMsgPatcher 3步修复 weixin.dll 新文件 你是不是也发现微信防撤回突然失效了坑在这微信安装目录里的核心文搜索引擎全文检索可观测性数据分析SurrealDB 遥测实战指南基于 OpenTelemetry 的 Metrics 与 Traces 可观测性搭建SurrealDB 遥测实战指南基于 OpenTelemetry 的 Metrics 与 Traces 可观测性搭建 导读 SurrealDB 服务器内置了基数据库后端分布式数据库文档数据库图数据库嵌入式数据库KV存储上一篇打破网盘下载速度限制9大平台直链解析工具的本地化革命下一篇go.yaml.in/yaml/v3 完全指南Go 语言 YAML 1.1/1.2 兼容编解码与 Node API 实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考