From 658d7a184e07460c78fc5acb843e83f7148b2efd Mon Sep 17 00:00:00 2001 From: Han Kang Date: Wed, 12 Oct 2022 09:33:43 -0700 Subject: [PATCH] parse time signatures for maxAge Change-Id: I91e330d82c4ebbfa38bc52889beb64e6689bfb77 --- test/instrumentation/decode_metric.go | 56 ++++++++++++++++++- .../testdata/pkg/kubelet/metrics/metrics.go | 25 +++++++++ .../testdata/test-stable-metrics-list.yaml | 14 +++++ 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/test/instrumentation/decode_metric.go b/test/instrumentation/decode_metric.go index 4ceeda7b516..c7e1f364148 100644 --- a/test/instrumentation/decode_metric.go +++ b/test/instrumentation/decode_metric.go @@ -24,6 +24,7 @@ import ( "sort" "strconv" "strings" + "time" "k8s.io/component-base/metrics" ) @@ -326,7 +327,6 @@ func (c *metricDecoder) decodeOpts(expr ast.Expr) (metric, error) { case "MaxAge": int64Val, err := c.decodeInt64(kv.Value) if err != nil { - print(key) return m, err } m.MaxAge = int64Val @@ -443,6 +443,7 @@ func (c *metricDecoder) decodeUint32(expr ast.Expr) (uint32, error) { func (c *metricDecoder) decodeInt64(expr ast.Expr) (int64, error) { switch v := expr.(type) { case *ast.BasicLit: + println("BasicLit") if v.Kind != token.FLOAT && v.Kind != token.INT { print(v.Kind) } @@ -453,8 +454,10 @@ func (c *metricDecoder) decodeInt64(expr ast.Expr) (int64, error) { } return value, nil case *ast.SelectorExpr: + println("SelectorExpr") variableName := v.Sel.String() importName, ok := v.X.(*ast.Ident) + println(variableName) if ok && importName.String() == c.kubeMetricsImportName { if variableName == "DefMaxAge" { // hardcode this for now. This is a duration but we'll output it as @@ -462,16 +465,67 @@ func (c *metricDecoder) decodeInt64(expr ast.Expr) (int64, error) { return 1000 * 1000 * 1000 * 60 * 10, nil } } + case *ast.Ident: + variableExpr, found := c.variables[v.Name] + if found { + be, ok := variableExpr.(*ast.BinaryExpr) + if ok { + i, err2, done := c.extractTimeExpression(be) + if done { + return i, err2 + } + } + + } + case *ast.CallExpr: + println("CallExpr") _, ok := v.Fun.(*ast.SelectorExpr) if !ok { return 0, newDecodeErrorf(v, errDecodeInt64) } return 0, nil + case *ast.BinaryExpr: + + i, err2, done := c.extractTimeExpression(v) + if done { + return i, err2 + } + } return 0, newDecodeErrorf(expr, errDecodeInt64) } +func (c *metricDecoder) extractTimeExpression(v *ast.BinaryExpr) (int64, error, bool) { + x := v.X.(*ast.BasicLit) + if x.Kind != token.FLOAT && x.Kind != token.INT { + print(x.Kind) + } + + xValue, err := strconv.ParseInt(x.Value, 10, 64) + if err != nil { + return 0, err, true + } + + switch y := v.Y.(type) { + case *ast.SelectorExpr: + variableName := y.Sel.String() + importName, ok := y.X.(*ast.Ident) + if ok && importName.String() == "time" { + if variableName == "Hour" { + return xValue * int64(time.Hour), nil, true + } + if variableName == "Minute" { + return xValue * int64(time.Minute), nil, true + } + if variableName == "Second" { + return xValue * int64(time.Second), nil, true + } + } + } + return 0, nil, false +} + func decodeFloatMap(exprs []ast.Expr) (map[float64]float64, error) { buckets := map[float64]float64{} for _, elt := range exprs { diff --git a/test/instrumentation/testdata/pkg/kubelet/metrics/metrics.go b/test/instrumentation/testdata/pkg/kubelet/metrics/metrics.go index 1ebd1acac04..5a8181c6ab5 100644 --- a/test/instrumentation/testdata/pkg/kubelet/metrics/metrics.go +++ b/test/instrumentation/testdata/pkg/kubelet/metrics/metrics.go @@ -77,6 +77,8 @@ var ( defObjectives = map[float64]float64{0.5: 0.5, 0.75: 0.75} testBuckets = []float64{0, 0.5, 1.0} testLabels = []string{"a", "b", "c"} + maxAge = 2 * time.Minute + // NodeName is a Gauge that tracks the ode's name. The count is always 1. NodeName = metrics.NewGaugeVec( &metrics.GaugeOpts{ @@ -109,6 +111,29 @@ var ( }, testLabels, ) + // PodWorkerDuration is a Histogram that tracks the duration (in seconds) in takes to sync a single pod. + // Broken down by the operation type. + SummaryMaxAge = metrics.NewSummary( + &metrics.SummaryOpts{ + Subsystem: KubeletSubsystem, + Name: "max_age", + Help: "Duration in seconds to sync a single pod. Broken down by operation type: create, update, or sync", + StabilityLevel: metrics.BETA, + MaxAge: 2 * time.Hour, + }, + ) + + // PodWorkerDuration is a Histogram that tracks the duration (in seconds) in takes to sync a single pod. + // Broken down by the operation type. + SummaryMaxAgeConst = metrics.NewSummary( + &metrics.SummaryOpts{ + Subsystem: KubeletSubsystem, + Name: "max_age_const", + Help: "Duration in seconds to sync a single pod. Broken down by operation type: create, update, or sync", + StabilityLevel: metrics.BETA, + MaxAge: maxAge, + }, + ) // PodStartDuration is a Histogram that tracks the duration (in seconds) it takes for a single pod to go from pending to running. PodStartDuration = metrics.NewHistogram( &metrics.HistogramOpts{ diff --git a/test/instrumentation/testdata/test-stable-metrics-list.yaml b/test/instrumentation/testdata/test-stable-metrics-list.yaml index 668daa62d7b..d6cc66b59aa 100644 --- a/test/instrumentation/testdata/test-stable-metrics-list.yaml +++ b/test/instrumentation/testdata/test-stable-metrics-list.yaml @@ -25,6 +25,20 @@ - 2.5 - 5 - 10 +- name: max_age + subsystem: kubelet + help: 'Duration in seconds to sync a single pod. Broken down by operation type: + create, update, or sync' + type: Summary + stabilityLevel: BETA + maxAge: 7200000000000 +- name: max_age_const + subsystem: kubelet + help: 'Duration in seconds to sync a single pod. Broken down by operation type: + create, update, or sync' + type: Summary + stabilityLevel: BETA + maxAge: 120000000000 - name: multiline subsystem: kubelet help: Cumulative number of pod preemptions by preemption resource asdf asdf asdf