This commit is contained in:
Aliaksandr Valialkin 2024-05-21 14:19:09 +02:00
parent 3888356bf6
commit 1a8fbdbb06
No known key found for this signature in database
GPG key ID: 52C003EE2BCDB9EB
6 changed files with 749 additions and 18 deletions

View file

@ -42,8 +42,7 @@ func TestStatsCountEmpty(t *testing.T) {
{"_msg", `def`},
{"a", `1`},
},
{
},
{},
{
{"a", `3`},
{"b", `54`},
@ -64,8 +63,7 @@ func TestStatsCountEmpty(t *testing.T) {
{"_msg", `def`},
{"a", `1`},
},
{
},
{},
{
{"a", `3`},
{"b", `54`},
@ -86,8 +84,7 @@ func TestStatsCountEmpty(t *testing.T) {
{"_msg", `def`},
{"a", `1`},
},
{
},
{},
{
{"aa", `3`},
{"bb", `54`},
@ -207,8 +204,7 @@ func TestStatsCountEmpty(t *testing.T) {
{"a", `1`},
{"c", "3"},
},
{
},
{},
{
{"a", `3`},
{"b", `5`},

View file

@ -42,8 +42,7 @@ func TestStatsCount(t *testing.T) {
{"_msg", `def`},
{"a", `1`},
},
{
},
{},
{
{"a", `3`},
{"b", `54`},
@ -64,8 +63,7 @@ func TestStatsCount(t *testing.T) {
{"_msg", `def`},
{"a", `1`},
},
{
},
{},
{
{"a", `3`},
{"b", `54`},
@ -86,8 +84,7 @@ func TestStatsCount(t *testing.T) {
{"_msg", `def`},
{"a", `1`},
},
{
},
{},
{
{"aa", `3`},
{"bb", `54`},
@ -208,8 +205,7 @@ func TestStatsCount(t *testing.T) {
{"a", `1`},
{"c", "3"},
},
{
},
{},
{
{"a", `3`},
{"b", `5`},

View file

@ -154,6 +154,9 @@ func (smp *statsMaxProcessor) updateStateBytes(b []byte) {
}
func (smp *statsMaxProcessor) updateStateString(v string) {
if v == "" {
// Skip empty strings
}
if smp.hasMax && !lessString(smp.max, v) {
return
}
@ -163,7 +166,7 @@ func (smp *statsMaxProcessor) updateStateString(v string) {
func (smp *statsMaxProcessor) finalizeStats() string {
if !smp.hasMax {
return "NaN"
return ""
}
return smp.max
}

View file

@ -0,0 +1,366 @@
package logstorage
import (
"testing"
)
func TestParseStatsMaxSuccess(t *testing.T) {
f := func(pipeStr string) {
t.Helper()
expectParseStatsFuncSuccess(t, pipeStr)
}
f(`max(*)`)
f(`max(a)`)
f(`max(a, b)`)
}
func TestParseStatsMaxFailure(t *testing.T) {
f := func(pipeStr string) {
t.Helper()
expectParseStatsFuncFailure(t, pipeStr)
}
f(`max`)
f(`max(a b)`)
f(`max(x) y`)
}
func TestStatsMax(t *testing.T) {
f := func(pipeStr string, rows, rowsExpected [][]Field) {
t.Helper()
expectPipeResults(t, pipeStr, rows, rowsExpected)
}
f("stats max(*) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
},
}, [][]Field{
{
{"x", "def"},
},
})
f("stats max(a) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
},
}, [][]Field{
{
{"x", "3"},
},
})
f("stats max(a, b) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
{"c", "1232"},
},
}, [][]Field{
{
{"x", "54"},
},
})
f("stats max(b) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
},
}, [][]Field{
{
{"x", "54"},
},
})
f("stats max(c) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
},
}, [][]Field{
{
{"x", ""},
},
})
f("stats max(a) if (b:*) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `3432`},
},
{
{"a", `3`},
{"b", `54`},
},
}, [][]Field{
{
{"x", "3"},
},
})
f("stats by (b) max(a) if (b:*) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
{"b", "3"},
},
{
{"a", `3`},
{"c", `54`},
},
}, [][]Field{
{
{"b", "3"},
{"x", "2"},
},
{
{"b", ""},
{"x", ""},
},
})
f("stats by (a) max(b) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `5`},
},
{
{"a", `3`},
{"b", `7`},
},
}, [][]Field{
{
{"a", "1"},
{"x", "3"},
},
{
{"a", "3"},
{"x", "7"},
},
})
f("stats by (a) max(*) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
{"c", "10"},
},
{
{"a", `3`},
{"b", `5`},
},
{
{"a", `3`},
{"b", `7`},
},
}, [][]Field{
{
{"a", "1"},
{"x", "def"},
},
{
{"a", "3"},
{"x", "7"},
},
})
f("stats by (a) max(c) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"c", `foo`},
},
{
{"a", `3`},
{"b", `7`},
},
}, [][]Field{
{
{"a", "1"},
{"x", ""},
},
{
{"a", "3"},
{"x", "foo"},
},
})
f("stats by (a) max(a, b, c) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `34`},
},
{
{"_msg", `def`},
{"a", `1`},
{"c", "3"},
},
{
{"a", `3`},
{"b", `5`},
},
{
{"a", `3`},
{"b", `7`},
},
}, [][]Field{
{
{"a", "1"},
{"x", "34"},
},
{
{"a", "3"},
{"x", "7"},
},
})
f("stats by (a, b) max(a) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
{"c", "3"},
},
{
{"a", `3`},
{"b", `5`},
},
}, [][]Field{
{
{"a", "1"},
{"b", "3"},
{"x", "1"},
},
{
{"a", "1"},
{"b", ""},
{"x", "1"},
},
{
{"a", "3"},
{"b", "5"},
{"x", "3"},
},
})
f("stats by (a, b) max(c) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
{"c", "foo"},
},
{
{"a", `3`},
{"b", `5`},
{"c", "4"},
},
}, [][]Field{
{
{"a", "1"},
{"b", "3"},
{"x", ""},
},
{
{"a", "1"},
{"b", ""},
{"x", "foo"},
},
{
{"a", "3"},
{"b", "5"},
{"x", "4"},
},
})
}

