grafana/k6

Extend the `metrics.TagSet` API

Open

#2,764 创建于 2022年11月10日

在 GitHub 查看
 (3 评论) (1 反应) (0 负责人)Go (30,564 star) (1,537 fork)batch import
featuregood first issueuxxk6

描述

Feature Description

During the grafana/xk6-output-prometheus-remote's PR review discussions, we found that extensions might need memory efficiently iterate on the tag/values because of a standard Map() is not memory efficient.

https://github.com/grafana/k6/blob/e14f14d416b0af4e495e6f565a2a9787a73ade54/metrics/tags.go#L72-L75

This leads that extensions should refer to the internals and iterate like:

https://github.com/grafana/xk6-output-prometheus-remote/blob/6c3f96add65cef26cf80fc157fa067de7c96f78b/pkg/remotewrite/prometheus.go#L12-L24

func MapTagSet(t *metrics.TagSet) []*prompb.Label {
	n := (*atlas.Node)(t)
	if n.Len() < 1 {
		return nil
	}
	labels := make([]*prompb.Label, 0, n.Len())
	for !n.IsRoot() {
		prev, key, value := n.Data()
		labels = append(labels, &prompb.Label{Name: key, Value: value})
		n = prev
	}
	return labels
}

Ideally, we should be more developer friendly and provide a way to iterate on tags without casting to an underlying type (atlas.Node).

Also, it seems like it with to mention that Map itself is not memory efficient so extension developers can learn it earlier.

Suggested Solution (optional)

An alternative can be something like:

func (ts *TagSet) Len() int {
	return (*atlas.Node)(ts).Len()
}

// Iterate memory efficient way of iterating all tags
func (ts *TagSet) Iterate(fn func(key, value string)) {
	if ts.Len() < 1 {
		return
	}

	n := (*atlas.Node)(ts)

	for !n.IsRoot() {
		prev, key, value := n.Data()
		fn(key, value)
		n = prev
	}
}

then the extension's method will look like:

labels := make([]*prompb.Label, 0, t.Len())
t.Iterate(func (key, value string) {
   labels = append(labels, &prompb.Label{Name: key, Value: value})
}) 
return labels

Already existing or connected issues / PRs (optional)

https://github.com/grafana/xk6-output-prometheus-remote/pull/55

贡献者指南