aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/yeya24
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2025-01-22 16:07:17 +0100
committerTaras Madan <tarasmadan@google.com>2025-01-23 10:42:36 +0000
commit7b4377ad9d8a7205416df8d6217ef2b010f89481 (patch)
treee6fec4fd12ff807a16d847923f501075bf71d16c /vendor/github.com/yeya24
parent475a4c203afb8b7d3af51c4fd32bb170ff32a45e (diff)
vendor: delete
Diffstat (limited to 'vendor/github.com/yeya24')
-rw-r--r--vendor/github.com/yeya24/promlinter/.gitignore20
-rw-r--r--vendor/github.com/yeya24/promlinter/LICENSE201
-rw-r--r--vendor/github.com/yeya24/promlinter/Makefile39
-rw-r--r--vendor/github.com/yeya24/promlinter/README.md80
-rw-r--r--vendor/github.com/yeya24/promlinter/promlinter.go831
5 files changed, 0 insertions, 1171 deletions
diff --git a/vendor/github.com/yeya24/promlinter/.gitignore b/vendor/github.com/yeya24/promlinter/.gitignore
deleted file mode 100644
index bffb9a029..000000000
--- a/vendor/github.com/yeya24/promlinter/.gitignore
+++ /dev/null
@@ -1,20 +0,0 @@
-# Binaries for programs and plugins
-*.exe
-*.exe~
-*.dll
-*.so
-*.dylib
-
-# Test binary, built with `go test -c`
-*.test
-
-# binary
-bin
-
-# Output of the go coverage tool, specifically when used with LiteIDE
-*.out
-
-# Dependency directories (remove the comment below to include it)
-# vendor/
-
-.idea
diff --git a/vendor/github.com/yeya24/promlinter/LICENSE b/vendor/github.com/yeya24/promlinter/LICENSE
deleted file mode 100644
index 261eeb9e9..000000000
--- a/vendor/github.com/yeya24/promlinter/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/vendor/github.com/yeya24/promlinter/Makefile b/vendor/github.com/yeya24/promlinter/Makefile
deleted file mode 100644
index d50db1ee7..000000000
--- a/vendor/github.com/yeya24/promlinter/Makefile
+++ /dev/null
@@ -1,39 +0,0 @@
-GOOS := $(if $(GOOS),$(GOOS),linux)
-GOARCH := $(if $(GOARCH),$(GOARCH),amd64)
-GO=CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) GO111MODULE=on go
-GOVERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1)
-
-GIT_COMMIT = $(shell git rev-parse --short HEAD)
-
-BUILDFLAGS ?=
-
-ifeq ($(shell expr ${GOVERSION} \>= 1.14), 1)
- BUILDFLAGS += -mod=mod
-endif
-
-PACKAGE_LIST := go list ./...
-PACKAGES := $$($(PACKAGE_LIST))
-FILES_TO_FMT := $(shell find . -path -prune -o -name '*.go' -print)
-
-all: format build test
-
-format: vet fmt
-
-fmt:
- @echo "gofmt"
- @gofmt -w ${FILES_TO_FMT}
- @git diff --exit-code .
-
-build: mod
- $(GO) build ${BUILDFLAGS} -o ./bin/promlinter cmd/promlinter/main.go
-
-vet:
- $(GO) vet ${BUILDFLAGS} ./...
-
-mod:
- @echo "go mod tidy"
- $(GO) mod tidy
- @git diff --exit-code -- go.mod
-
-test:
- $(GO) test ${BUILDFLAGS} ./... -cover $(PACKAGES)
diff --git a/vendor/github.com/yeya24/promlinter/README.md b/vendor/github.com/yeya24/promlinter/README.md
deleted file mode 100644
index 4fbffaa6b..000000000
--- a/vendor/github.com/yeya24/promlinter/README.md
+++ /dev/null
@@ -1,80 +0,0 @@
-# promlinter
-
-A linter for checking Prometheus metrics name via promlint.
-
-![usage](assets/promlinter.gif)
-
-## Installation
-
-### Go Get
-
-go get github.com/yeya24/promlinter/cmd/promlinter
-
-### Download from release
-
-Please go to https://github.com/yeya24/promlinter/releases.
-
-### Build from source
-
-#### Requirements
-
-- Go >= 1.13
-- make
-
-``` bash
-git clone https://github.com/yeya24/promlinter.git
-make build
-```
-
-Then you can find the `promlinter` binary file in the `./bin` directory.
-
-## Usage
-
-``` bash
-usage: promlinter [<flags>] <command> [<args> ...]
-
-Prometheus metrics linter for Go code.
-
-This tool can cover most of the patterns of metrics naming issues, but it cannot detect metric values that can only be determined in the runtime.
-
-By default it doesn't output parsing failures, if you want to see them, you can add --strict flag to enable it.
-
-It is also supported to disable the lint functions using repeated flag --disable. Current supported functions are:
-
- [Help]: Help detects issues related to the help text for a metric.
-
- [MetricUnits]: MetricUnits detects issues with metric unit names.
-
- [Counter]: Counter detects issues specific to counters, as well as patterns that should only be used with counters.
-
- [HistogramSummaryReserved]: HistogramSummaryReserved detects when other types of metrics use names or labels reserved for use by histograms and/or summaries.
-
- [MetricTypeInName]: MetricTypeInName detects when metric types are included in the metric name.
-
- [ReservedChars]: ReservedChars detects colons in metric names.
-
- [CamelCase]: CamelCase detects metric names and label names written in camelCase.
-
- [UnitAbbreviations]: UnitAbbreviations detects abbreviated units in the metric name.
-
-Flags:
- -h, --help Show context-sensitive help (also try --help-long and --help-man).
- --version Show application version.
-
-Commands:
- help [<command>...]
- Show help.
-
- list [<flags>] [<files>...]
- List metrics name.
-
- lint [<flags>] [<files>...]
- Lint metrics via promlint.
-
-```
-
-## Run tests
-
-``` bash
-make test
-```
diff --git a/vendor/github.com/yeya24/promlinter/promlinter.go b/vendor/github.com/yeya24/promlinter/promlinter.go
deleted file mode 100644
index 17a7f4c3e..000000000
--- a/vendor/github.com/yeya24/promlinter/promlinter.go
+++ /dev/null
@@ -1,831 +0,0 @@
-package promlinter
-
-import (
- "fmt"
- "go/ast"
- "go/token"
- "sort"
- "strconv"
- "strings"
-
- "github.com/prometheus/client_golang/prometheus"
- "github.com/prometheus/client_golang/prometheus/testutil/promlint"
- dto "github.com/prometheus/client_model/go"
-)
-
-var (
- metricsType map[string]dto.MetricType
- constMetricArgNum map[string]int
- validOptsFields map[string]bool
- lintFuncText map[string][]string
- LintFuncNames []string
-)
-
-func init() {
- metricsType = map[string]dto.MetricType{
- "Counter": dto.MetricType_COUNTER,
- "NewCounter": dto.MetricType_COUNTER,
- "NewCounterVec": dto.MetricType_COUNTER,
- "Gauge": dto.MetricType_GAUGE,
- "NewGauge": dto.MetricType_GAUGE,
- "NewGaugeVec": dto.MetricType_GAUGE,
- "NewHistogram": dto.MetricType_HISTOGRAM,
- "NewHistogramVec": dto.MetricType_HISTOGRAM,
- "NewSummary": dto.MetricType_SUMMARY,
- "NewSummaryVec": dto.MetricType_SUMMARY,
- }
-
- constMetricArgNum = map[string]int{
- "MustNewConstMetric": 3,
- "MustNewHistogram": 4,
- "MustNewSummary": 4,
- "NewLazyConstMetric": 3,
- }
-
- // Doesn't contain ConstLabels since we don't need this field here.
- validOptsFields = map[string]bool{
- "Name": true,
- "Namespace": true,
- "Subsystem": true,
- "Help": true,
- }
-
- lintFuncText = map[string][]string{
- "Help": {"no help text"},
- "MetricUnits": {"use base unit"},
- "Counter": {"counter metrics should"},
- "HistogramSummaryReserved": {"non-histogram", "non-summary"},
- "MetricTypeInName": {"metric name should not include type"},
- "ReservedChars": {"metric names should not contain ':'"},
- "CamelCase": {"'snake_case' not 'camelCase'"},
- "lintUnitAbbreviations": {"metric names should not contain abbreviated units"},
- }
-
- LintFuncNames = []string{"Help", "MetricUnits", "Counter", "HistogramSummaryReserved",
- "MetricTypeInName", "ReservedChars", "CamelCase", "lintUnitAbbreviations"}
-}
-
-type Setting struct {
- Strict bool
- DisabledLintFuncs []string
-}
-
-// Issue contains metric name, error text and metric position.
-type Issue struct {
- Text string
- Metric string
- Pos token.Position
-}
-
-type MetricFamilyWithPos struct {
- MetricFamily *dto.MetricFamily
- Pos token.Position
-}
-
-func (m *MetricFamilyWithPos) Labels() []string {
- var arr []string
- if len(m.MetricFamily.Metric) > 0 {
- for _, label := range m.MetricFamily.Metric[0].Label {
- if label.Value != nil {
- arr = append(arr,
- fmt.Sprintf("%s=%s",
- strings.Trim(*label.Name, `"`),
- strings.Trim(*label.Value, `"`)))
- } else {
- arr = append(arr, strings.Trim(*label.Name, `"`))
- }
- }
- }
- return arr
-}
-
-type visitor struct {
- fs *token.FileSet
- metrics []MetricFamilyWithPos
- issues []Issue
- strict bool
-}
-
-type opt struct {
- namespace string
- subsystem string
- name string
-
- help string
- helpSet bool
-
- labels []string
- constLabels map[string]string
-}
-
-func RunList(fs *token.FileSet, files []*ast.File, strict bool) []MetricFamilyWithPos {
- v := &visitor{
- fs: fs,
- metrics: make([]MetricFamilyWithPos, 0),
- issues: make([]Issue, 0),
- strict: strict,
- }
-
- for _, file := range files {
- ast.Walk(v, file)
- }
-
- sort.Slice(v.metrics, func(i, j int) bool {
- return v.metrics[i].Pos.String() < v.metrics[j].Pos.String()
- })
- return v.metrics
-}
-
-func RunLint(fs *token.FileSet, files []*ast.File, s Setting) []Issue {
- v := &visitor{
- fs: fs,
- metrics: make([]MetricFamilyWithPos, 0),
- issues: make([]Issue, 0),
- strict: s.Strict,
- }
-
- for _, file := range files {
- ast.Walk(v, file)
- }
-
- // lint metrics
- for _, mfp := range v.metrics {
- problems, err := promlint.NewWithMetricFamilies([]*dto.MetricFamily{mfp.MetricFamily}).Lint()
- if err != nil {
- panic(err)
- }
-
- for _, p := range problems {
- for _, disabledFunc := range s.DisabledLintFuncs {
- for _, pattern := range lintFuncText[disabledFunc] {
- if strings.Contains(p.Text, pattern) {
- goto END
- }
- }
- }
-
- v.issues = append(v.issues, Issue{
- Pos: mfp.Pos,
- Metric: p.Metric,
- Text: p.Text,
- })
-
- END:
- }
- }
-
- return v.issues
-}
-
-func (v *visitor) Visit(n ast.Node) ast.Visitor {
- if n == nil {
- return v
- }
-
- switch t := n.(type) {
- case *ast.CallExpr:
- return v.parseCallerExpr(t)
-
- case *ast.SendStmt:
- return v.parseSendMetricChanExpr(t)
-
- default:
- }
-
- return v
-}
-
-func (v *visitor) addMetric(mfp *MetricFamilyWithPos) {
- for _, m := range v.metrics {
- if mfp.MetricFamily.String() == m.MetricFamily.String() {
- return
- }
- }
-
- v.metrics = append(v.metrics, *mfp)
-}
-
-func (v *visitor) parseCallerExpr(call *ast.CallExpr) ast.Visitor {
- var (
- metricType dto.MetricType
- methodName string
- ok bool
- )
-
- switch stmt := call.Fun.(type) {
-
- /*
- That's the case of setting alias . to client_golang/prometheus or promauto package.
-
- import . "github.com/prometheus/client_golang/prometheus"
- metric := NewCounter(CounterOpts{})
- */
- case *ast.Ident:
- if stmt.Name == "NewCounterFunc" {
- return v.parseOpts(call.Args, dto.MetricType_COUNTER)
- }
-
- if stmt.Name == "NewGaugeFunc" {
- return v.parseOpts(call.Args, dto.MetricType_GAUGE)
- }
-
- if metricType, ok = metricsType[stmt.Name]; !ok {
- return v
- }
-
- methodName = stmt.Name
-
- /*
- This case covers the most of cases to initialize metrics.
-
- prometheus.NewCounter(CounterOpts{})
-
- promauto.With(nil).NewCounter(CounterOpts{})
-
- factory := promauto.With(nil)
- factory.NewCounter(CounterOpts{})
-
- prometheus.NewCounterFunc()
- */
- case *ast.SelectorExpr:
- if stmt.Sel.Name == "NewCounterFunc" {
- return v.parseOpts(call.Args, dto.MetricType_COUNTER)
- }
-
- if stmt.Sel.Name == "NewGaugeFunc" {
- return v.parseOpts(call.Args, dto.MetricType_GAUGE)
- }
-
- if stmt.Sel.Name == "NewFamilyGenerator" && len(call.Args) == 5 {
- return v.parseKSMMetrics(call.Args[0], call.Args[1], call.Args[2])
- }
-
- if metricType, ok = metricsType[stmt.Sel.Name]; !ok {
- return v
- }
-
- methodName = stmt.Sel.Name
-
- default:
- return v
- }
-
- argNum := 1
- if strings.HasSuffix(methodName, "Vec") {
- argNum = 2
- }
- // The methods used to initialize metrics should have at least one arg.
- if len(call.Args) < argNum && v.strict {
- v.issues = append(v.issues, Issue{
- Pos: v.fs.Position(call.Pos()),
- Metric: "",
- Text: fmt.Sprintf("%s should have at least %d arguments", methodName, argNum),
- })
- return v
- }
-
- if len(call.Args) == 0 {
- return v
- }
-
- return v.parseOpts(call.Args, metricType)
-}
-
-func (v *visitor) parseOpts(optArgs []ast.Expr, metricType dto.MetricType) ast.Visitor {
- // position for the first arg of the CallExpr
- optsPosition := v.fs.Position(optArgs[0].Pos())
- opts := v.parseOptsExpr(optArgs[0])
-
- var metric *dto.Metric
- if len(optArgs) > 1 {
- // parse labels
- if labelOpts := v.parseOptsExpr(optArgs[1]); labelOpts != nil && len(labelOpts.labels) > 0 {
- metric = &dto.Metric{}
- for idx, _ := range labelOpts.labels {
- metric.Label = append(metric.Label,
- &dto.LabelPair{
- Name: &labelOpts.labels[idx],
- })
- }
- }
- }
-
- if opts == nil {
- return v
- }
-
- currentMetric := dto.MetricFamily{
- Type: &metricType,
- }
-
- if !opts.helpSet {
- currentMetric.Help = nil
- } else {
- currentMetric.Help = &opts.help
- }
-
- if metric != nil {
- currentMetric.Metric = append(currentMetric.Metric, metric)
- }
-
- metricName := prometheus.BuildFQName(opts.namespace, opts.subsystem, opts.name)
- // We skip the invalid metric if the name is an empty string.
- // This kind of metric declaration might be used as a stud metric
- // https://github.com/thanos-io/thanos/blob/main/cmd/thanos/tools_bucket.go#L538.
- if metricName == "" {
- return v
- }
- currentMetric.Name = &metricName
-
- v.addMetric(&MetricFamilyWithPos{MetricFamily: &currentMetric, Pos: optsPosition})
- return v
-}
-
-// Parser for kube-state-metrics generators.
-func (v *visitor) parseKSMMetrics(nameArg ast.Node, helpArg ast.Node, metricTypeArg ast.Node) ast.Visitor {
- optsPosition := v.fs.Position(nameArg.Pos())
- currentMetric := dto.MetricFamily{}
- name, ok := v.parseValue("name", nameArg)
- if !ok {
- return v
- }
- currentMetric.Name = &name
-
- help, ok := v.parseValue("help", helpArg)
- if !ok {
- return v
- }
- currentMetric.Help = &help
-
- switch stmt := metricTypeArg.(type) {
- case *ast.SelectorExpr:
- if metricType, ok := metricsType[stmt.Sel.Name]; !ok {
- return v
- } else {
- currentMetric.Type = &metricType
- }
- }
-
- v.addMetric(&MetricFamilyWithPos{MetricFamily: &currentMetric, Pos: optsPosition})
-
- return v
-}
-
-func (v *visitor) parseSendMetricChanExpr(chExpr *ast.SendStmt) ast.Visitor {
- var (
- ok bool
- requiredArgNum int
- methodName string
- metricType dto.MetricType
- )
-
- call, ok := chExpr.Value.(*ast.CallExpr)
- if !ok {
- return v
- }
-
- switch stmt := call.Fun.(type) {
- case *ast.Ident:
- if requiredArgNum, ok = constMetricArgNum[stmt.Name]; !ok {
- return v
- }
- methodName = stmt.Name
-
- case *ast.SelectorExpr:
- if requiredArgNum, ok = constMetricArgNum[stmt.Sel.Name]; !ok {
- return v
- }
- methodName = stmt.Sel.Name
- }
-
- if len(call.Args) < requiredArgNum && v.strict {
- v.issues = append(v.issues, Issue{
- Metric: "",
- Pos: v.fs.Position(call.Pos()),
- Text: fmt.Sprintf("%s should have at least %d arguments", methodName, requiredArgNum),
- })
- return v
- }
-
- if len(call.Args) == 0 {
- return v
- }
-
- descCall := v.parseConstMetricOptsExpr(call.Args[0])
- if descCall == nil {
- return v
- }
-
- metric := &dto.MetricFamily{
- Name: descCall.name,
- Help: descCall.help,
- }
-
- if len(descCall.labels) > 0 {
- m := &dto.Metric{}
- for idx, _ := range descCall.labels {
- m.Label = append(m.Label,
- &dto.LabelPair{
- Name: &descCall.labels[idx],
- })
- }
-
- for idx, _ := range descCall.constLabels {
- m.Label = append(m.Label,
- &dto.LabelPair{
- Name: &descCall.constLabels[idx][0],
- Value: &descCall.constLabels[idx][1],
- })
- }
-
- metric.Metric = append(metric.Metric, m)
- }
-
- switch methodName {
- case "MustNewConstMetric", "NewLazyConstMetric":
- switch t := call.Args[1].(type) {
- case *ast.Ident:
- metric.Type = getConstMetricType(t.Name)
- case *ast.SelectorExpr:
- metric.Type = getConstMetricType(t.Sel.Name)
- }
-
- case "MustNewHistogram":
- metricType = dto.MetricType_HISTOGRAM
- metric.Type = &metricType
- case "MustNewSummary":
- metricType = dto.MetricType_SUMMARY
- metric.Type = &metricType
- }
-
- v.addMetric(&MetricFamilyWithPos{MetricFamily: metric, Pos: v.fs.Position(call.Pos())})
- return v
-}
-
-func (v *visitor) parseOptsExpr(n ast.Node) *opt {
- switch stmt := n.(type) {
- case *ast.CompositeLit:
- return v.parseCompositeOpts(stmt)
-
- case *ast.Ident:
- if stmt.Obj != nil {
- if decl, ok := stmt.Obj.Decl.(*ast.AssignStmt); ok && len(decl.Rhs) > 0 {
- if t, ok := decl.Rhs[0].(*ast.CompositeLit); ok {
- return v.parseCompositeOpts(t)
- }
- }
- }
-
- case *ast.UnaryExpr:
- return v.parseOptsExpr(stmt.X)
- }
-
- return nil
-}
-
-func (v *visitor) parseCompositeOpts(stmt *ast.CompositeLit) *opt {
- metricOption := &opt{}
-
- for _, elt := range stmt.Elts {
-
- // labels
- label, ok := elt.(*ast.BasicLit)
- if ok {
- metricOption.labels = append(metricOption.labels, strings.Trim(label.Value, `"`))
- continue
- }
-
- kvExpr, ok := elt.(*ast.KeyValueExpr)
- if !ok {
- continue
- }
-
- // const labels
- if key, ok := kvExpr.Key.(*ast.BasicLit); ok {
-
- if metricOption.constLabels == nil {
- metricOption.constLabels = map[string]string{}
- }
-
- // only accept literal string value
- //
- // {
- // "key": "some-string-literal",
- // }
- switch val := kvExpr.Value.(type) {
- case *ast.BasicLit:
- metricOption.constLabels[key.Value] = val.Value
-
- default:
- metricOption.constLabels[key.Value] = "?" // use a placeholder for the const label
- }
-
- continue
- }
-
- object, ok := kvExpr.Key.(*ast.Ident)
- if !ok {
- continue
- }
-
- if _, ok := validOptsFields[object.Name]; !ok {
- continue
- }
-
- // If failed to parse field value, stop parsing.
- stringLiteral, ok := v.parseValue(object.Name, kvExpr.Value)
- if !ok {
- return nil
- }
-
- switch object.Name {
- case "Namespace":
- metricOption.namespace = stringLiteral
- case "Subsystem":
- metricOption.subsystem = stringLiteral
- case "Name":
- metricOption.name = stringLiteral
- case "Help":
- metricOption.help = stringLiteral
- metricOption.helpSet = true
- }
- }
-
- return metricOption
-}
-
-func (v *visitor) parseValue(object string, n ast.Node) (string, bool) {
-
- switch t := n.(type) {
-
- // make sure it is string literal value
- case *ast.BasicLit:
- if t.Kind == token.STRING {
- return mustUnquote(t.Value), true
- }
-
- return "", false
-
- case *ast.Ident:
- if t.Obj == nil {
- return "", false
- }
-
- switch vs := t.Obj.Decl.(type) {
-
- case *ast.ValueSpec:
- // var some string = "some string"
- return v.parseValue(object, vs)
-
- case *ast.AssignStmt:
- // TODO:
- // some := "some string"
- return "", false
-
- default:
- return "", false
- }
-
- case *ast.ValueSpec:
- if len(t.Values) == 0 {
- return "", false
- }
-
- return v.parseValue(object, t.Values[0])
-
- // For binary expr, we only support adding two strings like `foo` + `bar`.
- case *ast.BinaryExpr:
- if t.Op == token.ADD {
- x, ok := v.parseValue(object, t.X)
- if !ok {
- return "", false
- }
-
- y, ok := v.parseValue(object, t.Y)
- if !ok {
- return "", false
- }
-
- return x + y, true
- }
-
- // We can only cover some basic cases here
- case *ast.CallExpr:
- return v.parseValueCallExpr(object, t)
-
- default:
- if v.strict {
- v.issues = append(v.issues, Issue{
- Pos: v.fs.Position(n.Pos()),
- Metric: "",
- Text: fmt.Sprintf("parsing %s with type %T is not supported", object, t),
- })
- }
- }
-
- return "", false
-}
-
-func (v *visitor) parseValueCallExpr(object string, call *ast.CallExpr) (string, bool) {
- var (
- methodName string
- namespace string
- subsystem string
- name string
- ok bool
- )
- switch expr := call.Fun.(type) {
- case *ast.SelectorExpr:
- methodName = expr.Sel.Name
- case *ast.Ident:
- methodName = expr.Name
- default:
- return "", false
- }
-
- if methodName == "BuildFQName" && len(call.Args) == 3 {
- namespace, ok = v.parseValue("namespace", call.Args[0])
- if !ok {
- return "", false
- }
- subsystem, ok = v.parseValue("subsystem", call.Args[1])
- if !ok {
- return "", false
- }
- name, ok = v.parseValue("name", call.Args[2])
- if !ok {
- return "", false
- }
- return prometheus.BuildFQName(namespace, subsystem, name), true
- }
-
- if v.strict {
- v.issues = append(v.issues, Issue{
- Metric: "",
- Pos: v.fs.Position(call.Pos()),
- Text: fmt.Sprintf("parsing %s with function %s is not supported", object, methodName),
- })
- }
-
- return "", false
-}
-
-func (v *visitor) parseConstMetricOptsExpr(n ast.Node) *descCallExpr {
- switch stmt := n.(type) {
- case *ast.CallExpr:
- return v.parseNewDescCallExpr(stmt)
-
- case *ast.Ident:
- if stmt.Obj != nil {
- switch t := stmt.Obj.Decl.(type) {
- case *ast.AssignStmt:
- if len(t.Rhs) > 0 {
- if call, ok := t.Rhs[0].(*ast.CallExpr); ok {
- return v.parseNewDescCallExpr(call)
- }
- }
- case *ast.ValueSpec:
- if len(t.Values) > 0 {
- if call, ok := t.Values[0].(*ast.CallExpr); ok {
- return v.parseNewDescCallExpr(call)
- }
- }
- }
-
- if v.strict {
- v.issues = append(v.issues, Issue{
- Pos: v.fs.Position(stmt.Pos()),
- Metric: "",
- Text: fmt.Sprintf("parsing desc of type %T is not supported", stmt.Obj.Decl),
- })
- }
- }
-
- default:
- if v.strict {
- v.issues = append(v.issues, Issue{
- Pos: v.fs.Position(stmt.Pos()),
- Metric: "",
- Text: fmt.Sprintf("parsing desc of type %T is not supported", stmt),
- })
- }
- }
-
- return nil
-}
-
-type descCallExpr struct {
- name, help *string
- labels []string
- constLabels [][2]string
-}
-
-func (v *visitor) parseNewDescCallExpr(call *ast.CallExpr) *descCallExpr {
- var (
- help string
- name string
- ok bool
- )
-
- switch expr := call.Fun.(type) {
- case *ast.Ident:
- if expr.Name != "NewDesc" {
- if v.strict {
- v.issues = append(v.issues, Issue{
- Pos: v.fs.Position(expr.Pos()),
- Metric: "",
- Text: fmt.Sprintf("parsing desc with function %s is not supported", expr.Name),
- })
- }
- return nil
- }
- case *ast.SelectorExpr:
- if expr.Sel.Name != "NewDesc" {
- if v.strict {
- v.issues = append(v.issues, Issue{
- Pos: v.fs.Position(expr.Sel.Pos()),
- Metric: "",
- Text: fmt.Sprintf("parsing desc with function %s is not supported", expr.Sel.Name),
- })
- }
- return nil
- }
- default:
- if v.strict {
- v.issues = append(v.issues, Issue{
- Pos: v.fs.Position(expr.Pos()),
- Metric: "",
- Text: fmt.Sprintf("parsing desc of %T is not supported", expr),
- })
- }
- return nil
- }
-
- // k8s.io/component-base/metrics.NewDesc has 6 args
- // while prometheus.NewDesc has 4 args
- if len(call.Args) < 4 && v.strict {
- v.issues = append(v.issues, Issue{
- Metric: "",
- Pos: v.fs.Position(call.Pos()),
- Text: "NewDesc should have at least 4 args",
- })
- return nil
- }
-
- name, ok = v.parseValue("fqName", call.Args[0])
- if !ok {
- return nil
- }
-
- help, ok = v.parseValue("help", call.Args[1])
- if !ok {
- return nil
- }
-
- res := &descCallExpr{
- name: &name,
- help: &help,
- }
-
- if x, ok := call.Args[2].(*ast.CompositeLit); ok {
- opt := v.parseCompositeOpts(x)
- if opt == nil {
- return nil
- }
-
- res.labels = opt.labels
- }
-
- if x, ok := call.Args[3].(*ast.CompositeLit); ok {
- opt := v.parseCompositeOpts(x)
- if opt == nil {
- return nil
- }
-
- for k, v := range opt.constLabels {
- res.constLabels = append(res.constLabels, [2]string{k, v})
- }
- }
-
- return res
-}
-
-func mustUnquote(str string) string {
- stringLiteral, err := strconv.Unquote(str)
- if err != nil {
- panic(err)
- }
-
- return stringLiteral
-}
-
-func getConstMetricType(name string) *dto.MetricType {
- metricType := dto.MetricType_UNTYPED
- if name == "CounterValue" {
- metricType = dto.MetricType_COUNTER
- } else if name == "GaugeValue" {
- metricType = dto.MetricType_GAUGE
- }
-
- return &metricType
-}