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
}
lint is the entry point for linting a single metric.
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
}