【发布时间】:2016-06-27 02:19:40
【问题描述】:
在使用开源 ELK 堆栈时,我们遇到了一个问题,其中一个 Logstash 输入 snmptrap 正在以一种我们无法使用的方式格式化数据。在SNMPv1_Trap 类中有一个名为agent_address 的实例变量,它存储为SNMP::IpAddress。对于熟悉 SNMP 工作方式的任何人来说,在您的网络上使用陷阱中继时,代理地址对于确定 SNMP 陷阱的来源非常重要。
当您查看 Logstash 在收到陷阱时生成的事件时,可以看到该问题。主要是agent_address变量的inspect方法是转储不匹配任何有效数据的数据。
一个示例事件看起来像这样:
#<SNMP::SNMPv1_Trap:0x2db53346 @enterprise=[1.3.6.1.4.1.6827.10.17.3.1.1.1], @timestamp=#<SNMP::TimeTicks:0x2a643dd1 @value=0>, @varbind_list=[#<SNMP::VarBind:0x2d5043a5 @name=[1.0], @value=#<SNMP::Integer:0x29fb6a4a @value=1>>], @specific_trap=1000, @source_ip=\"192.168.87.228\", @agent_addr=#<SNMP::IpAddress:0x227a4011 @value=\"\\xC0\\xA8V\\xFE\">, @generic_trap=6>
然而,我们知道,SNMP::SNMPv1_Trap 中使用的 IpAddress 对象能够向我们返回一个格式良好的字符串,表示它正在存储的 IPv4 地址。
例如:
require 'snmp'
include SNMP
address = IpAddress.new(192.168.86.254)
puts address
将产生 192.168.86.254 而:
require 'snmp'
include SNMP
address = IpAddress.new(192.168.86.254)
puts address.inspect
将产生:
#<SNMP::IpAddress:0x0000000168ae88 @value="\xC0\xA8V\xFE">
这是其.inspect 方法未被覆盖的对象的预期行为。
显然@value 中的 IPv4 地址对我们没有用处,它只有三个有效的十六进制序列(xC0=192、xA8=168、xFE=254)并且还包含一个无效的十六进制序列('V')。每当表示 IPv4 地址的八位字节字符串也作为变量绑定发送时,也会发生同样的事情,这表明存在一些奇怪的编码。
不幸的是,除了编写我们自己的 SNMP 输入之外,没有对该对象的接口级别访问。我们通过“事件”接收到的对象包含检查字符串,而不是对象本身。因此,获取我们需要的信息的最简单的明显方法是重建 SNMPv1_Trap 对象,然后通过Object.#send 自己调用它。
如果我有 Object.#inspect 返回的原始、未格式化和默认字符串转储,是否有任何方法可以物理地重新创建用于即时进行检查转储的对象?
例如,给定字符串转储:
#<Integer:0x2737476 @value=1>
是否可以重新创建具有值为 1 的字段的 Integer 对象?如果这是可能的,还有没有办法以同样的方式重新创建嵌套对象?例如,给定字符串:
#<SNMP::SNMPv1_Trap:0x2ef73621 @value=1, @agent_address=#<SNMP::IpAddress:0x0000000168ae88 @value="\xC0\xA8V\xFE">>
是否有可能拥有如下所示的对象?
SNMP::SNMPv1_Trap{
@value : 1
@agent_address : SNMP::IpAddress{
@value : 1
}
}
【问题讨论】:
-
它没有回答你的问题(因此是评论),但我们最近用 snmptrapd 替换了我们的 snmptrap 输入(由一个单独的、较小的 logstash 处理,将它们放入 redis 以实现弹性)。它为我们提供了更大的处理灵活性,并消除了对 redis 的需求。
-
欢迎来到 SO。我们不在乎您是否是 SO 或语言的新手,我们只希望您进行研究并向我们展示您的努力。请阅读“How to Ask”(包括底部的链接)和“minimal reproducible example”。
-
如果他们没有为类实现
inspect方法,你为什么不呢?您可以通过许多不同的方式覆盖方法。而且,根据我们的工作经验,就完整性和准确性而言,SNMP MIB 无处不在。我们让他们返回原始/二进制数据,要求我编写代码来分解结构并将其转回可用信息。 -
如果一个对象的状态完全由它的实例变量决定(没有全局变量,没有一些哈希类变量中的条目,没有什么奇怪的),并且
inspect输出包含所有这些值,是的,您可以重建具有相同值的对象(但不是 same 对象)。 -
其他东西——如果你有一个仍然“活着”的对象的检查字符串(没有被垃圾收集,在某处仍然有引用),你可以这样做(尽管它的效率会非常低,不要用于生产)
ObjectSpace.each_object(SNMP::SNMPv1_Trap)搜索在其检查字符串中查找具有匹配地址的对象(至少,对于当前版本的 YARV,我认为这是一个地址)。
标签: ruby elasticsearch marshalling logstash