Skip to content

Commit

Permalink
feat(metrics): add additional labels to metrics
Browse files Browse the repository at this point in the history
feat(metrics): change additionalLabelsArray to array and use regex to extract labels

feat(metrics): add unit tests for BuildAdditionalLabelsValues function

feat(metrics): add err return value check.
  • Loading branch information
halleystar committed May 11, 2024
1 parent 9bdcaf1 commit 4578e29
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 4 deletions.
3 changes: 2 additions & 1 deletion pkg/exporter/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ type InspServerConfig struct {
}

type MetricsConfig struct {
Probes []ProbeConfig `yaml:"probes" mapstructure:"probes" json:"probes"`
Probes []ProbeConfig `yaml:"probes" mapstructure:"probes" json:"probes"`
AdditionalLabels []string `yaml:"additionalLabels" mapstructure:"additionalLabels" json:"additionalLabels"`
}

type EventConfig struct {
Expand Down
6 changes: 6 additions & 0 deletions pkg/exporter/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,12 @@ func (i *inspServer) start(cfg *InspServerConfig) error {
var err error
ctx := context.TODO()

err = probe.InitAdditionalLabels(cfg.MetricsConfig.AdditionalLabels)
if err != nil {
log.Errorf("failed init additional labels: %v", err)
return
}

log.Infof("start metrics server")
i.metricsServer, err = NewMetricsServer()
if err != nil {
Expand Down
7 changes: 7 additions & 0 deletions pkg/exporter/nettop/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ type Entity struct {
podMeta
initPid int
pids []int
labels map[string]string
}

func (e *Entity) String() string {
Expand All @@ -177,6 +178,10 @@ func (e *Entity) GetPodNamespace() string {
return e.podMeta.namespace
}

func (e *Entity) GetLabels() map[string]string {
return e.labels
}

func (e *Entity) IsHostNetwork() bool {
return e.netnsMeta.isHostNetwork
}
Expand Down Expand Up @@ -353,6 +358,7 @@ func cacheNetTopology(ctx context.Context) error {

namespace := sandbox.Metadata.Namespace
name := sandbox.Metadata.Name
labels := sandbox.Labels

sandboxStatus, err := criClient.PodSandboxStatus(sandbox.Id, true)
if err != nil {
Expand Down Expand Up @@ -411,6 +417,7 @@ func cacheNetTopology(ctx context.Context) error {
namespace: namespace,
},
initPid: info.Pid,
labels: labels,
pids: pids,
}

Expand Down
63 changes: 60 additions & 3 deletions pkg/exporter/probe/legacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package probe

import (
"fmt"
"regexp"
"strings"

"github.com/alibaba/kubeskoop/pkg/exporter/bpfutil"
"github.com/alibaba/kubeskoop/pkg/exporter/nettop"
Expand All @@ -12,9 +14,63 @@ import (
var legacyMetricsLabels = []string{"target_node", "target_namespace", "target_pod", "node", "namespace", "pod"}
var StandardMetricsLabels = []string{"k8s_node", "k8s_namespace", "k8s_pod"}
var TupleMetricsLabels = []string{"protocol", "src", "src_type", "src_node", "src_namespace", "src_pod", "dst", "dst_type", "dst_node", "dst_namespace", "dst_pod", "sport", "dport"}
var AdditionalLabelValueExpr []string

func BuildStandardMetricsLabelValues(entity *nettop.Entity) []string {
return []string{nettop.GetNodeName(), entity.GetPodNamespace(), entity.GetPodName()}
metaPodLabels := []string{nettop.GetNodeName(), entity.GetPodNamespace(), entity.GetPodName()}
return append(metaPodLabels, BuildAdditionalLabelsValues(entity.GetLabels())...)
}

func InitAdditionalLabels(additionalLabels []string) error {
if len(additionalLabels) == 0 {
return nil
}

//append to StandardMetricsLabels and AdditionalLabelValueExpr
for additionalKV := range additionalLabels {
labelKVPair := strings.Split(additionalLabels[additionalKV], "=")
StandardMetricsLabels = append(StandardMetricsLabels, strings.TrimSpace(labelKVPair[0]))
AdditionalLabelValueExpr = append(AdditionalLabelValueExpr, strings.TrimSpace(labelKVPair[1]))
}

return nil
}

func BuildAdditionalLabelsValues(podLabels map[string]string) []string {
if len(AdditionalLabelValueExpr) == 0 {
return []string{}
}

var values []string

var replaceAllStringSubmatchFunc = func(re *regexp.Regexp, str string, repl func([]string) string) string {
result := ""
lastIndex := 0

for _, v := range re.FindAllSubmatchIndex([]byte(str), -1) {
groups := []string{}
for i := 0; i < len(v); i += 2 {
groups = append(groups, str[v[i]:v[i+1]])
}

result += str[lastIndex:v[0]] + repl(groups)
lastIndex = v[1]
}

return result + str[lastIndex:]
}

for _, labelValueExpr := range AdditionalLabelValueExpr {
podLabelValue := replaceAllStringSubmatchFunc(regexp.MustCompile(`\${labels:(.*?)}`), labelValueExpr, func(groups []string) string {
if podLabelValue, ok := podLabels[groups[1]]; ok {
return podLabelValue
}
return ""
})
values = append(values, podLabelValue)
}

return values
}

type legacyBatchMetrics struct {
Expand Down Expand Up @@ -89,11 +145,12 @@ func (l *legacyBatchMetrics) Collect(metrics chan<- prometheus.Metric) {
if err != nil || et == nil {
continue
}
labelValues := []string{nettop.GetNodeName(), et.GetPodNamespace(), et.GetPodName()}
labelValues := BuildStandardMetricsLabelValues(et)
// for legacy pod labels
emit(newMetricsName(l.module, key), labelValues, float64(value))

labelValues = append(labelValues, labelValues...)
var metaPodData = []string{nettop.GetNodeName(), et.GetPodNamespace(), et.GetPodName()}
labelValues = append(metaPodData, metaPodData...)
emit(legacyMetricsName(l.module, key, l.underscore), labelValues, float64(value))
}
}
Expand Down
38 changes: 38 additions & 0 deletions pkg/exporter/probe/legacy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package probe

import (
"reflect"
"testing"
)

func TestBuildAdditionalLabelsValues1(t *testing.T) {
type args struct {
podLabels map[string]string
additionalLabels []string
}
tests := []struct {
name string
args args
want []string
}{
{"common", args{map[string]string{"l1": "v1", "l2": "v2"}, []string{"n1=alv1", "n2=alv2"}}, []string{"alv1", "alv2"}},
{"match", args{map[string]string{"l1": "v1", "l2": "v2"}, []string{"n1=${labels:l1}", "n2=alv2"}}, []string{"v1", "alv2"}},
{"submatch", args{map[string]string{"l1": "v1", "l2": "v2"}, []string{"n1=prefix_${labels:l1}_${labels:l2}_suffix"}}, []string{"prefix_v1_v2_suffix"}},
{"nomatch", args{map[string]string{"l1": "v1", "l2": "v2"}, []string{"n1=${labels:ln}"}}, []string{""}},
{"empty", args{map[string]string{"l1": "v1", "l2": "v2"}, []string{}}, []string{}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
AdditionalLabelValueExpr = []string{}
err := InitAdditionalLabels(tt.args.additionalLabels)
if err != nil {
t.Error(err)
return
}

if got := BuildAdditionalLabelsValues(tt.args.podLabels); !reflect.DeepEqual(got, tt.want) {
t.Errorf("BuildAdditionalLabelsValues() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit 4578e29

Please sign in to comment.