func lintCounter(mf *dto.MetricFamily) []Problem {
	var problems []Problem
	isCounter := mf.GetType() == dto.MetricType_COUNTER
	isUntyped := mf.GetType() == dto.MetricType_UNTYPED
	hasTotalSuffix := strings.HasSuffix(mf.GetName(), "_total")
	switch {
	case isCounter && !hasTotalSuffix:
		problems = append(problems, newProblem(mf, `counter metrics should have "_total" suffix`))
	case !isUntyped && !isCounter && hasTotalSuffix:
		problems = append(problems, newProblem(mf, `non-counter metrics should not have "_total" suffix`))
	}
	return problems
}
lintCounter detects issues specific to counters, as well as patterns that should
only be used with counters.
package promlint
import (
	"fmt"
	"io"
	"regexp"
	"sort"
	"strings"
	"github.com/prometheus/common/expfmt"
	dto "github.com/prometheus/client_model/go"
)
type Linter struct {
	r   io.Reader
	mfs []*dto.MetricFamily
}
type Problem struct {
	Metric string
	Text string
}
func newProblem(mf *dto.MetricFamily, text string) Problem {
	return Problem{
		Metric: mf.GetName(),
		Text:   text,
	}
}
func New(r io.Reader) *Linter {
	return &Linter{
		r: r,
	}
}
func NewWithMetricFamilies(mfs []*dto.MetricFamily) *Linter {
	return &Linter{
		mfs: mfs,
	}
}
func (l *Linter) Lint() ([]Problem, error) {
	var problems []Problem
	if l.r != nil {
		d := expfmt.NewDecoder(l.r, expfmt.FmtText)
		mf := &dto.MetricFamily{}
		for {
			if err := d.Decode(mf); err != nil {
				if err == io.EOF {
					break
				}
				return nil, err
			}
			problems = append(problems, lint(mf)...)
		}
	}
	for _, mf := range l.mfs {
		problems = append(problems, lint(mf)...)
	}
	sort.SliceStable(problems, func(i, j int) bool {
		if problems[i].Metric == problems[j].Metric {
			return problems[i].Text < problems[j].Text
		}
		return problems[i].Metric < problems[j].Metric
	})
	return problems, nil
}
func lint(mf *dto.MetricFamily) []Problem {
	fns := []func(mf *dto.MetricFamily) []Problem{
		lintHelp,
		lintMetricUnits,
		lintCounter,
		lintHistogramSummaryReserved,
		lintMetricTypeInName,
		lintReservedChars,
		lintCamelCase,
		lintUnitAbbreviations,
	}
	var problems []Problem
	for _, fn := range fns {
		problems = append(problems, fn(mf)...)
	}
	return problems
}
func lintHelp(mf *dto.MetricFamily) []Problem {
	var problems []Problem
	if mf.Help == nil {
		problems = append(problems, newProblem(mf, "no help text"))
	}
	return problems
}
func lintMetricUnits(mf *dto.MetricFamily) []Problem {
	var problems []Problem
	unit, base, ok := metricUnits(*mf.Name)
	if !ok {
		return nil
	}
	if unit == base {
		return nil
	}
	problems = append(problems, newProblem(mf, fmt.Sprintf("use base unit %q instead of %q", base, unit)))
	return problems
}