尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Erlang/OTP Event Tracer(ET)深度指南:用 et_collector 与 et_viewer 构建可视化序列图事件追踪

发布时间:2026/9/23 19:54:30

资讯中心
01
ARTICLE

Erlang/OTP Event Tracer(ET)深度指南:用 et_collector 与 et_viewer 构建可视化序列图事件追踪

Erlang/OTP Event Tracer(ET)深度指南:用 et_collector 与 et_viewer 构建可视化序列图事件追踪
Erlang/OTP Event TracerET深度指南用 et_collector 与 et_viewer 构建可视化序列图事件追踪【免费下载链接】otpErlang/OTP项目地址: https://gitcode.com/gh_mirrors/ot/otpETEvent Tracer是 Erlang/OTP 自带的轻量级分布式追踪工具它把 Erlang 运行时产生的 trace 数据、或应用代码中显式上报的事件统一采集进一个事件仓库并渲染成可交互的序列图sequence chart。本文基于 OTP 仓库中lib/et的实现与文档讲解 ET 的两大核心组件et_collector事件仓库与et_viewer图形查看器、过滤器Filter与字典机制、Trace Client 接入、全局追踪global tracing以及两套图形窗口的完整操作手册。读完本文你将能够自己启动 ET、上报/接入各类事件源、编写自定义视图过滤器并把 ET 嵌入到多节点系统的实时追踪中。一、整体架构Collector 与 Viewer 两大组件从 et.erl 模块头注释 可以清晰看到ET 应用由以下几部分构成et_collector事件采集与后端存储。它是一个gen_server进程接收 trace 数据、经过过滤器后按时间戳有序存放并为多个订阅进程如多个 Viewer提供字典服务与组通信et_viewer图形化序列图查看器。它连接到一个 Collector定期轮询获取新事件并在显示前对每个事件应用用户自定义过滤器et_contents_viewer单个事件的细节查看窗口通常由et_viewer启动et_selector底层库模块负责把细节级别detail level翻译成 Erlang trace patternmatch spec并实现默认过滤器——把原始 Erlang trace 数据转换成#event{}记录et面向业务应用的极轻量上报 APItrace_me/4,5等。文档中的架构要点是一个 Collector 可以作为多个 Viewer 的共享后端存储每个 Viewer 可以对同一份 trace 数据展示不同的视角例如不同的过滤器和缩放比例。Collector 与 Viewer 之间的接口是公开的因此理论上可以编写其它类型的 Viewer但本文聚焦et_viewer的标准用法。1.1 启动et_viewer:start/1主要启动函数是et_viewer:start/1默认情况下它会同时启动一个et_collector和一个et_viewer% erl -pa et/examples Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false] Eshell V5.7.4 (abort with ^G) 1 {ok, Viewer} et_viewer:start([]). {ok,0.40.0}1.2 事件如何流动轮询 report_event/6Viewer 会定期轮询其 Collector获取更多待显示的事件。事件本身可以由任何进程通过et_collector:report_event/6上报例如2 Collector et_viewer:get_collector_pid(Viewer). 0.39.0 3 et_collector:report_event(Collector, 60, my_shell, mnesia_tm, start_outer, 3 Start outer transaction), 3 et_collector:report_event(Collector, 40, mnesia_tm, my_shell, new_tid, 3 New transaction id is 4711), 3 et_collector:report_event(Collector, 20, my_shell, mnesia_locker, try_write_lock, 3 Acquire write lock for {my_tab, key}), 3 et_collector:report_event(Collector, 10, mnesia_locker, my_shell, granted, 3 You got the write lock for {my_tab, key}), 3 et_collector:report_event(Collector, 60, my_shell, do_commit, 3 Perform transaction commit), 3 et_collector:report_event(Collector, 40, my_shell, mnesia_locker, release_tid, 3 Release all locks for transaction 4711), 3 et_collector:report_event(Collector, 60, my_shell, mnesia_tm, delete_transaction, 3 End of outer transaction), 3 et_collector:report_event(Collector, 20, my_shell, end_outer, 3 Transaction returned {atomic, ok}). {ok,{table_handle,0.39.0,16402,trace_ts, #Funet_collector.0.62831470}}注意report_event/6的返回值第一次调用以 Collector 的 pid 作为句柄之后可以直接复用返回的table_handle记录它内嵌了 Ets 表标识和过滤器 fun从而省去每次向 Collector 进程请求句柄的往返开销见下文源码走读。这段示例实际上是模拟了一次 Mnesia 本地表写事务产生的进程事件真实事务等价于mnesia:transaction(fun() - mnesia:write({my_tab, key, val}) end).在 et_demo.erl 的sim_trans/0,1中可以看到同样的事件序列被封装为可复用函数。有了这批事件图形界面中即可看到序列图在序列图中参与事件的**演员actor**显示为带名字的竖直条。你可以按住鼠标左键拖动某个 actor 的名字标签并放到其它位置从而调整 actor 的左右排列顺序一个事件既可能是单个 actor 的动作蓝色文字标签也可能涉及两个 actor此时会渲染成从一个 actor 指向另一个 actor 的箭头红色文字标签。单击事件标签文字或箭头按下并松开鼠标左键会弹出Contents Viewer窗口展示该事件的细节二、事件记录#event{} 的结构ET 内部统一使用#event{}记录作为事件的中介格式其字段定义在 et.hrl字段含义detail_level细节级别0..100。噪声noise事件的值偏高关键事件值偏低trace_tstrace 数据被生成的时间戳若原始 trace 数据未携带时间戳则等于event_tsevent_ts事件记录被创建解析的时间戳from来源 actor例如消息的发送方to目标 actor例如消息的接收方label事件的简短摘要标签contents事件的全部细节建议使用[{Key, Value}]键值对列表细节级别的上下限在 et_internal.hrl 中定义为0..100。三、过滤器Filter与字典机制3.1 过滤器接口与 lists:filtermap/2 一致ET 在各种场景中大量使用命名过滤器。一个事件 trace 过滤器是一个 Erlang fun接收 trace 数据作为输入返回其可能的修改版本filter(TraceData) - false | true | {true, NewEvent} TraceData Event | erlang_trace_data() Event #event{} NewEvent #event{}其语义与标准库lists:filtermap/2的过滤函数完全相同false静默丢弃该 trace 数据truetrace 数据本身已经是#event{}记录原样保留{true, NewEvent}用NewEvent替换原始 trace 数据。这样既可以去噪丢弃不需要的事件也可以改变事件在视图中的呈现方式。3.2 Collector Filter 的特别之处第一个接触到 trace 数据的过滤器是Collector Filter字典中名字为all的那个过滤器见 et_internal.hrl。当事件通过et_collector:report/2或report_event/5,6上报时首先会向 Collector 进程发送消息以获取一个句柄其中包含 Collector Filter Fun 和 Ets 表标识随后应用该过滤器若返回true或{true, NewEvent}事件即被写入 Ets 表。作为优化后续report调用可以直接使用这个句柄而不再向 Collector 进程请求。所有过滤器无论注册在 Collector 还是 Viewer 中都必须能处理#event{}记录作为输入而 Collector Filter名为all略有特殊——它的输入还可能是原始的 Erlang trace 数据。3.3 Collector 的字典服务与订阅传播Collector 内部维护一个基于 key/value 的字典用于存放过滤器等条目。字典的每次更新都会被传播给所有订阅进程当某个 Viewer 启动时它会自动注册为字典更新的订阅者。相关 API实现在 et_collector.erlet_collector:dict_insert(CollectorPid, Key, Val)插入条目并向所有订阅者发送{et, {dict_insert, Key, Val}}消息若是新订阅者注册会先把已存在的全部条目逐一发送给它et_collector:dict_lookup(CollectorPid, Key)查询条目et_collector:dict_delete(CollectorPid, Key)删除条目并广播et_collector:dict_match(CollectorPid, Pattern)按 Ets 匹配模式批量查询。每个 Viewer 同时只有一个激活过滤器从 Collector 取回的所有事件都会流过该过滤器编写巧妙的过滤器即可自定义事件在查看器中的形态。3.4 实战示例mgr_actors 过滤器下面这个过滤器来自 et_demo.erl它把 actor 名字mnesia_tm、mnesia_locker替换为语义化的trans_mgr、lock_mgr并把原始值备份到 contents 中其余字段保持不变mgr_actors(E) when is_record(E, event) - Actor fun(A) - case A of mnesia_tm - trans_mgr; mnesia_locker - lock_mgr; _ - A end end, {true, E#event{from Actor(E#event.from), to Actor(E#event.to), contents [{orig_from, E#event.from}, {orig_to, E#event.to}, {orig_contents, E#event.contents}]}}.把它插入正在运行的 Collector4 Fun fun(E) - et_demo:mgr_actors(E) end. #Funerl_eval.6.13229925 5 et_collector:dict_insert(Collector, {filter, mgr_actors}, Fun). ok此时所有 Viewer 的Filter菜单都会出现一个新条目mgr_actors。选中它会弹出一个新的 Viewer 窗口用该过滤器渲染同一份 trace 数据如果想查看事件的细枝末节可以单击事件打开Contents Viewer该窗口内同样有过滤器菜单允许从其它视角检视同一个事件。例如点击new_tid事件会弹出以mgr_actors视角展示该事件的 Contents Viewer在 Filters 菜单中选择all则会弹出以 Collector 视角即原始视图展示同一事件的窗口四、Trace clients把各种数据源接入 Collector除了手动调用report_event/5,6ET 还提供了一系列现成的 trace client把各种来源的 trace 数据转发进 Collector文件存取Collector 中托管的事件可以保存到文件之后通过 Viewer 的File菜单中的save/load或通过et_collectorAPI 重新载入。实现上文件由disk_log承载save_event_file/3支持existing | write | append事件范围/写模式与keep | clear写完后是否清空事件表等选项load_event_file/2按 chunk 读取并逐条report见 et_collector.erlErlang 内建 trace可以利用 Erlang 虚拟机内建的 trace 机制对运行中的系统做实时追踪trace 数据可输出到文件或端口。相关接口参见erlang:trace/3、erlang:trace_pattern/3、dbg与ttb对应的 trace clientet_collector:start_trace_client/3会启动能读取上述 Erlang trace 文件/端口格式的客户端并把数据重定向到 Collector实现中对file类型会等待读到end_of_trace后返回file_loaded对ip等端口类型返回{trace_client_pid, Pid}。默认的 Collector Filter 负责把原始 Erlang trace 数据格式转换为#event{}记录。如果希望走不同的转换路径可以完全自己编写 Collector Filter但更省力的做法是先调用et_selector:parse_event/2应用默认过滤逻辑再对其输出做二次加工et_selector.erl 中parse_event/2即默认过滤器的实现核心。反过来如果 trace 数据来自任何自有格式文件、数据库、消息流……你完全可以编写自定义 trace client 读取数据并喂给 Collector——只要在调用report/2之前把数据转成#event{}或替换默认 Collector Filter 来完成转换。五、全局追踪Global tracing一键铺开多节点 trace在多个节点上手工搭建 Erlang tracer、再把 trace client 接到各 tracer 的端口上非常繁琐。ET 为此提供了全局追踪能力启用后et_collector进程会监控 Erlang 节点每当有节点接入nodeup就在新节点上自动启动一个 Erlang tracer通过 port tracer同时在 Collector 所在节点启动对应的 trace client把 trace 事件自动转发回 Collector激活方式给et_collector或et_viewer设置布尔参数trace_global true并发匿名 Collector 的数量不受限制但全局 Collector 全局唯一——因为它的名字注册在global中源码中trace_global为 true 时以{global, ?MODULE}注册见 et_collector.erl。可通过et_collector:get_global_pid/0获取其 pid。5.1 et:trace_me/4,5为应用埋点的免费函数为了进一步简化追踪可以借助et:trace_me/4,5系列函数。它们设计为从其它应用的关键位置调用trace_me(DetailLevel, From, To, Label, Contents) - hopefully_traced从 et.erl 的实现 可见这些函数极其轻量——除了返回原子hopefully_traced之外什么都不做。它们存在的意义就是被 trace由于调用方显式提供了#event{}各字段的值默认 Collector Filter 无需任何用户自定义过滤器就能自动生成定制的事件记录。相关说明trace_me/4等价于trace_me/5且From、To都设为同一个 actorphone_home/4,5与report_event/4,5目前为向后兼容保留均委托给trace_meDetailLevel取 0..100 的整数Label建议用原子作简短摘要Contents建议用[{Key, Value}]列表以方便后续加工正常运行时这些调用几乎零开销需要追踪时可以显式对它们开启 trace或组合使用trace_global与trace_pattern。5.2 trace_pattern控制全局细节级别设置trace_pattern后它会自动在所有已连接节点上激活。它的好处是提供了一种非常简单的方式来压低产生的 trace 数据量你可以在源头就控制追踪的细节级别。这一点与 Viewer 中的Detail Level滑块互补——滑块只控制显示哪些事件而如果把trace_pattern的细节级别调低大量 trace 数据根本不会生成自然也就不会经 socket 发到 trace client、存进 Collector。从 et_selector.erl 的 make_pattern/1 可以看到细节级别如何翻译成 match specmin空 match spec[]即关闭对et:trace_me/4,5的追踪max匹配所有调用整数X匹配所有detail level X的调用match spec 条件{, $1, DetailLevel}。Collector 的change_pattern/2则通过rpc:multicall把新 pattern 同步到所有 trace 节点et_collector.erl。5.3 实机演示追踪真实的 Mnesia 事务et_demo提供了两个级别的演示sim_trans/0是纯模拟手动report_event而live_trans/0则做真实追踪启动带trace_global的 Viewer、创建 Mnesia 表、调用trace_mnesia/0用dbg对 Mnesia 模块设置调用追踪并开启send/receive/procs/timestamp标志然后执行一次真实事务et_demo.erl。et_demo:start/1的默认选项也展示了常用的 Viewer 配置Options [{trace_global, true}, {parent_pid, undefined}, {max_actors, infinity}, {max_events, 1000}, {active_filter, module_as_actor}], et_viewer:start_link(filters() Options ExtraOptions).六、et_viewer 窗口菜单与快捷键速查et_viewer中几乎所有功能都有键盘快捷键快捷键显示在菜单条目后的括号中。例如按键r等价于选择Viewer-Refresh。6.1 File 菜单条目作用Clear all events in the Collector删除 Collector 中存储的全部事件并通知所有相连的 ViewerLoad events to the Collector from file从文件向 Collector 装载事件并通知所有相连 ViewerSave all events in the Collector to file把 Collector 中全部事件保存到文件Print setup编辑打印设置纸张、布局Print current page打印当前页的事件页大小取决于所选纸张类型Print all pages打印全部事件Close this Viewer关闭本 Viewer 窗口保留其它 Viewer 窗口与 Collector 进程Close other Viewers, but this保留本 Viewer 及其 Collector关闭连接同一 Collector 的其它 ViewerClose all Viewers and the Collector关闭 Collector 及所有相连 Viewer6.2 Viewer 菜单条目作用First/Last本 Viewer 滚动到 Collector 中的第一个/最后一个事件Prev/Next本 Viewer 向后/向前翻一页Refresh快捷键r清空本 Viewer 并重新从 Collector 读取事件Up/Down向后/向前滚动少量事件Display all actors.重置隐藏/高亮 actor 的设置6.3 Collector 菜单与 Viewer 菜单功能相同但作用于所有ViewerFirst/Last/Prev/Next让所有 Viewer 滚动Refresh清空所有 Viewer 并重新读取。6.4 Filters and scaling 菜单条目作用ActiveFilter ()以当前激活过滤器和缩放比例新开一个 Viewer 窗口ActiveFilter ()以当前激活过滤器、更大缩放比例新开 Viewer 窗口ActiveFilter (-)以当前激活过滤器、更小缩放比例新开 Viewer 窗口all (0)以 Collector Filter 作为激活过滤器新开 Viewer查看 Collector 中全部事件AnotherFilter (2)字典中插入的更多过滤器会依次出现在此菜单第二个过滤器快捷键为 2第三个为 3依此类推条目按名字排序6.5 滑块与单选按钮控件作用Hide FromTo勾选后隐藏所有 from-actor 等于 to-actor 的事件这类事件又称动作 actionsHide (excluded actors)勾选后隐藏所有 actor 被标记为排除的事件。被排除的 actor 正常显示时名字带圆括号()Detail level控制 Viewer 的分辨率只显示 detail level小于滑块值的事件默认 100 最大显示全部6.6 其它交互特性垂直滚动鼠标滚轮与上下方向键小幅滚动PageUp/PageDown、Home/End 大幅滚动显示事件细节在事件标签或箭头上单击鼠标左键弹出 Contents Viewer 显示事件内容高亮 actor切换在 actor 名字标签上单击左键名字会被方括号[]括起。当有一个或多个 actor 被高亮时只显示与这些 actor 相关的事件其余全部隐藏排除 actor切换在 actor 名字标签上单击右键名字被圆括号()括起。被排除后与该 actor 相关的所有事件被隐藏若勾选了Hide (excluded actors)连名字标签和对应竖线也会被隐藏移动 actor在 actor 名字标签上按住鼠标左键拖动到新位置松开即可显示全部 actor按键a重置隐藏/高亮设置。七、Contents Viewer 窗口单事件检视与搜索7.1 File 菜单Close关闭本窗口Save把本窗口内容保存到文件。7.2 Filters 菜单ActiveFilter以相同激活过滤器新开一个 Contents Viewer 窗口AnotherFilter (2)字典中新增的过滤器依次出现在此菜单编号 2、3……按名字排序。7.3 Hide 菜单Hide actor in viewer已知 actor 在 Viewer 中以命名竖条显示隐藏 actor 后其竖条被移除Viewer 自动刷新。注意只有当max_actors阈值已到达时隐藏 actor 才真正有意义——此时被隐藏的 actor 会以UNKNOWN形式显示若阈值未到达该 actor 仍会以竖条重新出现在 Viewer 中Show actor in viewer把 actor 加为 Viewer 的已知 actor并赋予其独立竖条。7.4 Search 菜单Forward from this event把当前事件设为 Viewer 的第一个事件并切换到正向搜索模式该事件的 actorfrom、to 或两者会被加入选定 actor 列表Reverse from this event把当前事件设为 Viewer 的第一个事件并进入反向搜索模式注意反向模式下事件按倒序显示Abort search. Display all无论是否正在搜索切换到显示全部事件的模式并中止搜索。八、配置参数速查事件排序与 Collector 选项Collector 中 Ets 表里的事件按时间戳排序用哪个时间戳由event_order参数控制见 et_collector.erl 的start_link/1注释与 make_key/2 的实现trace_ts默认按 trace 数据被生成的时间排序event_ts按 trace 数据被解析转换为#event{}的时间排序。若 trace 数据缺少时间戳trace_ts会取event_ts的值。et_collector:start_link/1支持的选项与默认值汇总如下选项默认值说明{parent_pid, Pid}self()Collector 链接的父进程{event_order, trace_ts \| event_ts}trace_ts事件排序时间戳{dict_insert, {filter, all}, Fun}默认et_selector:parse_event/2设置 Collector Filter可替换/追加命名过滤器{dict_insert, {subscriber, Pid}, Val}—注册字典订阅者{dict_insert, Key, Val}/{dict_delete, Key}—字典读写{trace_client, {event_file, File}}—启动文件 trace client{trace_client, {dbg_trace_type(), Params}}—启动 dbg 格式 trace clientfile/ip/follow_file 等{trace_global, boolean()}false是否启用全局追踪{trace_pattern, Pattern}undefined全局 trace patternmin/max/整数或 match spec{trace_port, integer()}4711全局追踪使用的端口基址冲突时自动递增{trace_max_queue, integer()}50trace 端口队列上限Viewer 侧常用选项et_demo:start/1可作参考还包括max_actors如infinity、max_events、active_filter、hide_actions、title等。九、源码走读Collector 内部是如何工作的从 et_collector.erl 的实现可以确认文档描述的全部机制存储结构init_tables/1创建两张ordered_set类型的公共 Ets 表——et_events事件表与et_dict字典表键位置均为 1L1128-L1131。ordered_set保证事件可以按时间戳键前后迭代上报路径report/2先从 Collector 获取table_handle内含事件表 id、event_order与过滤器 fun随后应用过滤器false直接丢弃true/{true, NewEvent}则用make_key/2生成排序键后ets:insert若返回其它异常值会构造一个bad_filter事件存入L474-L524句柄优化get_table_handle每次从字典中读取名为all的 Collector Filter 打包进句柄L1188-L1194这样后续report无需再与 Collector 进程同步交互订阅通知字典插入/删除会向订阅者广播{et, Msg}新增订阅者会先收到全部既有条目再收到新条目Collector 还会定期check_size/1当事件表大小变化时向订阅者发送{more_events, Size}L1526-L1536这正是 Viewer轮询到新事件的通知机制遍历接口iterate/3,5支持从first/last或任意事件键出发正向/反向遍历Limit为正整数、infinity、负整数或-infinityL888-L1034全局追踪init_global/1在trace_global为 true 时启动本地 dbg tracer、net_kernel:monitor_nodes(true)并枚举已有节点handle_info({nodeup, Node}, ...)通过rpc:call在远端节点启动monitor_trace_port/2port tracer再在本地start_trace_client(self(), ip, {Host, Port})建立消费端并在该节点上应用 trace patternL1133-L1146、L1307-L1383。默认的全局 trace pattern 为max。十、进一步探索完整示例与过滤器集合et_demo.erlsim_trans模拟、live_trans实机 Mnesia 追踪、filters/0内置过滤器族事件记录结构et.hrl上报 APIet.erl、采集存储 APIet_collector.erlpattern 与默认转换et_selector.erl图形界面实现et_wx_viewer.erl 与 et_wx_contents_viewer.erl。ET 的价值在于把事件采集—存储—过滤—可视化整条链路做成标准件业务代码埋点近乎零成本多节点全局追踪一键开启而过滤器机制又让同一份 trace 数据可以衍生出无数种观察视角——这正是调试分布式系统、分析 Mnesia 等内部协议行为时最实用的工具箱。【免费下载链接】otpErlang/OTP项目地址: https://gitcode.com/gh_mirrors/ot/otp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。