声明实体与关系
实体声明目前处于实验阶段。选项 key、内置约定和声明边表在未来版本中可能变化。
一张表通过声明"它的行描述了哪些实体、哪些列标识每个实体"加入语义图。常见情况由内置约定覆盖,其余的用 greptime.semantic.entity.* 表选项声明。
内置约定
约定随二进制发布,不可配置。某个实体类型上的显式声明总是覆盖该类型的约定声明,包括显式声明本身不可用的情况:写错的声明不会悄悄退回到另一套身份。
OTLP trace 表
table_data_model 为 greptime_trace_v1 或 greptime_trace_v2 的表都会自动获得以下实体声明,无需额外的实体选项。v1 从打平的属性列读取值;v2 从 JSON2 属性中读取值,使用相同的声明名称:
| 实体 | 标识列 | 描述列 |
|---|---|---|
service | service_name | — |
service.instance | service_name、resource_attributes.service.instance.id | — |
host | resource_attributes.host.id | resource_attributes.host.name |
k8s.pod | resource_attributes.k8s.pod.uid | resource_attributes.k8s.pod.name、resource_attributes.k8s.namespace.name |
k8s.node | resource_attributes.k8s.node.name | — |
k8s.container | resource_attributes.k8s.pod.uid、resource_attributes.k8s.container.name | resource_attributes.container.id、resource_attributes.container.name |
container | resource_attributes.container.id | resource_attributes.container.name |
只有当一行上某个声明的全部标识列都存在且非空时,该声明才在这一行生效。在携带完整 k8s.container 身份的行上,通用的 container 声明不再生效,因此 pod 里的容器是一个节点,而不是两个。
OTLP trace 接入路径在建表时还会写入 greptime.semantic.entity.service.id = service_name。这个显式选项优先于约定的 service 声明,因此从 trace 派生的 service id 就是不带前缀的服务名。
service.instance 没有被写入显式选项,因此适用约定:resource_attributes.service.namespace 存在时,id 渲染为 <namespace>/<service_name>,<instance.id>。其中的首个分量与 Prometheus 的 job 标签一致——OpenTelemetry 兼容性规范把 job 定义为 <service.namespace>/<service.name>。
两条规则在 service 这一层并不一致。当 service.namespace 为 shop、service.name 为 api 时,同一个服务会以两个节点进入图:
| 来源 | entity_type | entity_id |
|---|---|---|
| OTLP trace 表 | service | api |
target_info 或 greptime_otel_resource_info | service | shop/api |
| OTLP trace 表 | service.instance | shop/api,<instance.id> |
只有 service.namespace 为空、job 就等于服务名本身时,两者才会重合。在这个差异存在期间要合并它们,需要在其中一侧用携带对方取值的列显式声明身份。
Prometheus 描述性指标
由 remote write 路径打上 signal_type = metric 和 source = prometheus 的表,如果表名命中白名单内的 kube-state-metrics 或 target_info 描述性指标,且标识列存在,就会得到隐式声明:
| 表 | 实体(标识列) |
|---|---|
kube_pod_info | k8s.pod(uid)、k8s.node(node) |
kube_node_info | k8s.node(node) |
kube_pod_owner | k8s.pod(uid)、k8s.workload(namespace、owner_kind、owner_name) |
kube_pod_container_info | k8s.pod(uid)、k8s.container(uid、container) |
kube_pod_init_container_info | k8s.pod(uid)、k8s.container(uid、container) |
kube_service_info | k8s.service(uid) |
target_info | service(job)、service.instance(job、instance) |
这些表同时贡献描述属性——pod 名和 namespace、节点内核版本、容器镜像——并按表上实际存在的列过滤,因为 kube-state-metrics 的标签集随版本变化。target_info 还会把剩余的全部 tag 列快照到 service.instance 实体上。
普通指标表不会被扫描出实体:带 job 和 instance 标签的指标本身不贡献实体,这些 service 由 target_info 引入。
OTLP 资源描述表
GreptimeDB 可以从写入的 OTLP metrics 的 resource attributes 中合成一张 greptime_otel_resource_info 表,让只有指标的 service 也能进入图。该功能默认关闭;开启后会创建并写入一张客户端没有发送的表。
[otlp]
experimental_enable_resource_info = true
开启后,该表声明 service(job)、service.instance(job、instance)、host(host.id)、k8s.pod(k8s.pod.uid)、k8s.node(k8s.node.name)、k8s.container(k8s.pod.uid、k8s.container.name)和 container(container.id),取代规则与 trace 侧相同。
在自己的表上声明实体
每种实体类型有三个 选项 key:
greptime.semantic.entity.<entity_type>.id = 逗号分隔的列名
greptime.semantic.entity.<entity_type>.descriptive = 逗号分隔的列名 (可选)
greptime.semantic.entity.<entity_type>.scope = 逗号分隔的列名 (可选)
<entity_type> 是一个或多个用点分隔的 [a-z0-9_] 片段,例如 service、k8s.pod、gen_ai.agent,也可以是自定义类型。与语义词汇表的其余部分不同,实体类型是开放的。
DDL 阶段强制四条规则:
- 列必须在表上存在;v2 trace 表还支持下文说明的 JSON2 属性引用。
- 列必须能渲染成字符串。
Binary、Json、Json2、Vector、List