1
16
17 package main
18
19 import (
20 "fmt"
21 "go/ast"
22 "go/token"
23 "sort"
24 "strconv"
25 "strings"
26 "time"
27
28 "k8s.io/component-base/metrics"
29 )
30
31 func decodeMetricCalls(fs []*ast.CallExpr, metricsImportName string, variables map[string]ast.Expr) ([]metric, []error) {
32 finder := metricDecoder{
33 kubeMetricsImportName: metricsImportName,
34 variables: variables,
35 }
36 ms := make([]metric, 0, len(fs))
37 errors := []error{}
38 for _, f := range fs {
39 m, err := finder.decodeNewMetricCall(f)
40 if err != nil {
41 errors = append(errors, err)
42 continue
43 }
44 if m != nil {
45 ms = append(ms, *m)
46 }
47 }
48 return ms, errors
49 }
50
51 type metricDecoder struct {
52 kubeMetricsImportName string
53 variables map[string]ast.Expr
54 }
55
56 func (c *metricDecoder) decodeNewMetricCall(fc *ast.CallExpr) (*metric, error) {
57 var m metric
58 var err error
59 se, ok := fc.Fun.(*ast.SelectorExpr)
60 if !ok {
61
62 switch v := fc.Fun.(type) {
63 case *ast.Ident:
64 if v.Name == "NewTimingRatioHistogramVec" {
65 m, err = c.decodeMetricVecForTimingRatioHistogram(fc)
66 m.Type = timingRatioHistogram
67 return &m, err
68 }
69 }
70 return nil, newDecodeErrorf(fc, errNotDirectCall)
71 }
72 functionName := se.Sel.String()
73 functionImport, ok := se.X.(*ast.Ident)
74 if !ok {
75 return nil, newDecodeErrorf(fc, errNotDirectCall)
76 }
77 if functionImport.String() != c.kubeMetricsImportName {
78 return nil, nil
79 }
80 switch functionName {
81 case "NewCounter", "NewGauge", "NewHistogram", "NewSummary", "NewTimingHistogram", "NewGaugeFunc":
82 m, err = c.decodeMetric(fc)
83 case "NewCounterVec", "NewGaugeVec", "NewHistogramVec", "NewSummaryVec", "NewTimingHistogramVec":
84 m, err = c.decodeMetricVec(fc)
85 case "Labels", "HandlerOpts", "HandlerFor", "HandlerWithReset":
86 return nil, nil
87 case "NewDesc":
88 m, err = c.decodeDesc(fc)
89 default:
90 return &m, newDecodeErrorf(fc, errNotDirectCall)
91 }
92 if err != nil {
93 return &m, err
94 }
95 m.Type = getMetricType(functionName)
96 return &m, nil
97 }
98
99 func getMetricType(functionName string) string {
100 switch functionName {
101 case "NewDesc":
102 return customType
103 case "NewCounter", "NewCounterVec":
104 return counterMetricType
105 case "NewGauge", "NewGaugeVec", "NewGaugeFunc":
106 return gaugeMetricType
107 case "NewHistogram", "NewHistogramVec":
108 return histogramMetricType
109 case "NewSummary", "NewSummaryVec":
110 return summaryMetricType
111 case "NewTimingHistogram", "NewTimingHistogramVec", "NewTimingRatioHistogramVec":
112 return timingRatioHistogram
113 default:
114 panic("getMetricType expects correct function name")
115 }
116 }
117
118 func (c *metricDecoder) decodeMetric(call *ast.CallExpr) (metric, error) {
119 if len(call.Args) > 2 {
120 return metric{}, newDecodeErrorf(call, errInvalidNewMetricCall)
121 }
122 return c.decodeOpts(call.Args[0])
123 }
124
125 func (c *metricDecoder) decodeDesc(ce *ast.CallExpr) (metric, error) {
126 m := &metric{}
127 name, err := c.decodeString(ce.Args[0])
128 if err != nil {
129 return *m, newDecodeErrorf(ce, errorDecodingString)
130 }
131 m.Name = *name
132 help, err := c.decodeString(ce.Args[1])
133 if err != nil {
134 return *m, newDecodeErrorf(ce, errorDecodingString)
135 }
136 m.Help = *help
137 labels, err := c.decodeLabels(ce.Args[2])
138 if err != nil {
139 return *m, newDecodeErrorf(ce, errorDecodingLabels)
140 }
141 m.Labels = labels
142 cLabels, err := c.decodeConstLabels(ce.Args[3])
143 if err != nil {
144 return *m, newDecodeErrorf(ce, "can't decode const labels")
145 }
146 m.ConstLabels = cLabels
147 sl, err := decodeStabilityLevel(ce.Args[4], c.kubeMetricsImportName)
148 if err != nil {
149 return *m, newDecodeErrorf(ce, "can't decode stability level")
150 }
151 if sl != nil {
152 m.StabilityLevel = string(*sl)
153 }
154 deprecatedVersion, err := c.decodeString(ce.Args[5])
155 if err != nil {
156 return *m, newDecodeErrorf(ce, errorDecodingString)
157 }
158 if deprecatedVersion != nil {
159 m.DeprecatedVersion = *deprecatedVersion
160 }
161 return *m, nil
162 }
163
164 func (c *metricDecoder) decodeString(expr ast.Expr) (*string, error) {
165 switch e := expr.(type) {
166 case *ast.BasicLit:
167 value, err := stringValue(e)
168 if err != nil {
169 return nil, err
170 }
171 return &value, nil
172 case *ast.CallExpr:
173 firstArg, secondArg, thirdArg, err := c.decodeBuildFQNameArguments(e)
174 if err != nil {
175 return nil, newDecodeErrorf(expr, errNonStringAttribute)
176 }
177 se, ok := e.Fun.(*ast.SelectorExpr)
178 if ok {
179 functionName := se.Sel.Name
180 switch functionName {
181 case "BuildFQName":
182 n := metrics.BuildFQName(firstArg, secondArg, thirdArg)
183 return &n, nil
184 }
185 }
186 case *ast.Ident:
187 variableExpr, found := c.variables[e.Name]
188 if !found {
189 return nil, newDecodeErrorf(expr, errBadVariableAttribute)
190 }
191 bl, ok := variableExpr.(*ast.BasicLit)
192 if !ok {
193 return nil, newDecodeErrorf(expr, errNonStringAttribute)
194 }
195 value, err := stringValue(bl)
196 if err != nil {
197 return nil, err
198 }
199 return &value, nil
200 case *ast.SelectorExpr:
201 s, ok := e.X.(*ast.Ident)
202 if !ok {
203 return nil, newDecodeErrorf(expr, errExprNotIdent, e.X)
204 }
205 variableExpr, found := c.variables[strings.Join([]string{s.Name, e.Sel.Name}, ".")]
206 if !found {
207 return nil, newDecodeErrorf(expr, errBadImportedVariableAttribute)
208 }
209 bl, ok := variableExpr.(*ast.BasicLit)
210 if !ok {
211 return nil, newDecodeErrorf(expr, errNonStringAttribute)
212 }
213 value, err := stringValue(bl)
214 if err != nil {
215 return nil, err
216 }
217 return &value, nil
218 case *ast.BinaryExpr:
219 var binaryExpr *ast.BinaryExpr
220 binaryExpr = e
221 var okay bool
222 var value string
223 okay = true
224
225 for okay {
226 yV, okay := binaryExpr.Y.(*ast.BasicLit)
227 if !okay {
228 return nil, newDecodeErrorf(expr, errNonStringAttribute)
229 }
230 yVal, err := stringValue(yV)
231 if err != nil {
232 return nil, newDecodeErrorf(expr, errNonStringAttribute)
233 }
234 value = fmt.Sprintf("%s%s", yVal, value)
235 x, okay := binaryExpr.X.(*ast.BinaryExpr)
236 if !okay {
237
238 xV, okay := binaryExpr.X.(*ast.BasicLit)
239 if !okay {
240 return nil, newDecodeErrorf(expr, errNonStringAttribute)
241 }
242 xVal, err := stringValue(xV)
243 if err != nil {
244 return nil, newDecodeErrorf(expr, errNonStringAttribute)
245 }
246 value = fmt.Sprintf("%s%s", xVal, value)
247 break
248 }
249 binaryExpr = x
250 }
251 return &value, nil
252 }
253 return nil, newDecodeErrorf(expr, errorDecodingString)
254 }
255
256 func (c *metricDecoder) decodeMetricVec(call *ast.CallExpr) (metric, error) {
257 if len(call.Args) != 2 {
258 return metric{}, newDecodeErrorf(call, errInvalidNewMetricCall)
259 }
260 m, err := c.decodeOpts(call.Args[0])
261 if err != nil {
262 return m, err
263 }
264 labels, err := c.decodeLabels(call.Args[1])
265 if err != nil {
266 return m, err
267 }
268 sort.Strings(labels)
269 m.Labels = labels
270 return m, nil
271 }
272
273 func (c *metricDecoder) decodeMetricVecForTimingRatioHistogram(call *ast.CallExpr) (metric, error) {
274 m, err := c.decodeOpts(call.Args[0])
275 if err != nil {
276 return m, err
277 }
278 labels, err := c.decodeLabelsFromArray(call.Args[1:])
279 if err != nil {
280 return m, err
281 }
282 sort.Strings(labels)
283 m.Labels = labels
284 return m, nil
285 }
286
287 func (c *metricDecoder) decodeLabelsFromArray(exprs []ast.Expr) ([]string, error) {
288 retval := []string{}
289 for _, e := range exprs {
290 v, err := c.decodeString(e)
291 if err != nil || v == nil {
292 return nil, newDecodeErrorf(e, errNonStringAttribute)
293 }
294 retval = append(retval, *v)
295 }
296
297 return retval, nil
298 }
299
300 func (c *metricDecoder) decodeLabels(expr ast.Expr) ([]string, error) {
301 cl, ok := expr.(*ast.CompositeLit)
302 if !ok {
303 switch e := expr.(type) {
304 case *ast.Ident:
305 if e.Name == "nil" {
306 return []string{}, nil
307 }
308 variableExpr, found := c.variables[e.Name]
309 if !found {
310 return nil, newDecodeErrorf(expr, errorFindingVariableForLabels)
311 }
312 cl2, ok := variableExpr.(*ast.CompositeLit)
313 if !ok {
314 return nil, newDecodeErrorf(expr, errorFindingVariableForLabels)
315 }
316 cl = cl2
317 }
318 }
319 return c.decodeLabelsFromArray(cl.Elts)
320 }
321
322 func (c *metricDecoder) decodeOpts(expr ast.Expr) (metric, error) {
323 m := metric{
324 Labels: []string{},
325 }
326 ue, ok := expr.(*ast.UnaryExpr)
327 if !ok {
328 return m, newDecodeErrorf(expr, errInvalidNewMetricCall)
329 }
330 cl, ok := ue.X.(*ast.CompositeLit)
331 if !ok {
332 return m, newDecodeErrorf(expr, errInvalidNewMetricCall)
333 }
334
335 for _, expr := range cl.Elts {
336 kv, ok := expr.(*ast.KeyValueExpr)
337 if !ok {
338 return m, newDecodeErrorf(expr, errPositionalArguments)
339 }
340 key := fmt.Sprintf("%v", kv.Key)
341
342 switch key {
343 case "Namespace", "Subsystem", "Name", "Help", "DeprecatedVersion":
344 var value string
345 var err error
346 s, err := c.decodeString(kv.Value)
347 if err != nil {
348 return m, newDecodeErrorf(expr, err.Error())
349 }
350 value = *s
351 switch key {
352 case "Namespace":
353 m.Namespace = value
354 case "Subsystem":
355 m.Subsystem = value
356 case "Name":
357 m.Name = value
358 case "DeprecatedVersion":
359 m.DeprecatedVersion = value
360 case "Help":
361 m.Help = value
362 }
363 case "Buckets":
364 buckets, err := c.decodeBuckets(kv.Value)
365 if err != nil {
366 return m, err
367 }
368 sort.Float64s(buckets)
369 m.Buckets = buckets
370 case "StabilityLevel":
371 level, err := decodeStabilityLevel(kv.Value, c.kubeMetricsImportName)
372 if err != nil {
373 return m, err
374 }
375 m.StabilityLevel = string(*level)
376 case "ConstLabels":
377 labels, err := c.decodeConstLabels(kv.Value)
378 if err != nil {
379 return m, err
380 }
381 m.ConstLabels = labels
382 case "AgeBuckets", "BufCap":
383 uintVal, err := c.decodeUint32(kv.Value)
384 if err != nil {
385 print(key)
386 return m, err
387 }
388 if key == "AgeBuckets" {
389 m.AgeBuckets = uintVal
390 }
391 if key == "BufCap" {
392 m.BufCap = uintVal
393 }
394
395 case "Objectives":
396 obj, err := c.decodeObjectives(kv.Value)
397 if err != nil {
398 print(key)
399 return m, err
400 }
401 m.Objectives = obj
402 case "MaxAge":
403 int64Val, err := c.decodeInt64(kv.Value)
404 if err != nil {
405 return m, err
406 }
407 m.MaxAge = int64Val
408 default:
409 return m, newDecodeErrorf(expr, errFieldNotSupported, key)
410 }
411 }
412 return m, nil
413 }
414
415 func stringValue(bl *ast.BasicLit) (string, error) {
416 if bl.Kind != token.STRING {
417 return "", newDecodeErrorf(bl, errNonStringAttribute)
418 }
419 return strings.Trim(bl.Value, `"`), nil
420 }
421
422 func (c *metricDecoder) decodeBuckets(expr ast.Expr) ([]float64, error) {
423 switch v := expr.(type) {
424 case *ast.Ident:
425 variableExpr, found := c.variables[v.Name]
426 if !found {
427 return nil, newDecodeErrorf(v, "couldn't find variable for bucket")
428 }
429 switch v2 := variableExpr.(type) {
430 case *ast.CompositeLit:
431 return decodeListOfFloats(v2, v2.Elts)
432 case *ast.CallExpr:
433 float64s, err2, done := c.decodeBucketFunctionCall(v2)
434 if done {
435 return float64s, err2
436 }
437 default:
438 return nil, newDecodeErrorf(v, errorFindingVariableForBuckets)
439 }
440
441 case *ast.CompositeLit:
442 return decodeListOfFloats(v, v.Elts)
443 case *ast.SelectorExpr:
444 variableName := v.Sel.String()
445 importName, ok := v.X.(*ast.Ident)
446 if ok && importName.String() == c.kubeMetricsImportName && variableName == "DefBuckets" {
447 return metrics.DefBuckets, nil
448 }
449 case *ast.CallExpr:
450 float64s, err2, done := c.decodeBucketFunctionCall(v)
451 if done {
452 return float64s, err2
453 }
454 }
455 return nil, newDecodeErrorf(expr, errBuckets)
456 }
457
458 func (c *metricDecoder) decodeBucketFunctionCall(v *ast.CallExpr) ([]float64, error, bool) {
459 se, ok := v.Fun.(*ast.SelectorExpr)
460 if !ok {
461
462 if ai, ok := v.Fun.(*ast.Ident); ok && ai.Name == "merge" {
463 merged := []float64{}
464 for _, arg := range v.Args {
465 v2, ok := arg.(*ast.CallExpr)
466 if !ok {
467 return nil, newDecodeErrorf(v2, errBuckets), true
468 }
469 se, ok = v2.Fun.(*ast.SelectorExpr)
470 if ok {
471 functionName := se.Sel.String()
472 functionImport, ok := se.X.(*ast.Ident)
473 if !ok {
474 return nil, newDecodeErrorf(v, errBuckets), true
475 }
476 if functionImport.String() != c.kubeMetricsImportName {
477 return nil, newDecodeErrorf(v, errBuckets), true
478 }
479 firstArg, secondArg, thirdArg, err := decodeBucketArguments(v2)
480 if err != nil {
481 return nil, newDecodeErrorf(v, errBuckets), true
482 }
483 switch functionName {
484 case "LinearBuckets":
485 merged = append(merged, metrics.LinearBuckets(firstArg, secondArg, thirdArg)...)
486 case "ExponentialBuckets":
487 merged = append(merged, metrics.ExponentialBuckets(firstArg, secondArg, thirdArg)...)
488 case "ExponentialBucketsRange":
489 merged = append(merged, metrics.ExponentialBucketsRange(firstArg, secondArg, thirdArg)...)
490 }
491 }
492 }
493 return merged, nil, true
494 }
495 return nil, newDecodeErrorf(v, errBuckets), true
496 }
497 functionName := se.Sel.String()
498 functionImport, ok := se.X.(*ast.Ident)
499 if !ok {
500 return nil, newDecodeErrorf(v, errBuckets), true
501 }
502 if functionImport.String() != c.kubeMetricsImportName {
503 return nil, newDecodeErrorf(v, errBuckets), true
504 }
505 switch functionName {
506 case "LinearBuckets":
507 firstArg, secondArg, thirdArg, err := decodeBucketArguments(v)
508 if err != nil {
509 return nil, err, true
510 }
511 return metrics.LinearBuckets(firstArg, secondArg, thirdArg), nil, true
512 case "ExponentialBuckets":
513 firstArg, secondArg, thirdArg, err := decodeBucketArguments(v)
514 if err != nil {
515 return nil, err, true
516 }
517 return metrics.ExponentialBuckets(firstArg, secondArg, thirdArg), nil, true
518 case "ExponentialBucketsRange":
519 firstArg, secondArg, thirdArg, err := decodeBucketArguments(v)
520 if err != nil {
521 return nil, err, true
522 }
523 return metrics.ExponentialBucketsRange(firstArg, secondArg, thirdArg), nil, true
524 case "MergeBuckets":
525 merged := []float64{}
526 for _, arg := range v.Args {
527 switch argExpr := arg.(type) {
528 case *ast.CompositeLit:
529 fs, err := decodeListOfFloats(argExpr, argExpr.Elts)
530 if err != nil {
531 return nil, newDecodeErrorf(v, errBuckets), true
532 }
533 merged = append(merged, fs...)
534 case *ast.CallExpr:
535 se, ok = argExpr.Fun.(*ast.SelectorExpr)
536 if ok {
537 functionName := se.Sel.String()
538 functionImport, ok := se.X.(*ast.Ident)
539 if !ok {
540 return nil, newDecodeErrorf(v, errBuckets), true
541 }
542 if functionImport.String() != c.kubeMetricsImportName {
543 return nil, newDecodeErrorf(v, errBuckets), true
544 }
545 firstArg, secondArg, thirdArg, err := decodeBucketArguments(argExpr)
546 if err != nil {
547 return nil, newDecodeErrorf(v, errBuckets), true
548 }
549 switch functionName {
550 case "LinearBuckets":
551 merged = append(merged, metrics.LinearBuckets(firstArg, secondArg, thirdArg)...)
552 case "ExponentialBuckets":
553 merged = append(merged, metrics.LinearBuckets(firstArg, secondArg, thirdArg)...)
554 }
555 }
556 }
557 }
558 return merged, nil, true
559 }
560 return nil, nil, false
561 }
562
563 func (c *metricDecoder) decodeObjectives(expr ast.Expr) (map[float64]float64, error) {
564 switch v := expr.(type) {
565 case *ast.CompositeLit:
566 return decodeFloatMap(v.Elts)
567 case *ast.Ident:
568 variableExpr, found := c.variables[v.Name]
569 if !found {
570 return nil, newDecodeErrorf(expr, errBadVariableAttribute)
571 }
572 return decodeFloatMap(variableExpr.(*ast.CompositeLit).Elts)
573 }
574 return nil, newDecodeErrorf(expr, errObjectives)
575 }
576
577 func (c *metricDecoder) decodeUint32(expr ast.Expr) (uint32, error) {
578 switch v := expr.(type) {
579 case *ast.BasicLit:
580 if v.Kind != token.FLOAT && v.Kind != token.INT {
581 print(v.Kind)
582 }
583 value, err := strconv.ParseUint(v.Value, 10, 32)
584 if err != nil {
585 return 0, err
586 }
587 return uint32(value), nil
588 case *ast.SelectorExpr:
589 variableName := v.Sel.String()
590 importName, ok := v.X.(*ast.Ident)
591 if ok && importName.String() == c.kubeMetricsImportName {
592 if variableName == "DefAgeBuckets" {
593
594 return metrics.DefAgeBuckets, nil
595 }
596 if variableName == "DefBufCap" {
597
598 return metrics.DefBufCap, nil
599 }
600 }
601 case *ast.CallExpr:
602 _, ok := v.Fun.(*ast.SelectorExpr)
603 if !ok {
604 return 0, newDecodeErrorf(v, errDecodeUint32)
605 }
606 return 0, nil
607 }
608 return 0, newDecodeErrorf(expr, errDecodeUint32)
609 }
610
611 func (c *metricDecoder) decodeInt64(expr ast.Expr) (int64, error) {
612 switch v := expr.(type) {
613 case *ast.BasicLit:
614 if v.Kind != token.FLOAT && v.Kind != token.INT {
615 print(v.Kind)
616 }
617
618 value, err := strconv.ParseInt(v.Value, 10, 64)
619 if err != nil {
620 return 0, err
621 }
622 return value, nil
623 case *ast.SelectorExpr:
624 variableName := v.Sel.String()
625 importName, ok := v.X.(*ast.Ident)
626 if ok && importName.String() == c.kubeMetricsImportName {
627 if variableName == "DefMaxAge" {
628
629
630 return int64(metrics.DefMaxAge), nil
631 }
632 }
633 case *ast.Ident:
634 variableExpr, found := c.variables[v.Name]
635 if found {
636 be, ok := variableExpr.(*ast.BinaryExpr)
637 if ok {
638 i, err2, done := c.extractTimeExpression(be)
639 if done {
640 return i, err2
641 }
642 }
643 }
644 case *ast.CallExpr:
645 _, ok := v.Fun.(*ast.SelectorExpr)
646 if !ok {
647 return 0, newDecodeErrorf(v, errDecodeInt64)
648 }
649 return 0, nil
650 case *ast.BinaryExpr:
651 i, err2, done := c.extractTimeExpression(v)
652 if done {
653 return i, err2
654 }
655 }
656 return 0, newDecodeErrorf(expr, errDecodeInt64)
657 }
658
659 func (c *metricDecoder) extractTimeExpression(v *ast.BinaryExpr) (int64, error, bool) {
660 x := v.X.(*ast.BasicLit)
661 if x.Kind != token.FLOAT && x.Kind != token.INT {
662 print(x.Kind)
663 }
664
665 xValue, err := strconv.ParseInt(x.Value, 10, 64)
666 if err != nil {
667 return 0, err, true
668 }
669
670 switch y := v.Y.(type) {
671 case *ast.SelectorExpr:
672 variableName := y.Sel.String()
673 importName, ok := y.X.(*ast.Ident)
674 if ok && importName.String() == "time" {
675 if variableName == "Hour" {
676 return xValue * int64(time.Hour), nil, true
677 }
678 if variableName == "Minute" {
679 return xValue * int64(time.Minute), nil, true
680 }
681 if variableName == "Second" {
682 return xValue * int64(time.Second), nil, true
683 }
684 }
685 }
686 return 0, nil, false
687 }
688
689 func decodeFloatMap(exprs []ast.Expr) (map[float64]float64, error) {
690 buckets := map[float64]float64{}
691 for _, elt := range exprs {
692 bl, ok := elt.(*ast.KeyValueExpr)
693 if !ok {
694 return nil, newDecodeErrorf(bl, errObjectives)
695 }
696 keyExpr, ok := bl.Key.(*ast.BasicLit)
697 if !ok {
698 return nil, newDecodeErrorf(bl, errObjectives)
699 }
700 valueExpr, ok := bl.Value.(*ast.BasicLit)
701 if !ok {
702 return nil, newDecodeErrorf(bl, errObjectives)
703 }
704 valueForKey, err := strconv.ParseFloat(keyExpr.Value, 64)
705 if err != nil {
706 return nil, newDecodeErrorf(bl, errObjectives)
707 }
708 valueForValue, err := strconv.ParseFloat(valueExpr.Value, 64)
709 if err != nil {
710 return nil, newDecodeErrorf(bl, errObjectives)
711 }
712 buckets[valueForKey] = valueForValue
713 }
714 return buckets, nil
715 }
716
717 func decodeListOfFloats(expr ast.Expr, exprs []ast.Expr) ([]float64, error) {
718 buckets := make([]float64, len(exprs))
719 for i, elt := range exprs {
720 bl, ok := elt.(*ast.BasicLit)
721 if !ok {
722 return nil, newDecodeErrorf(expr, errBuckets)
723 }
724 if bl.Kind != token.FLOAT && bl.Kind != token.INT {
725 return nil, newDecodeErrorf(bl, errBuckets)
726 }
727 value, err := strconv.ParseFloat(bl.Value, 64)
728 if err != nil {
729 return nil, err
730 }
731 buckets[i] = value
732 }
733 return buckets, nil
734 }
735
736 func decodeBucketArguments(fc *ast.CallExpr) (float64, float64, int, error) {
737 if len(fc.Args) != 3 {
738 return 0, 0, 0, newDecodeErrorf(fc, errBuckets)
739 }
740 strArgs := make([]string, len(fc.Args))
741 for i, elt := range fc.Args {
742 bl, ok := elt.(*ast.BasicLit)
743 if !ok {
744 return 0, 0, 0, newDecodeErrorf(bl, errBuckets)
745 }
746 if bl.Kind != token.FLOAT && bl.Kind != token.INT {
747 return 0, 0, 0, newDecodeErrorf(bl, errBuckets)
748 }
749 strArgs[i] = bl.Value
750 }
751 firstArg, err := strconv.ParseFloat(strArgs[0], 64)
752 if err != nil {
753 return 0, 0, 0, newDecodeErrorf(fc.Args[0], errBuckets)
754 }
755 secondArg, err := strconv.ParseFloat(strArgs[1], 64)
756 if err != nil {
757 return 0, 0, 0, newDecodeErrorf(fc.Args[1], errBuckets)
758 }
759 thirdArg, err := strconv.ParseInt(strArgs[2], 10, 64)
760 if err != nil {
761 return 0, 0, 0, newDecodeErrorf(fc.Args[2], errBuckets)
762 }
763
764 return firstArg, secondArg, int(thirdArg), nil
765 }
766 func (c *metricDecoder) decodeBuildFQNameArguments(fc *ast.CallExpr) (string, string, string, error) {
767 if len(fc.Args) != 3 {
768 return "", "", "", newDecodeErrorf(fc, "can't decode fq name args")
769 }
770 strArgs := make([]string, len(fc.Args))
771 for i, elt := range fc.Args {
772 s, err := c.decodeString(elt)
773 if err != nil || s == nil {
774 return "", "", "", newDecodeErrorf(fc, err.Error())
775 }
776 strArgs[i] = *s
777 }
778 return strArgs[0], strArgs[1], strArgs[2], nil
779 }
780
781 func decodeStabilityLevel(expr ast.Expr, metricsFrameworkImportName string) (*metrics.StabilityLevel, error) {
782 se, ok := expr.(*ast.SelectorExpr)
783 if !ok {
784 return nil, newDecodeErrorf(expr, errStabilityLevel)
785 }
786 s, ok := se.X.(*ast.Ident)
787 if !ok {
788 return nil, newDecodeErrorf(expr, errStabilityLevel)
789 }
790 if s.String() != metricsFrameworkImportName {
791 return nil, newDecodeErrorf(expr, errStabilityLevel)
792 }
793
794 stability := metrics.StabilityLevel(se.Sel.Name)
795 return &stability, nil
796 }
797
798 func (c *metricDecoder) decodeConstLabels(expr ast.Expr) (map[string]string, error) {
799 retval := map[string]string{}
800 switch v := expr.(type) {
801 case *ast.CompositeLit:
802 for _, e2 := range v.Elts {
803 kv := e2.(*ast.KeyValueExpr)
804 key := ""
805 switch k := kv.Key.(type) {
806
807 case *ast.Ident:
808 variableExpr, found := c.variables[k.Name]
809 if !found {
810 return nil, newDecodeErrorf(expr, errBadVariableAttribute)
811 }
812 bl, ok := variableExpr.(*ast.BasicLit)
813 if !ok {
814 return nil, newDecodeErrorf(expr, errNonStringAttribute)
815 }
816 k2, err := stringValue(bl)
817 if err != nil {
818 return nil, err
819 }
820 key = k2
821 case *ast.BasicLit:
822 k2, err := stringValue(k)
823 if err != nil {
824 return nil, err
825 }
826 key = k2
827 }
828 val, err := stringValue(kv.Value.(*ast.BasicLit))
829 if err != nil {
830 return nil, err
831 }
832 retval[key] = val
833 }
834 }
835 return retval, nil
836 }
837
View as plain text