Intermediate progress.

Working through some of the result conversions.
I want to use this code in a harness project to exercise some of it, but there are some versioning issues around my modified code vs. the current version of the real project. The easiest way to work around them at the moment is to push this.
This commit is contained in:
Tony Compton 2018-06-29 09:46:26 -04:00
parent a69a5cbbcc
commit d90012439c
6 changed files with 68 additions and 37 deletions

View file

@ -78,7 +78,11 @@ func (p *externalPrometheusProvider) GetExternalMetric(namespace string, metricN
return nil, err
}
return p.metricConverter.Convert(queryResults)
queryMetadata := conv.QueryMetadata{
MetricName: metricName,
WindowInSeconds: 0,
}
return p.metricConverter.Convert(queryMetadata, queryResults)
}
func (p *externalPrometheusProvider) ListAllExternalMetrics() []provider.ExternalMetricInfo {

View file

@ -17,7 +17,7 @@ func NewMatrixConverter() MetricConverter {
return &matrixConverter{}
}
func (c *matrixConverter) Convert(queryResult prom.QueryResult) (*external_metrics.ExternalMetricValueList, error) {
func (c *matrixConverter) Convert(metadata QueryMetadata, queryResult prom.QueryResult) (*external_metrics.ExternalMetricValueList, error) {
if queryResult.Type != model.ValMatrix {
return nil, errors.New("matrixConverter can only convert scalar query results")
}

View file

@ -11,7 +11,7 @@ import (
//MetricConverter provides a unified interface for converting the results of
//Prometheus queries into external metric types.
type MetricConverter interface {
Convert(queryResult prom.QueryResult) (*external_metrics.ExternalMetricValueList, error)
Convert(metadata QueryMetadata, queryResult prom.QueryResult) (*external_metrics.ExternalMetricValueList, error)
}
type metricConverter struct {
@ -30,17 +30,17 @@ func NewMetricConverter(scalar MetricConverter, vector MetricConverter, matrix M
}
}
func (c *metricConverter) Convert(queryResult prom.QueryResult) (*external_metrics.ExternalMetricValueList, error) {
func (c *metricConverter) Convert(metadata QueryMetadata, queryResult prom.QueryResult) (*external_metrics.ExternalMetricValueList, error) {
if queryResult.Type == model.ValScalar {
return c.scalarConverter.Convert(queryResult)
return c.scalarConverter.Convert(metadata, queryResult)
}
if queryResult.Type == model.ValVector {
return c.vectorConverter.Convert(queryResult)
return c.vectorConverter.Convert(metadata, queryResult)
}
if queryResult.Type == model.ValMatrix {
return c.matrixConverter.Convert(queryResult)
return c.matrixConverter.Convert(metadata, queryResult)
}
return nil, errors.New("encountered an unexpected query result type")

View file

@ -0,0 +1,11 @@
package provider
//QueryMetadata is a data object the holds information about what inputs
//were used to generate Prometheus query results. In most cases it's not
//necessary, as the Prometheus result come back with enough information
//to determine the metric name. However, for scalar results, Prometheus
//only provides the value.
type QueryMetadata struct {
MetricName string
WindowInSeconds int64
}

View file

@ -19,7 +19,7 @@ func NewScalarConverter() MetricConverter {
return &scalarConverter{}
}
func (c *scalarConverter) Convert(queryResult prom.QueryResult) (*external_metrics.ExternalMetricValueList, error) {
func (c *scalarConverter) Convert(metadata QueryMetadata, queryResult prom.QueryResult) (*external_metrics.ExternalMetricValueList, error) {
if queryResult.Type != model.ValScalar {
return nil, errors.New("scalarConverter can only convert scalar query results")
}
@ -30,37 +30,26 @@ func (c *scalarConverter) Convert(queryResult prom.QueryResult) (*external_metri
return nil, errors.New("the provided input did not contain scalar query results")
}
return c.convert(toConvert)
return c.convert(metadata, toConvert)
}
func (c *scalarConverter) convert(input *model.Scalar) (*external_metrics.ExternalMetricValueList, error) {
tempWindow := int64(0)
func (c *scalarConverter) convert(metadata QueryMetadata, input *model.Scalar) (*external_metrics.ExternalMetricValueList, error) {
result := external_metrics.ExternalMetricValueList{
//TODO: Where should all of these values come from?
TypeMeta: metav1.TypeMeta{
Kind: "?",
APIVersion: "?",
},
ListMeta: metav1.ListMeta{
SelfLink: "?",
ResourceVersion: "?",
Continue: "?",
},
//Using prometheusProvider.metricsFor(...) as an example,
//it seems that I don't need to provide values for
//TypeMeta and ListMeta.
//TODO: Get some confirmation on this.
Items: []external_metrics.ExternalMetricValue{
external_metrics.ExternalMetricValue{
TypeMeta: metav1.TypeMeta{
Kind: "?",
APIVersion: "?",
},
//TODO: Carry forward the metric name so we can set it here.
MetricName: "?",
MetricName: metadata.MetricName,
Timestamp: metav1.Time{
input.Timestamp.Time(),
},
//TODO: Carry forward some information about our configuration so we can provide it here.
WindowSeconds: &tempWindow,
//TODO: Jump through the necessary hoops to convert our number into the proper type.
Value: resource.Quantity{},
WindowSeconds: &metadata.WindowInSeconds,
//TODO: I'm not so sure about this type/conversions.
//Is there a meaningful loss of precision here?
//Does K8S only deal win integer metrics?
Value: *resource.NewQuantity(int64(input.Value), resource.DecimalSI),
},
},
}

View file

@ -5,6 +5,8 @@ import (
prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client"
"github.com/prometheus/common/model"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/metrics/pkg/apis/external_metrics"
)
@ -17,21 +19,46 @@ func NewVectorConverter() MetricConverter {
return &vectorConverter{}
}
func (c *vectorConverter) Convert(queryResult prom.QueryResult) (*external_metrics.ExternalMetricValueList, error) {
func (c *vectorConverter) Convert(metadata QueryMetadata, queryResult prom.QueryResult) (*external_metrics.ExternalMetricValueList, error) {
if queryResult.Type != model.ValVector {
return nil, errors.New("vectorConverter can only convert scalar query results")
}
toConvert := queryResult.Vector
toConvert := *queryResult.Vector
if toConvert == nil {
return nil, errors.New("the provided input did not contain vector query results")
}
return c.convert(toConvert)
return c.convert(metadata, toConvert)
}
func (c *vectorConverter) convert(result *model.Vector) (*external_metrics.ExternalMetricValueList, error) {
//TODO: Implementation.
return nil, nil
func (c *vectorConverter) convert(metadata QueryMetadata, result model.Vector) (*external_metrics.ExternalMetricValueList, error) {
items := []external_metrics.ExternalMetricValue{}
metricValueList := external_metrics.ExternalMetricValueList{
Items: items,
}
numSamples := result.Len()
if numSamples == 0 {
return &metricValueList, nil
}
for _, val := range result {
singleMetric := external_metrics.ExternalMetricValue{
MetricName: string(val.Metric[model.LabelName("__name__")]),
Timestamp: metav1.Time{
val.Timestamp.Time(),
},
WindowSeconds: &metadata.WindowInSeconds,
//TODO: I'm not so sure about this type/conversions.
//This can't possibly be the right way to convert this.
//Also, does K8S only deal win integer metrics?
Value: *resource.NewQuantity(int64(float64(val.Value)), resource.DecimalSI),
}
items = append(items, singleMetric)
}
return &metricValueList, nil
}