探针 (API)
通用探测 REST API
以下信息将尽可能多地介绍 API,以便已经熟悉 Apstra API 约定的人员了解如何使用 IBA。正式的 API 文档是为 API 文档本身保留的。
我们将逐步了解该 API,因为它用于简介中描述的示例工作流,并通过具体示例演示其一般功能。
创建探针
要创建探针,作员按以下形式开机自检 /api/blueprints/<blueprint_id>/probes :
{
"label": "server_tx_bytes",
"description": "Server traffic imbalance",
"tags": ["server", "imbalance"],
"disabled": false,
"processors": [
{
"name": "server_tx_bytes",
"outputs": {
"out": "server_tx_bytes_output"
},
"properties": {
"counter_type": "tx_bytes",
"graph_query": "node('system', name='sys').out('hosted_interfaces').node('interface', name='intf').out('link').node('link', link_type='ethernet', speed=not_none()).in_('link').node('interface', name='dst_intf').in_('hosted_interfaces').node('system', name='dst_node', role='server').ensure_different('intf', 'dst_intf')",
"interface": "intf.if_name",
"system_id": "sys.system_id"
},
"type": "if_counter"
},
{
"inputs": {
"in": "server_tx_bytes_output"
},
"name": "std",
"outputs": {
"out": "std_dev_output"
},
"properties": {
"ddof": 0,
"group_by": []
},
"type": "std_dev"
},
{
"inputs": {
"in": "std_dev_output"
},
"name": "server_imbalance",
"outputs": {
"out": "std_dev_output_in_range"
},
"properties": {
"range": {
"max": 100
}
},
"type": "range_check"
},
{
"inputs": {
"in": "std_dev_output_in_range"
},
"name": "server_imbalance_anomaly",
"outputs": {
"out": "server_traffic_imbalanced"
},
"type": "anomaly"
}
],
"stages": [
{
"name": "server_tx_bytes_output",
"description": "Collect server tx_bytes",
"tags": ["traffic counter"],
"units": "Bps"
}
]
}
如上所示,端点将获得探测元数据、处理器实例列表和输出阶段列表的输入。
探针元数据由以下字段组成:
| label | 人类可读的探针标签;必填 |
| description | 探头的可选描述, |
| tags | 带有探针标记的字符串列表;自选 |
| disabled | 可选布尔值,指示是否应禁用探针。禁用的探针不提供任何数据,也不会消耗任何资源。默认情况下,探针未被禁用。 |
每个处理器实例都包含实例名称(由用户定义)、处理器类型(从平台和参考设计定义的目录中选择的选项)和 inputs /或 outputs。每个处理器中的所有其他字段都特定于该类型的处理器,在子字段中 properties 指定,可以通过我们的自省 API /api/blueprints/<blueprint_id>/telemetry/processors通过自省来学习;我们稍后将介绍此 API。
与我们的工作示例相匹配,我们将遍历上述示例中处理器列表中的每个条目。
在第一个条目中,我们有一个类型为处理器实例 if_counter ,我们将其命名为 server_tx_bytes。它将一个名为 graph_query 的查询作为输入,该查询是图形查询。然后,它还有另外两个名为 interface 和 system_id的字段。这三个字段共同表示我们要为系统中每个面向服务器的端口收集一个(第一次导数)计数器。对于 指定的 graph_query查询的每个匹配项,我们通过获取 system_id 结果路径中节点的字段 sys (如处理器字段中指定 system_id )来提取system_id,并通过获取 if_name 生成路径中节点的 intf 字段(如处理器字段中指定 interface )来提取接口名称。系统 ID 和接口的组合用于识别网络中的接口,其tx_bytes计数器(由 指定) counter_type被放入此处理器的输出中。此处理器的输出类型为“数字集”(NS);阶段类型将在后面详尽地讨论。该处理器没有输入,因此我们不提供 input 字段。它有一个标记为( out 由 if_counter 处理器类型定义)的输出;我们将该输出映射到标记为 server_tx_bytes_output的阶段。
第二个处理器的类型 std_dev 是,它把我们之前创建 server_tx_bytes_output的阶段作为输入,称为;有关字段的含义 ddof ,请参阅特定于处理器的文档。另外,请参阅特定于处理器的文档,了解字段的完整含义 group_by 。现在我只想说,在这种情况下 group_by ,告诉我们从输入 NS 构造一个输出“数字”(N);也就是说,这个处理器输出一个数字——许多输入数字中每个数字的标准偏差。此输出名为“std_dev_output”。
第三个处理器是类型 range_check ,并作为输入 std_dev_output。它检查输入是否超出了 - 在本例中,如果输入大于 100(我们选择此任意值来指示服务器定向流量何时不平衡)指定的预期范围 range 。该处理器具有单个输出,我们选择将其标记为 std_dev_output_in_range。此输出(由 range_check 处理器类型定义)为 DS(离散状态)类型,可以取值 true 或 false,指示值是否超出范围。
我们的最终处理器是类型 anomaly 并作为输入 std_dev_output_in_range。当输入处于该 true 状态时,它会引发 Apstra 异常。该处理器具有单个输出,我们选择将其标记为 server_traffic_imbalanced。此输出(由异常处理器类型定义)的类型为 DS(离散状态),可以取值 true 或 false,指示是否引发了异常。在此示例中,我们不会对这些异常状态数据进行任何进一步的处理,但这并不排除其一般可能性。
最后,我们有一个 stages 字段。这是输出阶段子集的列表,每个阶段都由引用阶段标签的 name 字段表示。此列表旨在将无法从 DAG 本身推断的每个输出阶段添加元数据。目前,支持的字段包括:
| description | 带有阶段描述的字符串, |
| tags | 用于为 Stage 创建一组标记的字符串列表, |
| units | 字符串,用于描述阶段数据的单位。 |
所有这些字段都是可选的。
通过 REST API 从该阶段获取数据时,将返回此阶段元数据,并由 GUI 在可视化中使用。
HTTP POST 可以发送到 /api/blueprints/<blueprint_id>/probes。在这里,我们进行POST探针配置,如“POST for Probe Creation”图中所示,以创建一个新探针。POSTing 到此端点将返回一个 UUID,就像 Apstra 中的大多数其他创建端点一样,该端点可用于进一步的作。
在 2.3 版更改: 要获取可预测的探测 ID 而不是上述 UUID,可以通过向请求正文添加“id”属性来指定它。
{
"id": "my_tx_bytes_probe",
"label": "server_tx_bytes",
"processors": [],
"rest_of_the": "request_body"
}
在 2.3 版更改: 以前,阶段定义内联到处理器定义中,如下所示:
{
"label": "test probe",
"processors": [
{
"name": "testproc",
"outputs": {"out": "test_stage"},
"stages": [{"name": "out", "units": "pps"}]
}
]
}
这不再有效,艺名应指舞台标签而不是内部艺名。因此,上面的示例应如下所示:
{
"stages": [{"name": "test_stage", "units": "pps"}]
}
附加说明:建议不要将阶段定义内联到处理器定义中,并将其作为独立元素放置,如上面的 POST 示例所示。
HTTP DELETE 可以发送到 /api/blueprints/<blueprint_id>/probes/<probe_id> 删除其 probe_id指定的探针的位置。
可以将 HTTP GET 发送到 /api/blueprints/<blueprint_id>/probes/<probe_id> 以检索探针的配置,因为它已开机自发。它包含的字段将多于创建探针时指定的字段:
| id | 使用探针的 ID(如果在创建时未指定 UUID),则使用 UUID |
| state | 探头的实际状态;对于正在配置的探针,可能的值为 “created”,对于已成功配置的探针,可能的值为 “operational”,如果探针配置失败,则为 “error”。 |
| last_error | 包含处于“错误”状态的探针的最新错误的详细错误说明。它具有以下子字段:
|
可以通过向 /api/blueprints/<blueprint_id>/probes/<probe_id>/messages发出 HTTP GET 请求来获取探测消息的完整列表。
消息按“时间戳”字段排序,最早的排在前。
此外,可以将 HTTP GET 发送到 /api/blueprints/<blueprint_id>/probes 以检索 blueprint <blueprint_id>的所有探测。
2.3
从 Apstra 2.3 版开始,用于探针的 HTTP PATCH 和 PUT 方法已可用。
可以发送 /api/blueprints/<blueprint_id>/probes/<probe_id> HTTP PATCH 以更新探测元数据或禁用或启用探测。
{
"label": "new server_tx_bytes",
"description": "some better probe description",
"tags": ["production"],
"stages": [
{
"name": "server_tx_bytes",
"description": "updated stage description",
"tags": ["server traffic"],
"units": "bps"
}
]
}
此示例更新使用上面列出的 POST 请求创建的探针的探针元数据。此处的所有字段均为可选字段,未指定的值保持不变。
每个阶段实例也是可选的,也就是说,只有指定的阶段才会更新,未指定的阶段保持不变。
标签集合将完全更新,即如果是 tags: ["a", "b"] 并且指定 tags: ["c"]了 PATCH 有效负载,则生成的集合将类似于 tags: ["c"] (NOT tags: ["a", "b", "c"])。
使用 PATCH 时,无法更改探针的处理器和阶段集。请进一步阅读允许执行此作的 PUT 说明。
可以将 HTTP PUT 发送到 /api/blueprints/<blueprint_id>/probes/<probe_id> 以替换探针。
这与开机自检非常相似,不同之处在于它将探针 <probe_id> 的旧配置替换为有效负载中指定的新配置。此请求的有效负载格式与开机自检的有效负载格式相同,但 id 不允许使用。
检查探头
阶段是通过在各种处理器的输入和输出中命名而隐式创建的。您可以检查探头的各个阶段。用于读取特定阶段的 API 是 /api/blueprints/<blueprint_id>/probes/<probe_id>/stages/<stage_name>
每个阶段都有一个类型。这是生成处理器和该处理器的输入级的功能。类型为:数字 (N);数字时间序列 (NTS)、数字集 (NS);数字集时间序列 (NSTS);文本 (T);文本时间序列 (TTS);文本集 (TS);文本集时间序列 (TSTS);离散状态 (DS);离散状态时间序列(DSTS);离散状态集 (DSS);离散集时间序列 (DSSTS)
NS 就是这样:一组数字。
同样,DSS 是一组离散状态变量。DSS(和 DSSTS)阶段规范的一部分是离散状态变量可以采用的可能值。
文本集是一组字符串。
NSTS 是一组以数字为值的时间序列。例如,此集合的成员为:(time=0 seconds, value=3)、(time=3 seconds, value=5)、(time=6 seconds, value=23),依此类推。
DSTS 与 NSTS 相同,只是值为离散状态。
TSTS 与 NSTS 相同,只是值是字符串。
数字 (N)、离散状态 (DS) 和文本 (T) 只是保证长度为 1 的数字集、离散状态集和文本集。
NTS、DSTS 和 TS 与上述相同,但为时间序列,而不是单个值。
让我们考虑第一阶段 - “server_tx_bytes”。此阶段包含系统中每个面向服务器的端口的tx_bytes计数器。我们可以从 url 获取它 /api/blueprints/<blueprint_id>/probes/<probe_id>/stages/server_tx_bytes_output
我们得到的响应形式如下:
{
"properties": [
"interface",
"system_id"
],
"type": "ns",
"units": "bytes_per_second",
"values": [
{
"properties": {
"interface": "intf1",
"system_id": "spine1"
},
"value": 22
},
{
"properties": {
"interface": "intf2",
"system_id": "spine1"
},
"value": 23
},
{
"properties": {
"interface": "intf1",
"system_id": "spine3"
},
"value": 24
}
]
}
正如我们从正在运行的示例中了解到的那样,“server_tx_bytes”阶段包含网络中每个面向服务器的接口的tx_bytes值。查看上面的示例,我们可以看到此阶段的类型为“ns”,表示 NS 或 Number-Set。如前所述,分阶段的数据与上下文相关联。这意味着阶段集中的每个元素都与一组键值对相关联。在每个阶段,每个数据(或等效地,集合中的项)的键都是相同的。这些键列在给定阶段的“属性”字段中,通常是生成处理器的函数。“values”中的每个项目都为阶段的每个属性分配一个值,并提供一个值(“Number Set”中的“Number”)。此阶段此数据的含义是,主干 1 的 intf1 上的tx_bytes为 22,主干 1 的 intf2 为 23,主干 3 的 intf1 为每秒 24 字节。
请注意,按照正在运行的示例中指定的方式,为此阶段设置了“units”。
要查询探测中的第二阶段,请将 HTTP GET 发送到 std 端点 /api/blueprints/<blueprint_id>/probes/<probe_id>/stages/std_dev_output。
{
"type": "n",
"units": "",
"value": 1
}
这个阶段是一个数字。它没有上下文,只有一个值。在我们的示例中,这是所有主干的标准差。
探针的倒数第二个阶段可以在端点 /api/blueprints/<blueprint_id>/probes/<probe_id>/stages/server_traffic_imbalanced查询。
{
"possible_values": [
"true",
"false"
],
"type": "ds",
"units": "",
"value": false
}
如图所示,此阶段通过指示所有面向服务器的端口的 tx_bytes 间的标准偏差是否大于 100 来指示服务器流量是否不平衡 (“true”) 或不平衡 (“false”)。请注意,“possible_values”字段描述了离散状态“值”可以采用的所有值。
探针的所有处理器也可以通过 /api/blueprints/<blueprint_id>/probes/<probe_id>/processors/<processor_name>进行查询。通过执行此类查询,您可以发现用于创建所述处理器的配置。
查询探测异常
示例处理器的最后阶段会引发 Apstra 异常(并将其输出设置为 “true”),此时面向服务器的接口之间的 tx_bytes 标准偏差大于 100。
您可以通过标准异常 API 查询探测异常,网址为 /api/blueprints/<bluprint_id>/anomalies?type=probe。
以下是我们的示例探测将引发的异常的 JSON 形式(在此示例中,我们不关心的数据使用省略号):
{
"actual": {
"value_int": 101
},
"anomaly_type": "probe",
"expected": {
"value_int": 100
},
"id": "...",
"identity": {
"anomaly_type": "probe",
"probe_id": "efb2bf7f-d8cc-4a55-8e9b-9381e4dba61f",
"properties": {},
"stage_id": "server_traffic_imbalanced"
},
"last_modified_at": "...",
"severity": "critical"
}
如上例所示,标识包含引发异常且需要作员进一步检查的阶段的probe_id和名称。在给定阶段内,如果阶段的类型是基于集合的类型,则异常的“属性”字段将填充导致异常的集合中特定项的属性。这就引出了一个重要的观点,即只要每个异常发生在集合中的不同项目上,就可以在一个阶段上引发多个异常。在我们的示例中,由于所讨论的阶段是 NS 类型,因此未设置“属性”字段。
自省处理器
可供作员使用的处理器集取决于平台和参考设计。Apstra 提供了一个 API,供运维人员列出所有可用的处理器,了解它们采用的参数,以及它们需要的输入和产生的输出。
有问题的 API 可在 /api/blueprints/<blueprint_id>/telemetry/processors中找到。
它将生成一个处理器描述列表。在以下示例中,我们展示了 std_dev 处理器的描述。
{
"description": "Standard Deviation Processor.\n\n Groups as described by group_by, then calculates std deviation and\n outputs one standard deviation for each group. Output is NS.\n Input is an NS or NSTS.\n ",
"inputs": {
"in": {
"required": true,
"types": [
{
"keys": [],
"possible_values": null,
"type": "ns"
},
{
"keys": [],
"possible_values": null,
"type": "nsts"
}
]
}
},
"outputs": {
"out": {
"required": true,
"types": [
{
"keys": [],
"possible_values": null,
"type": "ns"
}
]
}
},
"label": "Standard Deviation",
"name": "std_dev",
"schema": {
"additionalProperties": false,
"properties": {
"ddof": {
"default": 0,
"description": "Standard deviation correction value, is used to correct divisor (N - ddof) in calculations, e.g. ddof=0 - uncorrected sample standard deviation, ddof=1 - corrected sample standard deviation.",
"title": "ddof",
"type": "integer"
},
"enable_streaming": {
"default": false,
"type": "boolean"
},
"group_by": {
"default": [
"system_id"
],
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object"
}
}
如上所示,有一个基于字符串的描述,即类型处理器类型的名称(在探测配置中提供给 REST API)。特定于给定探针的参数集在“schema”中描述。
必须特别注意“投入”和“产出”。尽管它们在“架构”部分中,但它们存在于每种类型的处理器上。每个处理器可以采用零个或更多输入级,并且必须输出一个或多个级。可选阶段将“required”设置为 false。这些变量描述了它们所采用的阶段名称(相对于处理器的特定实例)。我们可以看到,“std_dev”处理器接受一个名为“in”的输入和一个名为“out”的输出。这反映在我们在上一个示例中对它的使用中。
有一个特殊的输入名称: *.例如:
"inputs": {
"*": {
"required": true,
"types": [
{
"keys": [],
"possible_values": null,
"type": "ns"
},
{
"keys": [],
"possible_values": [],
"type": "dss"
},
{
"keys": [],
"possible_values": null,
"type": "ts"
}
]
}
}
这意味着处理器接受一个或多个具有任意名称的指定类型的输入。
在 3.0 中更改:以前,输入和输出部分没有指定是否需要特定的输入或输出,因此格式从以下更改:
此语法已弃用且无效。
"inputs": {
"in": [
{
"data_type": "ns",
"keys": [
"system_id"
],
"value_map": null,
"value_type": "int64"
}
...
]
}
流数据
任何探针中的任何处理器实例都可以配置为在 Apstra 流式传输输出的 “perfmon” 通道中流式传输其输出级。如果在任何处理器的配置中将属性“enable_streaming”设置为“true”,则其输出级将流式传输其所有数据。
对于非基于时间序列的阶段,每当其值发生变化时,每个阶段都会生成一条消息。对于基于时间序列的阶段,每当有新条目进入时间序列时,每个阶段都会生成一条消息。对于基于集合的阶段,集合中的每个项目都会根据前面的两个规则生成一条消息。
生成的每条消息都有一个值、一个时间戳和一组键值对。其价值不言自明。时间戳是非基于时间序列的阶段的值更改的时间,以及基于时间序列的阶段的新条目的时间戳。键值对应于我们之前在阶段的“值”部分观察到的“属性”字段,从而提供了上下文。
下面是来自 IBA 的消息的格式,它被封装在 PerfMon 消息中(而这又封装在 AosMessage 中)。上下文的键值对被放入“property”重复字段(以 “name” 为键,“value” 为值),而值被放入 “value” 字段。“probe_id”和“stage_name”是它们出现的样子。将blueprint_id放入封装的 AosMessage 的“origin_name”中。同样,时间戳被放入通用的“时间戳”字段中。
message ProbeProperty {
required string name = 5;
required string value = 6;
}
message ProbeMessage {
repeated ProbeProperty property = 1;
oneof value {
int64 int64_value = 2;
float float_value = 3;
string string_value = 4;
}
required string probe_id = 5;
required string stage_name = 6;
}