diff --git a/notification/notification_test.go b/notification/notification_test.go index b540312fe..7b8637dc5 100644 --- a/notification/notification_test.go +++ b/notification/notification_test.go @@ -81,7 +81,7 @@ func TestNotificationHandler(t *testing.T) { // Correct message. summary: "Summary", 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"}]`, }, } diff --git a/rules/ast/ast.go b/rules/ast/ast.go index b23443cf7..494018839 100644 --- a/rules/ast/ast.go +++ b/rules/ast/ast.go @@ -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. type SampleStream struct { - Metric clientmodel.COWMetric - Values metric.Values + Metric clientmodel.COWMetric `json:"metric"` + Values metric.Values `json:"values"` } // Sample is a single sample belonging to a COWMetric. type Sample struct { - Metric clientmodel.COWMetric - Value clientmodel.SampleValue - Timestamp clientmodel.Timestamp + Metric clientmodel.COWMetric `json:"metric"` + Value clientmodel.SampleValue `json:"value"` + Timestamp clientmodel.Timestamp `json:"timestamp"` } // Vector is basically only an alias for clientmodel.Samples, but the diff --git a/rules/ast/printer.go b/rules/ast/printer.go index 0c5f29d3d..eba3ffe72 100644 --- a/rules/ast/printer.go +++ b/rules/ast/printer.go @@ -37,6 +37,8 @@ const ( JSON ) +const jsonFormatVersion = 1 + func (opType BinOpType) String() string { opTypeMap := map[BinOpType]string{ Add: "+", @@ -121,11 +123,13 @@ func (matrix Matrix) String() string { // ErrorToJSON converts the given error into JSON. func ErrorToJSON(err error) string { errorStruct := struct { - Type string - Value string + Type string `json:"type"` + Value string `json:"value"` + Version int `json:"version"` }{ - Type: "error", - Value: err.Error(), + Type: "error", + Value: err.Error(), + Version: jsonFormatVersion, } errorJSON, err := json.Marshal(errorStruct) @@ -139,11 +143,13 @@ func ErrorToJSON(err error) string { // 'vector', or 'matrix' into its JSON representation. func TypedValueToJSON(data interface{}, typeStr string) string { dataStruct := struct { - Type string - Value interface{} + Type string `json:"type"` + Value interface{} `json:"value"` + Version int `json:"version"` }{ - Type: typeStr, - Value: data, + Type: typeStr, + Value: data, + Version: jsonFormatVersion, } dataJSON, err := json.Marshal(dataStruct) if err != nil { diff --git a/storage/metric/sample.go b/storage/metric/sample.go index 734b00ffc..d1ab1577e 100644 --- a/storage/metric/sample.go +++ b/storage/metric/sample.go @@ -15,13 +15,14 @@ package metric import ( "fmt" + "strconv" clientmodel "github.com/prometheus/client_golang/model" ) // MarshalJSON implements json.Marshaler. 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. diff --git a/web/static/js/graph.js b/web/static/js/graph.js index 0a18c6cc5..29d55c619 100644 --- a/web/static/js/graph.js +++ b/web/static/js/graph.js @@ -385,18 +385,18 @@ Prometheus.Graph.prototype.parseValue = function(value) { Prometheus.Graph.prototype.transformData = function(json) { self = this; 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."); return []; } - var data = json.Value.map(function(ts) { + var data = json.value.map(function(ts) { return { - name: escapeHTML(self.metricToTsName(ts.Metric)), - labels: ts.Metric, - data: ts.Values.map(function(value) { + name: escapeHTML(self.metricToTsName(ts.metric)), + labels: ts.metric, + data: ts.values.map(function(value) { return { - x: value.Timestamp, - y: self.parseValue(value.Value) + x: value[0], + y: self.parseValue(value[1]) } }), color: palette.color() @@ -506,8 +506,8 @@ Prometheus.Graph.prototype.resizeGraph = function() { Prometheus.Graph.prototype.handleGraphResponse = function(json, textStatus) { var self = this - if (json.Type == "error") { - self.showError(json.Value); + if (json.type == "error") { + self.showError(json.value); return; } self.data = self.transformData(json); @@ -526,38 +526,38 @@ Prometheus.Graph.prototype.handleConsoleResponse = function(data, textStatus) { var tBody = self.consoleTab.find(".console_table tbody"); tBody.empty(); - switch(data.Type) { + switch(data.type) { case "vector": - if (data.Value.length === 0) { + if (data.value.length === 0) { tBody.append("no data"); return; } - for (var i = 0; i < data.Value.length; i++) { - var v = data.Value[i]; - var tsName = self.metricToTsName(v.Metric); - tBody.append("" + escapeHTML(tsName) + "" + v.Value + ""); + for (var i = 0; i < data.value.length; i++) { + var v = data.value[i]; + var tsName = self.metricToTsName(v.metric); + tBody.append("" + escapeHTML(tsName) + "" + v.value + ""); } break; case "matrix": - if (data.Value.length === 0) { + if (data.value.length === 0) { tBody.append("no data"); return; } - for (var i = 0; i < data.Value.length; i++) { - var v = data.Value[i]; - var tsName = self.metricToTsName(v.Metric); + for (var i = 0; i < data.value.length; i++) { + var v = data.value[i]; + var tsName = self.metricToTsName(v.metric); var valueText = ""; - for (var j = 0; j < v.Values.length; j++) { - valueText += v.Values[j].Value + " @" + v.Values[j].Timestamp + "
"; + for (var j = 0; j < v.values.length; j++) { + valueText += v.values[j][1] + " @" + v.values[j][0] + "
"; } tBody.append("" + escapeHTML(tsName) + "" + valueText + "") } break; case "scalar": - tBody.append("scalar" + data.Value + ""); + tBody.append("scalar" + data.value + ""); break; case "error": - self.showError(data.Value); + self.showError(data.value); break; default: self.showError("Unsupported value type!"); diff --git a/web/static/js/prom_console.js b/web/static/js/prom_console.js index 6b83896f7..fab2a7b6d 100644 --- a/web/static/js/prom_console.js +++ b/web/static/js/prom_console.js @@ -397,11 +397,11 @@ PromConsole.Graph.prototype._render = function(data) { // Get the data into the right format. var seriesLen = 0; 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++] = { - 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(), - 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. var labelValues = {}; for (var e = 0; e < data.length; e++) { - for (var i = 0; i < data[e].Value.length; i++) { - for (var label in data[e].Value[i].Metric) { + for (var i = 0; i < data[e].value.length; i++) { + for (var label in data[e].value[i].metric) { if (!(label in labelValues)) { labelValues[label] = {}; } - labelValues[label][data[e].Value[i].Metric[label]] = 1; + labelValues[label][data[e].value[i].metric[label]] = 1; } } }