func (m *constMetric) Write(out *dto.Metric) errors.WithContext {
	out.Label = m.labelPairs
	switch t := m.desc.ValueType(); t {
	case prometheus.CounterValue:
		out.Counter = &dto.Counter{Value: proto.Float64(m.val)}
	case prometheus.GaugeValue:
		out.Gauge = &dto.Gauge{Value: proto.Float64(m.val)}
	default:
		return errors.Errorf(m.desc.LogContext(), "encountered unknown type %v", t)
	}
	return nil
}
Write implements Metric.
package sql_exporter
import (
	"fmt"
	"sort"
	"github.com/free/sql_exporter/config"
	"github.com/free/sql_exporter/errors"
	"github.com/golang/protobuf/proto"
	"github.com/prometheus/client_golang/prometheus"
	dto "github.com/prometheus/client_model/go"
)
type MetricDesc interface {
	Name() string
	Help() string
	ValueType() prometheus.ValueType
	ConstLabels() []*dto.LabelPair
	Labels() []string
	LogContext() string
}
type MetricFamily struct {
	config      *config.MetricConfig
	constLabels []*dto.LabelPair
	labels      []string
	logContext  string
}
func NewMetricFamily(logContext string, mc *config.MetricConfig, constLabels []*dto.LabelPair) (*MetricFamily, errors.WithContext) {
	logContext = fmt.Sprintf("%s, metric=%q", logContext, mc.Name)
	if len(mc.Values) == 0 {
		return nil, errors.New(logContext, "no value column defined")
	}
	if len(mc.Values) > 1 && mc.ValueLabel == "" {
		return nil, errors.New(logContext, "multiple values but no value label")
	}
	labels := make([]string, 0, len(mc.KeyLabels)+1)
	labels = append(labels, mc.KeyLabels...)
	if mc.ValueLabel != "" {
		labels = append(labels, mc.ValueLabel)
	}
	sortedLabels := append(constLabels[:0:0], constLabels...)
	for k, v := range mc.StaticLabels {
		sortedLabels = append(sortedLabels, &dto.LabelPair{
			Name:  proto.String(k),
			Value: proto.String(v),
		})
	}
	sort.Sort(labelPairSorter(sortedLabels))
	return &MetricFamily{
		config:      mc,
		constLabels: sortedLabels,
		labels:      labels,
		logContext:  logContext,
	}, nil
}
func (mf MetricFamily) Collect(row map[string]interface{}, ch chan<- Metric) {
	labelValues := make([]string, len(mf.labels))
	for i, label := range mf.config.KeyLabels {
		labelValues[i] = row[label].(string)
	}
	for _, v := range mf.config.Values {
		if mf.config.ValueLabel != "" {
			labelValues[len(labelValues)-1] = v
		}
		value := row[v].(float64)
		ch <- NewMetric(&mf, value, labelValues...)
	}
}
func (mf MetricFamily) Name() string {
	return mf.config.Name
}
func (mf MetricFamily) Help() string {
	return mf.config.Help
}
func (mf MetricFamily) ValueType() prometheus.ValueType {
	return mf.config.ValueType()
}
func (mf MetricFamily) ConstLabels() []*dto.LabelPair {
	return mf.constLabels
}
func (mf MetricFamily) Labels() []string {
	return mf.labels
}
func (mf MetricFamily) LogContext() string {
	return mf.logContext
}
type automaticMetricDesc struct {
	name        string
	help        string
	valueType   prometheus.ValueType
	labels      []string
	constLabels []*dto.LabelPair
	logContext  string
}
func NewAutomaticMetricDesc(
	logContext, name, help string, valueType prometheus.ValueType, constLabels []*dto.LabelPair, labels ...string) MetricDesc {
	return &automaticMetricDesc{
		name:        name,
		help:        help,
		valueType:   valueType,
		constLabels: constLabels,
		labels:      labels,
		logContext:  logContext,
	}
}
func (a automaticMetricDesc) Name() string {
	return a.name
}
func (a automaticMetricDesc) Help() string {
	return a.help
}
func (a automaticMetricDesc) ValueType() prometheus.ValueType {
	return a.valueType
}
func (a automaticMetricDesc) ConstLabels() []*dto.LabelPair {
	return a.constLabels
}
func (a automaticMetricDesc) Labels() []string {
	return a.labels
}
func (a automaticMetricDesc) LogContext() string {
	return a.logContext
}
type Metric interface {
	Desc() MetricDesc
	Write(out *dto.Metric) errors.WithContext
}
func NewMetric(desc MetricDesc, value float64, labelValues ...string) Metric {
	if len(desc.Labels()) != len(labelValues) {
		panic(fmt.Sprintf("[%s] expected %d labels, got %d", desc.LogContext(), len(desc.Labels()), len(labelValues)))
	}
	return &constMetric{
		desc:       desc,
		val:        value,
		labelPairs: makeLabelPairs(desc, labelValues),
	}
}
type constMetric struct {
	desc       MetricDesc
	val        float64
	labelPairs []*dto.LabelPair
}
func (m *constMetric) Desc() MetricDesc {
	return m.desc
}