From fad619a43be113ba3792f3215a34d8b8bc44334a Mon Sep 17 00:00:00 2001 From: ben hockey Date: Mon, 20 Apr 2015 16:40:05 -0500 Subject: [PATCH 1/5] add test for stddev --- cmd/influxd/server_integration_test.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cmd/influxd/server_integration_test.go b/cmd/influxd/server_integration_test.go index 6c3d05c3728..390f3c658bc 100644 --- a/cmd/influxd/server_integration_test.go +++ b/cmd/influxd/server_integration_test.go @@ -590,6 +590,23 @@ func runTestsData(t *testing.T, testName string, nodes Cluster, database, retent queryDb: "%DB%", expected: `{"results":[{"series":[{"name":"cpu","columns":["time","mean"],"values":[["1970-01-01T00:00:00Z",` + string(maxFloat64) + `]]}]}]}`, }, + { + reset: true, + name: "mean and stddev", + write: `{"database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ + {"name": "cpu", "timestamp": "2000-01-01T00:00:00Z", "fields": {"value": 2}}, + {"name": "cpu", "timestamp": "2000-01-01T00:00:10Z", "fields": {"value": 4}}, + {"name": "cpu", "timestamp": "2000-01-01T00:00:20Z", "fields": {"value": 4}}, + {"name": "cpu", "timestamp": "2000-01-01T00:00:30Z", "fields": {"value": 4}}, + {"name": "cpu", "timestamp": "2000-01-01T00:00:40Z", "fields": {"value": 5}}, + {"name": "cpu", "timestamp": "2000-01-01T00:00:50Z", "fields": {"value": 5}}, + {"name": "cpu", "timestamp": "2000-01-01T00:01:00Z", "fields": {"value": 7}}, + {"name": "cpu", "timestamp": "2000-01-01T00:01:10Z", "fields": {"value": 9}} + ]}`, + query: `SELECT mean(value), stddev(value) FROM cpu WHERE time >= '2000-01-01' AND time < '2000-01-01T00:02:00Z' GROUP BY time(10m)`, + queryDb: "%DB%", + expected: `{"results":[{"series":[{"name":"cpu","columns":["time","mean","stddev"],"values":[["2000-01-01T00:00:00Z",5,2.138089935299395]]}]}]}`, + }, { reset: true, name: "aggregations", From 94030b2782216fb075779ea4e1361b23bae08799 Mon Sep 17 00:00:00 2001 From: ben hockey Date: Mon, 20 Apr 2015 17:06:32 -0500 Subject: [PATCH 2/5] return the values from stddev mapper function --- influxql/functions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/influxql/functions.go b/influxql/functions.go index 3ae5caba327..2b9469b1af2 100644 --- a/influxql/functions.go +++ b/influxql/functions.go @@ -386,7 +386,7 @@ func MapStddev(itr Iterator) interface{} { values = append(values, v.(float64)) } - return nil + return values } // ReduceStddev computes the stddev of values. From 23c38fb03cf4145907c62dd5369c81b1c6163e9d Mon Sep 17 00:00:00 2001 From: ben hockey Date: Wed, 22 Apr 2015 17:23:54 -0500 Subject: [PATCH 3/5] get stddev working this includes avoiding overflow for large values --- cmd/influxd/server_integration_test.go | 6 +++--- influxql/functions.go | 16 +++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/cmd/influxd/server_integration_test.go b/cmd/influxd/server_integration_test.go index 390f3c658bc..a3921c54231 100644 --- a/cmd/influxd/server_integration_test.go +++ b/cmd/influxd/server_integration_test.go @@ -581,14 +581,14 @@ func runTestsData(t *testing.T, testName string, nodes Cluster, database, retent // Aggregations { reset: true, - name: "large mean", + name: "large mean and stddev", write: `{"database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ {"name": "cpu", "timestamp": "2015-04-20T14:27:40Z", "fields": {"value": ` + string(maxFloat64) + `}}, {"name": "cpu", "timestamp": "2015-04-20T14:27:41Z", "fields": {"value": ` + string(maxFloat64) + `}} ]}`, - query: `SELECT mean(value) FROM cpu`, + query: `SELECT mean(value), stddev(value) FROM cpu`, queryDb: "%DB%", - expected: `{"results":[{"series":[{"name":"cpu","columns":["time","mean"],"values":[["1970-01-01T00:00:00Z",` + string(maxFloat64) + `]]}]}]}`, + expected: `{"results":[{"series":[{"name":"cpu","columns":["time","mean","stddev"],"values":[["1970-01-01T00:00:00Z",` + string(maxFloat64) + `,0]]}]}]}`, }, { reset: true, diff --git a/influxql/functions.go b/influxql/functions.go index 2b9469b1af2..a7c4a6a84a6 100644 --- a/influxql/functions.go +++ b/influxql/functions.go @@ -397,7 +397,9 @@ func ReduceStddev(values []interface{}) interface{} { if value == nil { continue } - data = append(data, value.([]float64)...) + for _, val := range value.([]float64) { + data = append(data, val) + } } // If no data or we only have one point, it's nil or undefined @@ -405,13 +407,13 @@ func ReduceStddev(values []interface{}) interface{} { return nil } - // Get the sum - var sum float64 + // Get the mean + var mean float64 + var count int for _, v := range data { - sum += v + count++ + mean += (v - mean) / float64(count) } - // Get the mean - mean := sum / float64(len(data)) // Get the variance var variance float64 for _, v := range data { @@ -419,7 +421,7 @@ func ReduceStddev(values []interface{}) interface{} { sq := math.Pow(dif, 2) variance += sq } - variance = variance / float64(len(data)-1) + variance = variance / float64(count-1) stddev := math.Sqrt(variance) return stddev From 762a77079a2b82947bf9eb5e84a1931ec8287511 Mon Sep 17 00:00:00 2001 From: ben hockey Date: Thu, 23 Apr 2015 10:35:12 -0500 Subject: [PATCH 4/5] unmarshal stddev appropriately --- influxql/functions.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/influxql/functions.go b/influxql/functions.go index a7c4a6a84a6..d3978a452ba 100644 --- a/influxql/functions.go +++ b/influxql/functions.go @@ -153,6 +153,12 @@ func InitializeUnmarshaller(c *Call) (UnmarshalFunc, error) { err := json.Unmarshal(b, &o) return &o, err }, nil + case "stddev": + return func(b []byte) (interface{}, error) { + val := make([]float64, 0) + err := json.Unmarshal(b, &val) + return val, err + }, nil default: return func(b []byte) (interface{}, error) { var val interface{} @@ -397,9 +403,7 @@ func ReduceStddev(values []interface{}) interface{} { if value == nil { continue } - for _, val := range value.([]float64) { - data = append(data, val) - } + data = append(data, value.([]float64)...) } // If no data or we only have one point, it's nil or undefined From ee01a5f66ffba7115939b72ac70530f387e51524 Mon Sep 17 00:00:00 2001 From: ben hockey Date: Wed, 29 Apr 2015 15:40:07 -0500 Subject: [PATCH 5/5] add test for stddev on 1 point --- cmd/influxd/server_integration_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cmd/influxd/server_integration_test.go b/cmd/influxd/server_integration_test.go index a3921c54231..ff7a92fffdb 100644 --- a/cmd/influxd/server_integration_test.go +++ b/cmd/influxd/server_integration_test.go @@ -579,6 +579,16 @@ func runTestsData(t *testing.T, testName string, nodes Cluster, database, retent }, // Aggregations + { + reset: true, + name: "stddev with just one point", + write: `{"database" : "%DB%", "retentionPolicy" : "%RP%", "points": [ + {"name": "cpu", "timestamp": "2015-04-20T14:27:41Z", "fields": {"value": 45}} + ]}`, + query: `SELECT stddev(value) FROM cpu`, + queryDb: "%DB%", + expected: `{"results":[{"series":[{"name":"cpu","columns":["time","stddev"],"values":[["1970-01-01T00:00:00Z",null]]}]}]}`, + }, { reset: true, name: "large mean and stddev",