从生成器克隆 Babeltrace 事件以进行随机访问遍历

Cloning Babeltrace events from generator for random-access traversal

我正在尝试使用 Babeltrace 1 检查 LTTNG 事件日志中的特定事件链。LTTNG 日志是使用 Babeltrace 集合加载的:

import babeltrace

my_collection = babeltrace.TraceCollection()
my_collection.add_traces_recursive(trace_path, 'ctf')

我正在寻找的特殊事件与正在发生的正常事件几乎没有区别,除了一旦链已经开始就会有一些额外的事件。所以我需要寻找这些特殊事件,然后搜索 backward 以获取实际开始。

问题是 Babeltrace 只让我在事件列表中前进。简单的解决方案似乎是在我自己的列表中创建事件的克隆:

events = [e for e in my_collection.events]

问题在于列表中的所有事件现在都引用了 last 事件。这表明 Babeltrace 一遍又一遍地重复使用同一个对象,而生成器仅 returns 对这个单个对象的引用。

我试过使用copy.copy:

events = [copy.copy(e) for e in my_collection.events]

这没有帮助,copy.deepcopy 根本不起作用。我也试过 itertools.tee:

events = list(itertools.tee(my_collection.events))

但是这个 returns 一个 _tee 对象的列表不能用作适当的事件对象。

有没有办法使用 Babeltrace 事件收集生成器向后搜索?或者有没有办法正确克隆事件对象来创建我自己的列表?

这里是 Babeltrace 的共同维护者。

事实上,Babeltrace 1 为每个迭代步骤重复使用相同的事件记录对象。这意味着您不能让“旧”事件记录保持活动状态,因为它的数据在幕后发生变化。

Babeltrace 1 的 Python 绑定是库对象的基本包装器。这意味着同样的约束适用。此外,Babeltrace 1 不提供任何事件记录对象复制功能,因此 copy.copy() 之类的东西只会复制内部指针,然后会出现同样的问题。

出于性能原因,Babeltrace(1 和 2)迭代器不能倒退(更多信息见下文)。

我看到的唯一解决方案是制作您自己的事件记录复制功能,将需要的内容保留在您自己的另一个实例中 class。毕竟,你可能只需要事件记录的名称、时间戳和一些一级字段。

但 Babeltrace 2 正是您要找的,尤其是因为我们不再维护 Babeltrace 1(critical/security 错误修复除外)。

Babeltrace 2 提供了一个丰富且一致的 C API,其中许多对象都有一个引用计数,因此可以随意使用。 Babeltrace 2 Python 绑定包装了这个 C API 以便您可以从相同的功能中受益。

虽然 C API 文档 is complete, unfortunately the Python bindings one is not. However, we have this,但至少显示了一些示例以帮助您入门。

关于您的评论:

since it seems the events are a kind of linked list where one could walk backward

不,你不能。这是为了适应某些跟踪格式的限制,特别是 CTF(LTTng 使用的格式)。 CTF数据包是一系列序列化的二进制事件记录:要解码事件记录N,需要先解码事件记录N - 1,然后很快。一个 CTF 数据包可以包含数千个这样的连续事件记录,CTF 数据流可以包含数千个数据包,一个 CTF 跟踪可以包含许多数据流。知道这一点,就没有合理的方法来存储所有编码的 CTF 事件记录的偏移量,以便您可以在没有重对象副本的情况下向后迭代。

然而,使用 Babeltrace 2,您可以做的是保留您需要的特定事件记录对象,而无需任何副本。

将来,我们想要一种复制消息迭代器的方法,复制其所有状态以及在幕后继续执行所需的内容。这将使保留“检查点迭代器”成为可能,以便您可以在由于某种原因无法一次性执行分析时返回到以前的事件记录。

请注意,您还可以让消息迭代器查找特定的时间戳,但“快速”查找在 ctf 插件中尚未实现(迭代器查找消息序列的开头和然后前进直到它到达请求的时间戳,这是低效的)。