2019-11-18 13:34:06 +00:00
|
|
|
package state
|
|
|
|
|
|
|
|
import (
|
2020-02-10 11:52:07 +00:00
|
|
|
"bytes"
|
2019-12-17 11:09:52 +00:00
|
|
|
"encoding/json"
|
2020-02-10 11:52:07 +00:00
|
|
|
"expvar"
|
|
|
|
"fmt"
|
2019-12-17 11:09:52 +00:00
|
|
|
|
2019-11-18 13:34:06 +00:00
|
|
|
"github.com/golang/protobuf/proto"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
dto "github.com/prometheus/client_model/go"
|
2019-12-17 11:09:52 +00:00
|
|
|
"github.com/spf13/viper"
|
2019-11-18 13:34:06 +00:00
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
"google.golang.org/grpc/status"
|
|
|
|
)
|
|
|
|
|
|
|
|
// MetricFamily is type alias for proto.Message generated
|
|
|
|
// from github.com/prometheus/client_model/metrics.proto.
|
|
|
|
type MetricFamily = dto.MetricFamily
|
|
|
|
|
|
|
|
// EncodeMetrics encodes metrics from gatherer into MetricsResponse message,
|
|
|
|
// if something went wrong returns gRPC Status error (can be returned from service).
|
|
|
|
func EncodeMetrics(g prometheus.Gatherer) (*MetricsResponse, error) {
|
|
|
|
metrics, err := g.Gather()
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.New(codes.Internal, err.Error()).Err()
|
|
|
|
}
|
|
|
|
|
|
|
|
results := make([][]byte, 0, len(metrics))
|
|
|
|
for _, mf := range metrics {
|
|
|
|
item, err := proto.Marshal(mf)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.New(codes.Internal, err.Error()).Err()
|
|
|
|
}
|
|
|
|
|
|
|
|
results = append(results, item)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &MetricsResponse{Metrics: results}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DecodeMetrics decodes metrics from MetricsResponse to []MetricFamily,
|
|
|
|
// if something went wrong returns error.
|
|
|
|
func DecodeMetrics(r *MetricsResponse) ([]*MetricFamily, error) {
|
|
|
|
metrics := make([]*dto.MetricFamily, 0, len(r.Metrics))
|
|
|
|
for i := range r.Metrics {
|
|
|
|
mf := new(MetricFamily)
|
|
|
|
if err := proto.Unmarshal(r.Metrics[i], mf); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-12-17 14:53:48 +00:00
|
|
|
metrics = append(metrics, mf)
|
2019-11-18 13:34:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return metrics, nil
|
|
|
|
}
|
2019-12-17 11:09:52 +00:00
|
|
|
|
|
|
|
// EncodeConfig encodes viper settings into DumpConfig message,
|
|
|
|
// if something went wrong returns gRPC Status error (can be returned from service).
|
|
|
|
func EncodeConfig(v *viper.Viper) (*DumpResponse, error) {
|
|
|
|
data, err := json.Marshal(v.AllSettings())
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Error(codes.Internal, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
return &DumpResponse{Config: data}, nil
|
|
|
|
}
|
2020-02-10 11:52:07 +00:00
|
|
|
|
|
|
|
// EncodeVariables encodes debug variables into DumpVarsResponse message.
|
|
|
|
// Variables encoded into JSON and stored as slice of bytes.
|
|
|
|
func EncodeVariables() *DumpVarsResponse {
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
buf.WriteString("{\n")
|
|
|
|
first := true
|
|
|
|
|
|
|
|
expvar.Do(func(kv expvar.KeyValue) {
|
|
|
|
if !first {
|
|
|
|
buf.WriteString(",\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
first = false
|
|
|
|
|
|
|
|
_, _ = fmt.Fprintf(buf, "%q: %s", kv.Key, kv.Value)
|
|
|
|
})
|
|
|
|
|
|
|
|
buf.WriteString("\n}\n")
|
|
|
|
|
|
|
|
return &DumpVarsResponse{Variables: buf.Bytes()}
|
|
|
|
}
|