mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-25 13:44:05 -08:00
More efficient JSON query result format.
This depends on https://github.com/prometheus/client_golang/pull/51. For vectors, the result format looks like this: ```json { "version": 1, "type" : "vector", "value" : [ { "timestamp" : 1421765411.045, "value" : "65.475000", "metric" : { "quantile" : "0.5", "instance" : "http://localhost:9090/metrics", "job" : "prometheus", "__name__" : "http_request_duration_microseconds", "handler" : "/static/", "method" : "get", "code" : "304" } }, { "timestamp" : 1421765411.045, "value" : "5826.339000", "metric" : { "quantile" : "0.9", "instance" : "http://localhost:9090/metrics", "job" : "prometheus", "__name__" : "http_request_duration_microseconds", "handler" : "prometheus", "method" : "get", "code" : "200" } }, /* ... */ ] } ``` For matrices, it looks like this: ```json { "version": 1, "type" : "matrix", "value" : [ { "metric" : { "quantile" : "0.99", "instance" : "http://localhost:9090/metrics", "job" : "prometheus", "__name__" : "http_request_duration_microseconds", "handler" : "/static/", "method" : "get", "code" : "200" }, "values" : [ [ 1421765547.659, "29162.953000" ], [ 1421765548.659, "29162.953000" ], [ 1421765549.659, "29162.953000" ], /* ... */ ] } ] } ```
This commit is contained in:
parent
f7e3da5488
commit
d4374a9265
|
@ -81,7 +81,7 @@ func TestNotificationHandler(t *testing.T) {
|
||||||
// Correct message.
|
// Correct message.
|
||||||
summary: "Summary",
|
summary: "Summary",
|
||||||
description: "Description",
|
description: "Description",
|
||||||
message: `[{"Description":"Description","Labels":{"instance":"testinstance"},"Payload":{"ActiveSince":"0001-01-01T00:00:00Z","AlertingRule":"Test rule string","GeneratorURL":"prometheus_url","Value":"0.333333"},"Summary":"Summary"}]`,
|
message: `[{"Description":"Description","Labels":{"instance":"testinstance"},"Payload":{"ActiveSince":"0001-01-01T00:00:00Z","AlertingRule":"Test rule string","GeneratorURL":"prometheus_url","Value":"0.3333333333333333"},"Summary":"Summary"}]`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,15 +36,15 @@ var stalenessDelta = flag.Duration("query.staleness-delta", 300*time.Second, "St
|
||||||
|
|
||||||
// SampleStream is a stream of Values belonging to an attached COWMetric.
|
// SampleStream is a stream of Values belonging to an attached COWMetric.
|
||||||
type SampleStream struct {
|
type SampleStream struct {
|
||||||
Metric clientmodel.COWMetric
|
Metric clientmodel.COWMetric `json:"metric"`
|
||||||
Values metric.Values
|
Values metric.Values `json:"values"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sample is a single sample belonging to a COWMetric.
|
// Sample is a single sample belonging to a COWMetric.
|
||||||
type Sample struct {
|
type Sample struct {
|
||||||
Metric clientmodel.COWMetric
|
Metric clientmodel.COWMetric `json:"metric"`
|
||||||
Value clientmodel.SampleValue
|
Value clientmodel.SampleValue `json:"value"`
|
||||||
Timestamp clientmodel.Timestamp
|
Timestamp clientmodel.Timestamp `json:"timestamp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vector is basically only an alias for clientmodel.Samples, but the
|
// Vector is basically only an alias for clientmodel.Samples, but the
|
||||||
|
|
|
@ -37,6 +37,8 @@ const (
|
||||||
JSON
|
JSON
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const jsonFormatVersion = 1
|
||||||
|
|
||||||
func (opType BinOpType) String() string {
|
func (opType BinOpType) String() string {
|
||||||
opTypeMap := map[BinOpType]string{
|
opTypeMap := map[BinOpType]string{
|
||||||
Add: "+",
|
Add: "+",
|
||||||
|
@ -121,11 +123,13 @@ func (matrix Matrix) String() string {
|
||||||
// ErrorToJSON converts the given error into JSON.
|
// ErrorToJSON converts the given error into JSON.
|
||||||
func ErrorToJSON(err error) string {
|
func ErrorToJSON(err error) string {
|
||||||
errorStruct := struct {
|
errorStruct := struct {
|
||||||
Type string
|
Type string `json:"type"`
|
||||||
Value string
|
Value string `json:"value"`
|
||||||
|
Version int `json:"version"`
|
||||||
}{
|
}{
|
||||||
Type: "error",
|
Type: "error",
|
||||||
Value: err.Error(),
|
Value: err.Error(),
|
||||||
|
Version: jsonFormatVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
errorJSON, err := json.Marshal(errorStruct)
|
errorJSON, err := json.Marshal(errorStruct)
|
||||||
|
@ -139,11 +143,13 @@ func ErrorToJSON(err error) string {
|
||||||
// 'vector', or 'matrix' into its JSON representation.
|
// 'vector', or 'matrix' into its JSON representation.
|
||||||
func TypedValueToJSON(data interface{}, typeStr string) string {
|
func TypedValueToJSON(data interface{}, typeStr string) string {
|
||||||
dataStruct := struct {
|
dataStruct := struct {
|
||||||
Type string
|
Type string `json:"type"`
|
||||||
Value interface{}
|
Value interface{} `json:"value"`
|
||||||
|
Version int `json:"version"`
|
||||||
}{
|
}{
|
||||||
Type: typeStr,
|
Type: typeStr,
|
||||||
Value: data,
|
Value: data,
|
||||||
|
Version: jsonFormatVersion,
|
||||||
}
|
}
|
||||||
dataJSON, err := json.Marshal(dataStruct)
|
dataJSON, err := json.Marshal(dataStruct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -15,13 +15,14 @@ package metric
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
clientmodel "github.com/prometheus/client_golang/model"
|
clientmodel "github.com/prometheus/client_golang/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MarshalJSON implements json.Marshaler.
|
// MarshalJSON implements json.Marshaler.
|
||||||
func (s SamplePair) MarshalJSON() ([]byte, error) {
|
func (s SamplePair) MarshalJSON() ([]byte, error) {
|
||||||
return []byte(fmt.Sprintf("{\"Value\": \"%f\", \"Timestamp\": %s}", s.Value, s.Timestamp.String())), nil
|
return []byte(fmt.Sprintf("[%s, \"%s\"]", s.Timestamp.String(), strconv.FormatFloat(float64(s.Value), 'f', -1, 64))), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SamplePair pairs a SampleValue with a Timestamp.
|
// SamplePair pairs a SampleValue with a Timestamp.
|
||||||
|
|
|
@ -385,18 +385,18 @@ Prometheus.Graph.prototype.parseValue = function(value) {
|
||||||
Prometheus.Graph.prototype.transformData = function(json) {
|
Prometheus.Graph.prototype.transformData = function(json) {
|
||||||
self = this;
|
self = this;
|
||||||
var palette = new Rickshaw.Color.Palette();
|
var palette = new Rickshaw.Color.Palette();
|
||||||
if (json.Type != "matrix") {
|
if (json.type != "matrix") {
|
||||||
self.showError("Result is not of matrix type! Please enter a correct expression.");
|
self.showError("Result is not of matrix type! Please enter a correct expression.");
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
var data = json.Value.map(function(ts) {
|
var data = json.value.map(function(ts) {
|
||||||
return {
|
return {
|
||||||
name: escapeHTML(self.metricToTsName(ts.Metric)),
|
name: escapeHTML(self.metricToTsName(ts.metric)),
|
||||||
labels: ts.Metric,
|
labels: ts.metric,
|
||||||
data: ts.Values.map(function(value) {
|
data: ts.values.map(function(value) {
|
||||||
return {
|
return {
|
||||||
x: value.Timestamp,
|
x: value[0],
|
||||||
y: self.parseValue(value.Value)
|
y: self.parseValue(value[1])
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
color: palette.color()
|
color: palette.color()
|
||||||
|
@ -506,8 +506,8 @@ Prometheus.Graph.prototype.resizeGraph = function() {
|
||||||
|
|
||||||
Prometheus.Graph.prototype.handleGraphResponse = function(json, textStatus) {
|
Prometheus.Graph.prototype.handleGraphResponse = function(json, textStatus) {
|
||||||
var self = this
|
var self = this
|
||||||
if (json.Type == "error") {
|
if (json.type == "error") {
|
||||||
self.showError(json.Value);
|
self.showError(json.value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.data = self.transformData(json);
|
self.data = self.transformData(json);
|
||||||
|
@ -526,38 +526,38 @@ Prometheus.Graph.prototype.handleConsoleResponse = function(data, textStatus) {
|
||||||
var tBody = self.consoleTab.find(".console_table tbody");
|
var tBody = self.consoleTab.find(".console_table tbody");
|
||||||
tBody.empty();
|
tBody.empty();
|
||||||
|
|
||||||
switch(data.Type) {
|
switch(data.type) {
|
||||||
case "vector":
|
case "vector":
|
||||||
if (data.Value.length === 0) {
|
if (data.value.length === 0) {
|
||||||
tBody.append("<tr><td colspan='2'><i>no data</i></td></tr>");
|
tBody.append("<tr><td colspan='2'><i>no data</i></td></tr>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (var i = 0; i < data.Value.length; i++) {
|
for (var i = 0; i < data.value.length; i++) {
|
||||||
var v = data.Value[i];
|
var v = data.value[i];
|
||||||
var tsName = self.metricToTsName(v.Metric);
|
var tsName = self.metricToTsName(v.metric);
|
||||||
tBody.append("<tr><td>" + escapeHTML(tsName) + "</td><td>" + v.Value + "</td></tr>");
|
tBody.append("<tr><td>" + escapeHTML(tsName) + "</td><td>" + v.value + "</td></tr>");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "matrix":
|
case "matrix":
|
||||||
if (data.Value.length === 0) {
|
if (data.value.length === 0) {
|
||||||
tBody.append("<tr><td colspan='2'><i>no data</i></td></tr>");
|
tBody.append("<tr><td colspan='2'><i>no data</i></td></tr>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (var i = 0; i < data.Value.length; i++) {
|
for (var i = 0; i < data.value.length; i++) {
|
||||||
var v = data.Value[i];
|
var v = data.value[i];
|
||||||
var tsName = self.metricToTsName(v.Metric);
|
var tsName = self.metricToTsName(v.metric);
|
||||||
var valueText = "";
|
var valueText = "";
|
||||||
for (var j = 0; j < v.Values.length; j++) {
|
for (var j = 0; j < v.values.length; j++) {
|
||||||
valueText += v.Values[j].Value + " @" + v.Values[j].Timestamp + "<br/>";
|
valueText += v.values[j][1] + " @" + v.values[j][0] + "<br/>";
|
||||||
}
|
}
|
||||||
tBody.append("<tr><td>" + escapeHTML(tsName) + "</td><td>" + valueText + "</td></tr>")
|
tBody.append("<tr><td>" + escapeHTML(tsName) + "</td><td>" + valueText + "</td></tr>")
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "scalar":
|
case "scalar":
|
||||||
tBody.append("<tr><td>scalar</td><td>" + data.Value + "</td></tr>");
|
tBody.append("<tr><td>scalar</td><td>" + data.value + "</td></tr>");
|
||||||
break;
|
break;
|
||||||
case "error":
|
case "error":
|
||||||
self.showError(data.Value);
|
self.showError(data.value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
self.showError("Unsupported value type!");
|
self.showError("Unsupported value type!");
|
||||||
|
|
|
@ -397,11 +397,11 @@ PromConsole.Graph.prototype._render = function(data) {
|
||||||
// Get the data into the right format.
|
// Get the data into the right format.
|
||||||
var seriesLen = 0;
|
var seriesLen = 0;
|
||||||
for (var e = 0; e < data.length; e++) {
|
for (var e = 0; e < data.length; e++) {
|
||||||
for (var i = 0; i < data[e].Value.length; i++) {
|
for (var i = 0; i < data[e].value.length; i++) {
|
||||||
series[seriesLen++] = {
|
series[seriesLen++] = {
|
||||||
data: data[e].Value[i].Values.map(function(s) {return {x: s.Timestamp, y: parseFloat(s.Value)} }),
|
data: data[e].value[i].values.map(function(s) {return {x: s[0], y: parseFloat(s[1])} }),
|
||||||
color: palette.color(),
|
color: palette.color(),
|
||||||
name: nameFunc(data[e].Value[i].Metric),
|
name: nameFunc(data[e].value[i].metric),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -549,12 +549,12 @@ PromConsole._chooseNameFunction = function(data) {
|
||||||
// If only one label varies, use that value.
|
// If only one label varies, use that value.
|
||||||
var labelValues = {};
|
var labelValues = {};
|
||||||
for (var e = 0; e < data.length; e++) {
|
for (var e = 0; e < data.length; e++) {
|
||||||
for (var i = 0; i < data[e].Value.length; i++) {
|
for (var i = 0; i < data[e].value.length; i++) {
|
||||||
for (var label in data[e].Value[i].Metric) {
|
for (var label in data[e].value[i].metric) {
|
||||||
if (!(label in labelValues)) {
|
if (!(label in labelValues)) {
|
||||||
labelValues[label] = {};
|
labelValues[label] = {};
|
||||||
}
|
}
|
||||||
labelValues[label][data[e].Value[i].Metric[label]] = 1;
|
labelValues[label][data[e].value[i].metric[label]] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue