Skip to content

Commit

Permalink
Support Value Conversions (#172)
Browse files Browse the repository at this point in the history
* Bump k8s.io/client-go from 0.24.2 to 0.24.3 (#171)

Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 0.24.2 to 0.24.3.
- [Release notes](https://github.com/kubernetes/client-go/releases)
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](kubernetes/client-go@v0.24.2...v0.24.3)

---
updated-dependencies:
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: ngrebels <ngrebels@mathworks.com>
Signed-off-by: Yao Hong Kok <yaokok@mathworks.com>

* Bump github.com/prometheus/common from 0.35.0 to 0.37.0 (#170)

Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.35.0 to 0.37.0.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](prometheus/common@v0.35.0...v0.37.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/common
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: ngrebels <ngrebels@mathworks.com>
Signed-off-by: Yao Hong Kok <yaokok@mathworks.com>

* Added a value converter for dynamic values and associated tests

Signed-off-by: ngrebels <ngrebels@mathworks.com>
Signed-off-by: Yao Hong Kok <yaokok@mathworks.com>

* Refactored into functions and created a type

Signed-off-by: ngrebels <ngrebels@mathworks.com>
Signed-off-by: Yao Hong Kok <yaokok@mathworks.com>

* value converter: added example

Signed-off-by: ngrebels <ngrebels@mathworks.com>
Signed-off-by: Yao Hong Kok <yaokok@mathworks.com>

* Remove underscore from variable name

Signed-off-by: Yao Hong Kok <yaokok@mathworks.com>

* Fix formatting error from merging

Signed-off-by: Yao Hong Kok <yaokok@mathworks.com>

Signed-off-by: ngrebels <ngrebels@mathworks.com>
Signed-off-by: Yao Hong Kok <yaokok@mathworks.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Yao Hong Kok <yaokok@mathworks.com>
  • Loading branch information
3 people committed Oct 5, 2022
1 parent ee76c0a commit ca13040
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 0 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ modules:
active: 1 # static value
count: '{.count}' # dynamic value
boolean: '{.some_boolean}'
- name: example_convert
type: object
path: '{.values[0,1]}'
labels:
state: '{.state}'
values:
state: '{.state}'
valueconverter:
'{.state}': #convert value 'state' into a number
active: 1
inactive: 2

headers:
X-Dummy: my-test-header
Expand All @@ -70,6 +82,8 @@ Serving HTTP on 0.0.0.0 port 8000 ...
$ ./json_exporter --config.file examples/config.yml &

$ curl "http://localhost:7979/probe?module=default&target=http://localhost:8000/examples/data.json" | grep ^example
example_convert_state{state="ACTIVE"} 1
example_convert_state{state="INACTIVE"} 2
example_global_value{environment="beta",location="planet-mars"} 1234
example_value_active{environment="beta",id="id-A"} 1
example_value_active{environment="beta",id="id-C"} 1
Expand Down
3 changes: 3 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ type Metric struct {
EpochTimestamp string
Help string
Values map[string]string
ValueConverter ValueConverterType
}

type ValueConverterType map[string]map[string]string

type ScrapeType string

const (
Expand Down
13 changes: 13 additions & 0 deletions examples/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ modules:
active: 1 # static value
count: '{.count}' # dynamic value
boolean: '{.some_boolean}'

- name: example_convert
type: object
path: '{.values[0,1]}'
labels:
state: '{.state}'
values:
state: '{.state}'
valueconverter:
'{.state}': #convert value 'state' in JSON into a number
active: 1
inactive: 2

headers:
X-Dummy: my-test-header

Expand Down
18 changes: 18 additions & 0 deletions exporter/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package exporter
import (
"bytes"
"encoding/json"
"strings"
"time"

"github.com/go-kit/log"
Expand All @@ -38,6 +39,7 @@ type JSONMetric struct {
ValueJSONPath string
LabelsJSONPaths []string
ValueType prometheus.ValueType
ValueConverter config.ValueConverterType
EpochTimestampJSONPath string
}

Expand Down Expand Up @@ -86,11 +88,14 @@ func (mc JSONMetricCollector) Collect(ch chan<- prometheus.Metric) {
continue
}
value, err := extractValue(mc.Logger, jdata, m.ValueJSONPath, false)

if err != nil {
level.Error(mc.Logger).Log("msg", "Failed to extract value for metric", "path", m.ValueJSONPath, "err", err, "metric", m.Desc)
continue
}

value = convertValueIfNeeded(m, value)

if floatValue, err := SanitizeValue(value); err == nil {
metric := prometheus.MustNewConstMetric(
m.Desc,
Expand Down Expand Up @@ -161,6 +166,19 @@ func extractLabels(logger log.Logger, data []byte, paths []string) []string {
return labels
}

// Returns the conversion of the dynamic value- if it exists in the ValueConverter configuration
func convertValueIfNeeded(m JSONMetric, value string) string {
if m.ValueConverter != nil {
if valueMappings, hasPathKey := m.ValueConverter[m.ValueJSONPath]; hasPathKey {
value = strings.ToLower(value)

if _, hasValueKey := valueMappings[value]; hasValueKey {
value = valueMappings[value]
}
}
}
return value
}
func timestampMetric(logger log.Logger, m JSONMetric, data []byte, pm prometheus.Metric) prometheus.Metric {
if m.EpochTimestampJSONPath == "" {
return pm
Expand Down
23 changes: 23 additions & 0 deletions exporter/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ func CreateMetricsList(c config.Module) ([]JSONMetric, error) {
variableLabels = append(variableLabels, k)
variableLabelsValues = append(variableLabelsValues, v)
}

var valueConverters config.ValueConverterType = initializeValueConverter(metric)

jsonMetric := JSONMetric{
Type: config.ObjectScrape,
Desc: prometheus.NewDesc(
Expand All @@ -130,6 +133,7 @@ func CreateMetricsList(c config.Module) ([]JSONMetric, error) {
ValueJSONPath: valuePath,
LabelsJSONPaths: variableLabelsValues,
ValueType: valueType,
ValueConverter: valueConverters,
EpochTimestampJSONPath: metric.EpochTimestamp,
}
metrics = append(metrics, jsonMetric)
Expand Down Expand Up @@ -245,3 +249,22 @@ func renderBody(logger log.Logger, body config.Body, tplValues url.Values) (meth
}
return
}

// Initializes and returns a ValueConverter object. nil if there aren't any conversions
func initializeValueConverter(metric config.Metric) config.ValueConverterType {
var valueConverters config.ValueConverterType

//convert all keys to lowercase
if metric.ValueConverter != nil {
valueConverters = make(config.ValueConverterType)
for valuesKey, innerMap := range metric.ValueConverter {
//make the mappings for each value key lowercase
valueConverters[valuesKey] = make(map[string]string)
for conversionFrom, conversionTo := range innerMap {
valueConverters[valuesKey][strings.ToLower(conversionFrom)] = conversionTo
}
}
}

return valueConverters
}
116 changes: 116 additions & 0 deletions test/config/test-converter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
#the following tests use ./valueconverter.json

modules:
default:
metrics:
#State should be converted to 1 for the metric value
#Test uppercase key
- name: test1
path: "{$}"
help: Testing Single Value Converter on Type Object
type: object
labels:
name: '{.name}'
values:
state: '{.state}'
valueconverter:
'{.state}':
ACTIVE: 1

#State should be converted to 1 for the metric value
#Test lowercase key
- name: test2
path: "{$}"
help: Testing Single Value Converter on Type Object
type: object
labels:
name: '{.name}'
values:
state: '{.state}'
valueconverter:
'{.state}':
active: 1

#There should be two JSONs returned: a metric for 'state' with value 1, and a metric with value 12
- name: test3
path: "{$}"
help: Testing Multi Diff Value Converter on Type Object
type: object
labels:
name: '{.name}'
values:
state: '{.state}'
active: 12
valueconverter:
'{.state}':
ACTIVE: 1

#Nothing should be returned. This should be an error since 'state' can't be converted to an int
- name: test4
path: "{$}"
help: Testing Value with missing conversion
type: object
labels:
name: '{.name}'
values:
state: '{.state}'

#Test nested JSON. It should return with both values but with 12 as the metric value
- name: test5
path: '{.values[*]}'
help: Testing Conversion with Missing value
type: object
labels:
name: '{.name}'
values:
active: 12
valueconverter:
'{.state}':
ACTIVE: 1

#Test nested JSON.
#It should return with both values but 'state' should be converted
- name: test6
path: '{.values[*]}'
help: Testing Value with Multiple Conversions
type: object
labels:
name: '{.name}'
values:
state: '{.state}'
valueconverter:
'{.state}':
ACTIVE: 1
inactive: 2

#Test nested JSON.
#However, it should only return with state value
#There is a missing key: 'down' in valueconverter
- name: test7
path: '{.values[*]}'
help: Testing Value with Multiple Conversions and Missing Key, Value
type: object
labels:
name: '{.name}'
values:
state: '{.state}'
valueconverter:
'{.state}':
ACTIVE: 1

#Two metrics should be returned
#State should be mapped to 1.
#ResponseCode should be 2 because it already has a value in the JSON.
- name: test8
path: "{$}"
help: Testing Multi Diff Value Converter on Type Object
type: object
labels:
name: '{.name}'
values:
stat: '{.state}'
active: '{.responseCode}'
valueconverter:
'{.state}':
ACTIVE: 1
29 changes: 29 additions & 0 deletions test/response/test-converter.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# HELP test1_state Testing Single Value Converter on Type Object
# TYPE test1_state untyped
test1_state{name="Test Converter"} 1
# HELP test2_state Testing Single Value Converter on Type Object
# TYPE test2_state untyped
test2_state{name="Test Converter"} 1
# HELP test3_active Testing Multi Diff Value Converter on Type Object
# TYPE test3_active untyped
test3_active{name="Test Converter"} 12
# HELP test3_state Testing Multi Diff Value Converter on Type Object
# TYPE test3_state untyped
test3_state{name="Test Converter"} 1
# HELP test5_active Testing Conversion with Missing value
# TYPE test5_active untyped
test5_active{name="id-A"} 12
test5_active{name="id-B"} 12
# HELP test6_state Testing Value with Multiple Conversions
# TYPE test6_state untyped
test6_state{name="id-A"} 1
test6_state{name="id-B"} 2
# HELP test7_state Testing Value with Multiple Conversions and Missing Key, Value
# TYPE test7_state untyped
test7_state{name="id-A"} 1
# HELP test8_active Testing Multi Diff Value Converter on Type Object
# TYPE test8_active untyped
test8_active{name="Test Converter"} 2
# HELP test8_stat Testing Multi Diff Value Converter on Type Object
# TYPE test8_stat untyped
test8_stat{name="Test Converter"} 1
16 changes: 16 additions & 0 deletions test/serve/test-converter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "Test Converter",
"state": "ACTIVE",
"responseCode": 2,
"values": [
{
"name": "id-A",
"state": "ACTIVE"
},
{
"name": "id-B",
"state": "INACTIVE"
}
]
}

0 comments on commit ca13040

Please sign in to comment.