View file

@ -154,6 +154,10 @@ func (smp *statsMinProcessor) updateStateBytes(b []byte) {
}
func (smp *statsMinProcessor) updateStateString(v string) {
if v == "" {
// Skip empty strings
return
}
if smp.hasMin && !lessString(v, smp.min) {
return
}
@ -163,7 +167,7 @@ func (smp *statsMinProcessor) updateStateString(v string) {
func (smp *statsMinProcessor) finalizeStats() string {
if !smp.hasMin {
return "NaN"
return ""
}
return smp.min
}

View file

@ -0,0 +1,366 @@
package logstorage
import (
"testing"
)
func TestParseStatsMinSuccess(t *testing.T) {
f := func(pipeStr string) {
t.Helper()
expectParseStatsFuncSuccess(t, pipeStr)
}
f(`min(*)`)
f(`min(a)`)
f(`min(a, b)`)
}
func TestParseStatsMinFailure(t *testing.T) {
f := func(pipeStr string) {
t.Helper()
expectParseStatsFuncFailure(t, pipeStr)
}
f(`min`)
f(`min(a b)`)
f(`min(x) y`)
}
func TestStatsMin(t *testing.T) {
f := func(pipeStr string, rows, rowsExpected [][]Field) {
t.Helper()
expectPipeResults(t, pipeStr, rows, rowsExpected)
}
f("stats min(*) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
},
}, [][]Field{
{
{"x", "1"},
},
})
f("stats min(a) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
},
}, [][]Field{
{
{"x", "1"},
},
})
f("stats min(a, b) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
{"c", "1232"},
},
}, [][]Field{
{
{"x", "1"},
},
})
f("stats min(b) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
},
}, [][]Field{
{
{"x", "3"},
},
})
f("stats min(c) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
},
}, [][]Field{
{
{"x", ""},
},
})
f("stats min(a) if (b:*) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `54`},
},
}, [][]Field{
{
{"x", "2"},
},
})
f("stats by (b) min(a) if (b:*) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `2`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `-12.34`},
{"b", "3"},
},
{
{"a", `3`},
{"c", `54`},
},
}, [][]Field{
{
{"b", "3"},
{"x", "-12.34"},
},
{
{"b", ""},
{"x", ""},
},
})
f("stats by (a) min(b) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"b", `5`},
},
{
{"a", `3`},
{"b", `7`},
},
}, [][]Field{
{
{"a", "1"},
{"x", "3"},
},
{
{"a", "3"},
{"x", "5"},
},
})
f("stats by (a) min(*) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
{"c", "-34"},
},
{
{"a", `3`},
{"b", `5`},
},
{
{"a", `3`},
{"b", `7`},
},
}, [][]Field{
{
{"a", "1"},
{"x", "-34"},
},
{
{"a", "3"},
{"x", "3"},
},
})
f("stats by (a) min(c) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
},
{
{"a", `3`},
{"c", `foo`},
},
{
{"a", `3`},
{"b", `7`},
},
}, [][]Field{
{
{"a", "1"},
{"x", ""},
},
{
{"a", "3"},
{"x", "foo"},
},
})
f("stats by (a) min(a, b, c) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `34`},
},
{
{"_msg", `def`},
{"a", `1`},
{"c", "3"},
},
{
{"a", `3`},
{"b", `5`},
},
{
{"a", `3`},
{"b", `7`},
},
}, [][]Field{
{
{"a", "1"},
{"x", "1"},
},
{
{"a", "3"},
{"x", "3"},
},
})
f("stats by (a, b) min(a) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
{"c", "3"},
},
{
{"a", `3`},
{"b", `5`},
},
}, [][]Field{
{
{"a", "1"},
{"b", "3"},
{"x", "1"},
},
{
{"a", "1"},
{"b", ""},
{"x", "1"},
},
{
{"a", "3"},
{"b", "5"},
{"x", "3"},
},
})
f("stats by (a, b) min(c) as x", [][]Field{
{
{"_msg", `abc`},
{"a", `1`},
{"b", `3`},
},
{
{"_msg", `def`},
{"a", `1`},
{"c", "foo"},
},
{
{"a", `3`},
{"b", `5`},
{"c", "4"},
},
}, [][]Field{
{
{"a", "1"},
{"b", "3"},
{"x", ""},
},
{
{"a", "1"},
{"b", ""},
{"x", "foo"},
},
{
{"a", "3"},
{"b", "5"},
{"x", "4"},
},
})
}