otelcol 连接器跨度指标
otelcol.connector.spanmetrics
从其他 otelcol
组件接受跨度数据,并从跨度中聚合请求、错误和持续时间(R.E.D)OpenTelemetry 指标
请求计数是按每个唯一维度集(包括错误)看到的跨度数量计算的。如果用户希望仅查看
service.name
和span.name
上的调用次数,则可以聚合多个指标。使用具有
status.code
数据点属性设置为Ok
的calls
指标来跟踪请求calls { service.name="shipping", span.name="get_shipping/{shippingId}", span.kind="SERVER", status.code="Ok" }
错误计数是从具有
Error
状态码的跨度数量计算的。使用具有
status.code
数据点属性设置为Error
的calls
指标来跟踪错误calls { service.name="shipping", span.name="get_shipping/{shippingId}, span.kind="SERVER", status.code="Error" }
持续时间是从跨度开始和结束时间之间的差异计算的,并插入到每个唯一维度集的相关持续时间直方图时间桶中。
使用
duration
直方图指标来跟踪跨度持续时间duration { service.name="shipping", span.name="get_shipping/{shippingId}", span.kind="SERVER", status.code="Ok" }
注意
otelcol.connector.spanmetrics
是上游 OpenTelemetry Collectorspanmetrics
连接器的包装器。如果需要,将错误报告或功能请求重定向到上游存储库。
可以通过提供不同的标签来指定多个 otelcol.connector.spanmetrics
组件。
用法
otelcol.connector.spanmetrics "LABEL" {
histogram {
...
}
output {
metrics = [...]
}
}
参数
otelcol.connector.spanmetrics
支持以下参数
名称 | 类型 | 描述 | 默认值 | 是否必须 |
---|---|---|---|---|
aggregation_temporality | 字符串 | 配置是否在刷新后重置指标。 | "CUMULATIVE" | 否 |
dimensions_cache_size | 数字 | 要缓存的维度数量。 | 1000 | 否 |
exclude_dimensions | 字符串列表 | 要从默认维度集中排除的维度列表。 | [] | 否 |
metrics_flush_interval | 持续时间 | 刷新生成指标的频率。 | "60s" | 否 |
metrics_expiration | 持续时间 | 指标被认为过时并被从缓存中删除的时间段。 | "0s" | 否 |
metric_timestamp_cache_size | 数字 | 控制用于跟踪指标最后一次刷新时间的缓存的大小。 | 1000 | 否 |
namespace | 字符串 | 指标命名空间。 | "traces.span.metrics" | 否 |
resource_metrics_cache_size | 数字 | 包含服务指标的缓存大小。 | 1000 | 否 |
resource_metrics_key_attributes | 字符串列表 | 限制用于创建指标的资源属性。 | [] | 否 |
调整 dimensions_cache_size
可以提高 Alloy 处理的内存使用。
aggregation_temporality
的支持值有
"CUMULATIVE"
: 指标在刷新后 不会 重置。"DELTA"
: 指标在刷新后将重置。
如果设置了 namespace
,则生成的指标名称将添加一个 namespace.
前缀。
将 metrics_expiration
设置为 "0s"
表示指标永远不会过期。
resource_metrics_cache_size
对于累积时间性主要相关。它有助于避免内存增加和指标时间戳重置错误的问题。
metric_timestamp_cache_size
仅与增量时间性跨度指标相关。它控制用于跟踪指标最后一次刷新时间的缓存的大小。当指标从缓存中移除时,它的下一个数据点将指示系列中的“重置”。将增量转换为累积的下游组件可能通过将累积计数器重置为 0 来处理这些重置。
resource_metrics_key_attributes
可用于避免资源属性可能在服务重启之间更改的情况,这会导致指标计数器中断(并重复)。资源不需要具有所有属性。列表必须包含足够的属性以正确标识唯一的资源,否则可能会从多个服务和跨度中聚合数据。例如,["service.name", "telemetry.sdk.language", "telemetry.sdk.name"]
。
块
以下块在 otelcol.connector.spanmetrics
定义内部受支持
层次结构 | 块 | 描述 | 是否必须 |
---|---|---|---|
dimension | dimension | 要添加的维度,除了默认维度之外。 | 否 |
events | events | 配置事件指标。 | 否 |
events > dimension | dimension | 要添加到事件指标的维度,位于默认维度和顶层 dimension 块中配置的维度之上。 | 否 |
exemplars | exemplars | 配置如何将示例附加到直方图。 | 否 |
histogram | histogram | 配置从跨度持续时间派生的直方图。 | 是 |
histogram > explicit | 显式 | 具有显式桶的直方图的配置。 | 否 |
histogram > exponential | 指数 | 具有指数桶的直方图的配置。 | 否 |
output | output | 配置将遥测数据发送到何处。 | 是 |
debug_metrics | debug_metrics | 配置此组件生成的指标以监控其状态。 | 否 |
维度块
dimension
块配置要添加的维度,这些维度将添加到默认维度之外。
默认维度包括
service.name
span.name
span.kind
status.code
默认维度总是会被添加。如果没有指定额外的维度,则只添加默认维度。
支持以下属性
名称 | 类型 | 描述 | 默认值 | 是否必须 |
---|---|---|---|---|
default | 字符串 | 如果属性缺失时使用的值。 | null | 否 |
name | 字符串 | 要查找的跨度属性或资源属性。 | 是 |
otelcol.connector.spanmetrics
将在跨度的属性集中查找name
属性。如果没有找到,将检查资源属性。
如果属性在跨度和资源属性中均缺失
- 如果没有设置
default
,则将省略维度。 - 如果设置了
default
,则将添加维度,并将其值设置为default
的值。
事件块
events
块配置跟踪跨度事件的events
度量。
支持以下属性
名称 | 类型 | 描述 | 默认值 | 是否必须 |
---|---|---|---|---|
enabled | bool | 启用所有事件度量。 | false | 否 |
如果将enabled
设置为true
,则至少需要一个dimension
块。
直方图块
histogram
块配置从跨度持续时间派生的直方图。
支持以下属性
名称 | 类型 | 描述 | 默认值 | 是否必须 |
---|---|---|---|---|
disable | bool | 禁用所有直方图度量。 | false | 否 |
unit | 字符串 | 配置直方图单位。 | "ms" | 否 |
unit
的支持值包括
"ms"
:毫秒"s"
:秒
指数块
exponential
块配置具有指数桶的直方图。
支持以下属性
名称 | 类型 | 描述 | 默认值 | 是否必须 |
---|---|---|---|---|
max_size | 数字 | 每个正数或负数范围的最大桶数。 | 160 | 否 |
显式块
explicit
块配置具有显式桶的直方图。
支持以下属性
名称 | 类型 | 描述 | 默认值 | 是否必须 |
---|---|---|---|---|
buckets | list(duration) | 直方图桶的列表。 | ["2ms", "4ms", "6ms", "8ms", "10ms", "50ms", "100ms", "200ms", "400ms", "800ms", "1s", "1400ms", "2s", "5s", "10s", "15s"] | 否 |
示例块
exemplars
块配置如何将示例附加到直方图。
支持以下属性
名称 | 类型 | 描述 | 默认值 | 是否必须 |
---|---|---|---|---|
enabled | bool | 配置是否将示例添加到直方图。 | false | 否 |
max_per_data_point | 数字 | 限制可以添加到唯一维度集的示例数量。 | null | 否 |
max_per_data_point
可以帮助减少内存消耗。
输出块
output
块配置一组组件,用于将结果遥测数据转发到这些组件。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 是否必须 |
---|---|---|---|---|
metrics | list(otelcol.Consumer) | 要发送度量到其处的消费者列表。 | [] | 否 |
必须指定output
块,但所有参数都是可选的。默认情况下,遥测数据将被丢弃。根据需要配置metrics
参数以将遥测数据发送到其他组件。
调试度量块
debug_metrics
块配置该组件生成的用于监控其状态的度量。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 是否必须 |
---|---|---|---|---|
disable_high_cardinality_metrics | boolean | 是否禁用某些高基数度量。 | true | 否 |
level | 字符串 | 控制包装收集器发出的度量的详细程度。 | "detailed" | 否 |
disable_high_cardinality_metrics
是 Grafana Alloy 中对应于 OpenTelemetry Collector 中的 telemetry.disableHighCardinalityMetrics
功能开关。它移除了可能导致高基数指标的属性。例如,从关于 HTTP 和 gRPC 连接的指标中移除包含 IP 地址和端口号的属性。
注意
如果配置了,disable_high_cardinality_metrics
仅适用于otelcol.exporter.*
和otelcol.receiver.*
组件。
level
是 Grafana Alloy 中对应于 OpenTelemetry Collector 中的 telemetry.metrics.level
功能开关。可能的值有 "none"
、"basic"
、"normal"
和 "detailed"
。
导出字段
以下字段被导出,并可由其他组件引用
名称 | 类型 | 描述 |
---|---|---|
input | otelcol.Consumer | 其他组件可以使用该值发送遥测数据。 |
input
接受 otelcol.Consumer
跟踪遥测数据。它不接受指标和日志。
资源属性的处理
otelcol.connector.spanmetrics
是一个 OTLP 原生组件。因此,它旨在保留跨度资源的资源属性。
例如,假设有两个带有相同
service.name
和k8s.pod.name
资源属性的传入资源跨度。{ "resourceSpans": [ { "resource": { "attributes": [ { "key": "service.name", "value": { "stringValue": "TestSvcName" } }, { "key": "k8s.pod.name", "value": { "stringValue": "first" } } ] }, "scopeSpans": [ { "spans": [ { "trace_id": "7bba9f33312b3dbb8b2c2c62bb7abe2d", "span_id": "086e83747d0e381e", "name": "TestSpan", "attributes": [ { "key": "attribute1", "value": { "intValue": "78" } } ] } ] } ] }, { "resource": { "attributes": [ { "key": "service.name", "value": { "stringValue": "TestSvcName" } }, { "key": "k8s.pod.name", "value": { "stringValue": "first" } } ] }, "scopeSpans": [ { "spans": [ { "trace_id": "7bba9f33312b3dbb8b2c2c62bb7abe2d", "span_id": "086e83747d0e381b", "name": "TestSpan", "attributes": [ { "key": "attribute1", "value": { "intValue": "78" } } ] } ] } ] } ] }
otelcol.connector.spanmetrics
将通过将它们附加到输出指标资源来保留传入的service.name
和k8s.pod.name
资源属性。由于两个跨度资源具有相同的资源属性,因此将仅创建一个指标资源。{ "resourceMetrics": [ { "resource": { "attributes": [ { "key": "service.name", "value": { "stringValue": "TestSvcName" } }, { "key": "k8s.pod.name", "value": { "stringValue": "first" } } ] }, "scopeMetrics": [ { "scope": { "name": "spanmetricsconnector" }, "metrics": [ { "name": "calls", "sum": { "dataPoints": [ { "attributes": [ { "key": "service.name", "value": { "stringValue": "TestSvcName" } }, { "key": "span.name", "value": { "stringValue": "TestSpan" } }, { "key": "span.kind", "value": { "stringValue": "SPAN_KIND_UNSPECIFIED" } }, { "key": "status.code", "value": { "stringValue": "STATUS_CODE_UNSET" } } ], "startTimeUnixNano": "1702582936761872000", "timeUnixNano": "1702582936761872012", "asInt": "2" } ], "aggregationTemporality": 2, "isMonotonic": true } } ] } ] } ] }
现在假设
otelcol.connector.spanmetrics
接收到两个带有不同k8s.pod.name
资源属性值的传入资源跨度。{ "resourceSpans": [ { "resource": { "attributes": [ { "key": "service.name", "value": { "stringValue": "TestSvcName" } }, { "key": "k8s.pod.name", "value": { "stringValue": "first" } } ] }, "scopeSpans": [ { "spans": [ { "trace_id": "7bba9f33312b3dbb8b2c2c62bb7abe2d", "span_id": "086e83747d0e381e", "name": "TestSpan", "attributes": [ { "key": "attribute1", "value": { "intValue": "78" } } ] } ] } ] }, { "resource": { "attributes": [ { "key": "service.name", "value": { "stringValue": "TestSvcName" } }, { "key": "k8s.pod.name", "value": { "stringValue": "second" } } ] }, "scopeSpans": [ { "spans": [ { "trace_id": "7bba9f33312b3dbb8b2c2c62bb7abe2d", "span_id": "086e83747d0e381b", "name": "TestSpan", "attributes": [ { "key": "attribute1", "value": { "intValue": "78" } } ] } ] } ] } ] }
为了保留所有资源属性值,
otelcol.connector.spanmetrics
将生成两个资源指标。每个资源指标将具有不同的k8s.pod.name
资源属性值。这样,在生成指标的过程中,不会丢失任何资源属性。{ "resourceMetrics": [ { "resource": { "attributes": [ { "key": "service.name", "value": { "stringValue": "TestSvcName" } }, { "key": "k8s.pod.name", "value": { "stringValue": "first" } } ] }, "scopeMetrics": [ { "scope": { "name": "spanmetricsconnector" }, "metrics": [ { "name": "calls", "sum": { "dataPoints": [ { "attributes": [ { "key": "service.name", "value": { "stringValue": "TestSvcName" } }, { "key": "span.name", "value": { "stringValue": "TestSpan" } }, { "key": "span.kind", "value": { "stringValue": "SPAN_KIND_UNSPECIFIED" } }, { "key": "status.code", "value": { "stringValue": "STATUS_CODE_UNSET" } } ], "startTimeUnixNano": "1702582936761872000", "timeUnixNano": "1702582936761872012", "asInt": "1" } ], "aggregationTemporality": 2, "isMonotonic": true } } ] } ] }, { "resource": { "attributes": [ { "key": "service.name", "value": { "stringValue": "TestSvcName" } }, { "key": "k8s.pod.name", "value": { "stringValue": "second" } } ] }, "scopeMetrics": [ { "scope": { "name": "spanmetricsconnector" }, "metrics": [ { "name": "calls", "sum": { "dataPoints": [ { "attributes": [ { "key": "service.name", "value": { "stringValue": "TestSvcName" } }, { "key": "span.name", "value": { "stringValue": "TestSpan" } }, { "key": "span.kind", "value": { "stringValue": "SPAN_KIND_UNSPECIFIED" } }, { "key": "status.code", "value": { "stringValue": "STATUS_CODE_UNSET" } } ], "startTimeUnixNano": "1702582936761872000", "timeUnixNano": "1702582936761872012", "asInt": "1" } ], "aggregationTemporality": 2, "isMonotonic": true } } ] } ] } ] }
组件健康状态
otelcol.connector.spanmetrics
仅在配置无效时报告为不健康。
调试信息
otelcol.connector.spanmetrics
不公开任何特定于组件的调试信息。
示例
显式直方图和额外维度
以下示例中,http.status_code
和 http.method
是在
service.name
span.name
span.kind
status.code
otelcol.receiver.otlp "default" {
http {}
grpc {}
output {
traces = [otelcol.connector.spanmetrics.default.input]
}
}
otelcol.connector.spanmetrics "default" {
// Since a default is not provided, the http.status_code dimension will be omitted
// if the span does not contain http.status_code.
dimension {
name = "http.status_code"
}
// If the span is missing http.method, the connector will insert
// the http.method dimension with value 'GET'.
dimension {
name = "http.method"
default = "GET"
}
dimensions_cache_size = 333
aggregation_temporality = "DELTA"
histogram {
unit = "s"
explicit {
buckets = ["333ms", "777s", "999h"]
}
}
// The period on which all metrics (whose dimension keys remain in cache) will be emitted.
metrics_flush_interval = "33s"
namespace = "test.namespace"
output {
metrics = [otelcol.exporter.otlp.production.input]
}
}
otelcol.exporter.otlp "production" {
client {
endpoint = sys.env("OTLP_SERVER_ENDPOINT")
}
}
通过Prometheus远程写入发送指标
生成的指标可以发送到Grafana Mimir等兼容Prometheus的数据库。但是,需要额外步骤以确保所有指标样本都被接收。这是因为otelcol.connector.spanmetrics
旨在在输出的指标中保留资源属性。
不幸的是,Prometheus数据模型没有资源属性的概念。这意味着如果otelcol.connector.spanmetrics
输出具有相同指标属性但不同资源属性的指标,otelcol.exporter.prometheus
将把指标转换为相同的指标系列。可以通过以下两种方法之一解决这个问题:
推荐方法:在
otelcol.connector.spanmetrics
之前,删除所有不需要的资源属性。otelcol.receiver.otlp "default" { http {} grpc {} output { traces = [otelcol.processor.transform.default.input] } } // Remove all resource attributes except the ones which // the otelcol.connector.spanmetrics needs. // If this is not done, otelcol.exporter.prometheus may fail to // write some samples due to an "err-mimir-sample-duplicate-timestamp" error. // This is because the spanmetricsconnector will create a new // metrics resource scope for each traces resource scope. otelcol.processor.transform "default" { error_mode = "ignore" trace_statements { context = "resource" statements = [ // We keep only the "service.name" and "special.attr" resource attributes, // because they are the only ones which otelcol.connector.spanmetrics needs. // // There is no need to list "span.name", "span.kind", and "status.code" // here because they are properties of the span (and not resource attributes): // https://github.com/open-telemetry/opentelemetry-proto/blob/v1.0.0/opentelemetry/proto/trace/v1/trace.proto `keep_keys(attributes, ["service.name", "special.attr"])`, ] } output { traces = [otelcol.connector.spanmetrics.default.input] } } otelcol.connector.spanmetrics "default" { histogram { explicit {} } dimension { name = "special.attr" } output { metrics = [otelcol.exporter.prometheus.default.input] } } otelcol.exporter.prometheus "default" { forward_to = [prometheus.remote_write.mimir.receiver] } prometheus.remote_write "mimir" { endpoint { url = "http://mimir:9009/api/v1/push" } }
或者,在
otelcol.connector.spanmetrics
之后,将每个资源属性作为指标数据点属性复制。这种方法的优势是资源属性将作为指标标签可见。然而,指标的基数 可能会很高,这可能会增加存储和查询的成本。以下示例使用merge_maps OTTL函数。otelcol.receiver.otlp "default" { http {} grpc {} output { traces = [otelcol.connector.spanmetrics.default.input] } } otelcol.connector.spanmetrics "default" { histogram { explicit {} } dimension { name = "special.attr" } output { metrics = [otelcol.processor.transform.default.input] } } // Insert resource attributes as metric data point attributes. otelcol.processor.transform "default" { error_mode = "ignore" metric_statements { context = "datapoint" statements = [ // "insert" means that a metric datapoint attribute will be inserted // only if an attribute with the same key does not already exist. `merge_maps(attributes, resource.attributes, "insert")`, ] } output { metrics = [otelcol.exporter.prometheus.default.input] } } otelcol.exporter.prometheus "default" { forward_to = [prometheus.remote_write.mimir.receiver] } prometheus.remote_write "mimir" { endpoint { url = "http://mimir:9009/api/v1/push" } }
如果未以上述任何一种方式处理资源属性,则prometheus.remote_write
可能会记录此类错误:由于另一个具有相同时间戳但不同值的样本已被摄入,已拒绝此样本(err-mimir-sample-duplicate-timestamp)
。
注意
为了生成Prometheus的
target_info
指标,传入的跨度资源作用域属性必须包含service.name
和service.instance.id
属性。将为每个资源作用域生成
target_info
指标,同时将OpenTelemetry指标名称和属性规范化,使其符合Prometheus命名规则。
兼容组件
otelcol.connector.spanmetrics
可以接受以下组件的参数:
otelcol.connector.spanmetrics
具有以下可以消费的导出:
注意
连接某些组件可能不合理,或者组件可能需要进一步配置才能正确连接。请参阅相关文档以获取更多详细信息。