[LTTng实操]------开发Babeltrace 2插件

25 篇文章 6 订阅

一、分析提供的示例

1、source

头文件

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <babeltrace2/babeltrace.h>

使用声明插件和类的宏 于 C文件末尾

示例
/* Mandatory */
BT_PLUGIN_MODULE();
 
/* Define the `dust` plugin */
BT_PLUGIN(dust);
 
/* Define the `input` source component class */
BT_PLUGIN_SOURCE_COMPONENT_CLASS(input, dust_in_message_iterator_next);
 
/* Set some of the `input` source component class's optional methods */
BT_PLUGIN_SOURCE_COMPONENT_CLASS_INITIALIZE_METHOD(input, dust_in_initialize);
BT_PLUGIN_SOURCE_COMPONENT_CLASS_FINALIZE_METHOD(input, dust_in_finalize);
BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD(input,
    dust_in_message_iterator_initialize);
BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD(input,
    dust_in_message_iterator_finalize);
引用原型
BT_PLUGIN_SOURCE_COMPONENT_CLASS
#define BT_PLUGIN_SOURCE_COMPONENT_CLASS	(	 	_name,
 	_message_iterator_class_next_method 
)		

Alias of BT_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID() with the _plugin_id parameter set to auto, the _component_class_id parameter set to _name, and the _name parameter set to a string version of _name.

参数1:
本例中输入 input 但是没加字符串双引号,应该是内部进行了转换。

参数2:
函数名(也可以说是函数指针,入口地址)。

按照如下格式实现method。


typedef bt_message_iterator_class_next_method_status(* bt_message_iterator_class_next_method) (bt_self_message_iterator *self_message_iterator, bt_message_array_const messages, uint64_t capacity, uint64_t *count)

同理,另外几个初始化和反初始化方法也是这个套路。

3、sink

头文件

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <babeltrace2/babeltrace.h>

插件定义

/* Mandatory */
BT_PLUGIN_MODULE();
 
/* Define the `epitome` plugin */
BT_PLUGIN(epitome);
 
/* Define the `output` sink component class */
BT_PLUGIN_SINK_COMPONENT_CLASS(output, epitome_out_consume);
 
/* Set some of the `output` sink component class's optional methods */
BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD(output,
    epitome_out_initialize);
BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(output, epitome_out_finalize);
BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD(output,
    epitome_out_graph_is_configured);

可以看到:

示例的sink类 没有设计初始化参数,所以只有component class 的初始化和反初始化方法。没有之前的source类的参数初始化方法。

多了一个专用的BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD。这个是在graph去run的时候调用的方法。

BT_PLUGIN_SINK_COMPONENT_CLASS

参数模块类名和consume方法。

  • bt_component_class_sink_consume_method
    typedef bt_component_class_sink_consume_method_status(* bt_component_class_sink_consume_method) (bt_self_component_sink *self_component)

处理一个message batch,实现中是处理一个message array。

在 bt_graph_run() 或 bt_graph_run_once() 中调用,以使sink组件使用和处理消息。 此方法通常从一个(或多个)上游消息迭代器获取一个消息批处理。如果需要,您可以自由地获取多批消息(多个渠道);但是,请记住,Babeltrace 2 项目建议此方法的执行速度足够快,以免阻止在同一线程上运行的交互式应用进程。

在您认为是长时间阻塞操作期间,项目建议您定期检查是否被bt_self_component_sink_is_interrupted() 打断。当您这样做时,您可以返回BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN或BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR,具体取决于您以后继续当前操作的能力。

如果需要block线程,可以改为通过返回BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN向bt_graph_run() 或 bt_graph_run_once() 调用方报告稍后重试。

如果接收器组件已完成使用和处理,请从此方法返回BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END。如果其他接收器组件仍在使用中,则trace graph可以在以后继续运行。 在此方法中,不能添加具有 bt_self_component_sink_add_input_port() 的输入端口。 在 sink 组件类创建时使用 bt_component_class_sink_create() 强制设置。

BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD

被调用处
在 bt_graph_add__component() 函数(参见graph)中调用以初始化您的组件。
接受初始化参数
在此方法中,您会收到传递给 bt_graph_add__component() 函数的初始化参数和初始化方法数据。
设置初始port
在此方法中,您可以使用 bt_self_component_source_add_output_port()、bt_self_component_filter_add_input_port()、bt_self_component_filter_add_output_port() 或 bt_self_component_sink_add_input_port() 向组件添加初始端口。
配置在构建graph时、动态增加port的method
您还可以在输入端口连接和输出端口连接方法中添加端口。
You can also add ports in the input port connected and output port connected methods.
借出自己使用的数据
您可以使用 bt_self_component_set_data() 创建用户数据并将其设置为 self 组件的用户数据。
使能finalization method
如果您从此方法返回 BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK,那幺当您的组件完成时,将调用您的组件的完成方法(如果存在)。使用 bt_component_class_source_set_initialize_method()、bt_component_class_filter_set_initialize_method() 和 bt_component_class_sink_set_initialize_method() 设置此可选方法。

BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD

调用以完成组件,即允许您销毁/释放/完成您拥有的任何用户数据(使用bt_self_component_get_data()获得的数据)。

Babeltrace 2 库没有确切地指定何时调用此方法,但保证在销毁组件之前调用此方法。

对于源组件和过滤器组件,库保证在所有组件的消息迭代器完成后调用此方法。

如果组件的初始化方法之前返回了错误状态码,则不会调用此方法。

在此方法中,您不能: 添加端口。使用任何消息迭代器。

使用 bt_component_class_source_set_finalize_method()、bt_component_class_filter_set_finalize_method() 和 bt_component_class_sink_set_finalize_method() 设置此可选方法。

BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD

只在最开始调用一次?
对于给定的跟踪处理图,第一次调用 bt_graph_run() 或 bt_graph_run_once() 以通知您的接收器组件该图现在已配置。

功能
在此方法中,可以在接收器组件的输入端口上创建消息迭代器。您还可以操作这些消息迭代器,例如获取和处理初始消息或创建它们。

此方法在调用组件的初始化方法后调用。不能在初始化方法中创建消息迭代器。 在此方法中,不能添加具有 bt_self_component_sink_add_input_port() 的输入端口。 使用 bt_component_class_sink_set_graph_is_configured_method() 设置此可选方法。

二、经验总结

开发插件,必须会涉及到比较细节的API和数据结构的使用。

这个时候,光看API Reference可能是不够的,一来是太多了。二来,写API文档的人很容易让读者产生歧义。也就是可能让人误解。

babeltrace是开源的,里面提供了三类插件各一个例子可以参考。

当然这几个例子内容很少,是远远不够的。

在这之后,我又去参考了提供的官方插件的源码,因为我需要自制sink插件,所以参考了pretty。在里面找到了提取时间戳的API使用。

当然,结果出乎我的意料。我对API Document的理解出现了偏差。

我根据描述,clock snapshot是 event occur的时候的时间。所以我认为可能这个clock 和 clock class是针对bebeltrace内部转换产生message的时间戳。可能是用于自己系统内部监控或者优化的。因为文档里说,这个clock属于 stream。而 event message引用stream 的clock生成快照。

但是看了代码里的调用,才发现,原来这个就是所谓的event 的时间戳。是这个event 在被监控程序中产生的时候,植入的。那也就是说,这个东西就是我需要的,而不是去读取field来获取。所以说之前一直没有找到。

下面总结一些概念:

1、插件和Component class development

在写插件的过程中,发现有另外一组不是插件声明宏的形式的API。和插件声明宏的作用重叠很大。

多处于Component class development里。比如添加消息迭代器的next方法。或者添加初始化、反初始化方法。

根据我的理解,可能插件宏专用于制作插件。而class的自制,不一定是和插件一起用。可能我就是写一套系统直接使用了库的API。而不是用动态链接插件的形式。那就是使用class development的API来自定义component了。 其实不冲突。

在插件宏覆盖不了的地方,可能在开发插件的时候也要使用一些API。

2、Message Interchange Protocol (MIP)

我之前理解错了。以为是跟VLAN一样的分组机制。

实际上,MIP是babrltrace自己设计的、出于可扩展迭代考虑的模块间信息交互方法的版本管理机制。

这个MIP泛指所有的trace数据结构、交互实现方法等形成的基础设施。不同的开发者使用了相同的基础设施,才有可能实现数据交互。

目前babeltrace2他们只做了版本0。以后可能迭代更新。

3、 Trace IR、clock

在这里插入图片描述
Trace 是由一系列的 stream构成。

Stream是一个 message序列。

message序列 stream里包含了各种各样的 message。

Event也是其中一种Message。

Event包含 一些 field用于记录信息。

在这里插入图片描述
如果stream开了 default clock class。那么里面的message都可以有一个 clock snapshot。

对于event 这种message来说。时钟快照就是 event在被观测程序中发生的时间。

可以通过API通过message提取 snapshot。然后还可以把clock这种东西转换为从1970年到现在的纳秒数。

到这应该够用了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小羊苏C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值