diff --git a/rules/ast/ast.go b/rules/ast/ast.go index a279a4f9d..eff53ede5 100644 --- a/rules/ast/ast.go +++ b/rules/ast/ast.go @@ -66,9 +66,10 @@ type Vector []*Sample type Matrix []SampleStream type groupedAggregation struct { - labels clientmodel.COWMetric - value clientmodel.SampleValue - groupCount int + labels clientmodel.COWMetric + value clientmodel.SampleValue + valuesSquaredSum clientmodel.SampleValue + groupCount int } // ---------------------------------------------------------------------------- @@ -128,6 +129,8 @@ const ( Min Max Count + Stdvar + Stddev ) // ---------------------------------------------------------------------------- @@ -468,6 +471,12 @@ func (node *VectorAggregation) groupedAggregationsToVector(aggregations map[uint aggregation.value = aggregation.value / clientmodel.SampleValue(aggregation.groupCount) case Count: aggregation.value = clientmodel.SampleValue(aggregation.groupCount) + case Stdvar: + avg := float64(aggregation.value) / float64(aggregation.groupCount) + aggregation.value = clientmodel.SampleValue(float64(aggregation.valuesSquaredSum)/float64(aggregation.groupCount) - avg*avg) + case Stddev: + avg := float64(aggregation.value) / float64(aggregation.groupCount) + aggregation.value = clientmodel.SampleValue(math.Sqrt(float64(aggregation.valuesSquaredSum)/float64(aggregation.groupCount) - avg*avg)) default: // For other aggregations, we already have the right value. } @@ -509,6 +518,10 @@ func (node *VectorAggregation) Eval(timestamp clientmodel.Timestamp) Vector { } case Count: groupedResult.groupCount++ + case Stdvar, Stddev: + groupedResult.value += sample.Value + groupedResult.valuesSquaredSum += sample.Value * sample.Value + groupedResult.groupCount++ default: panic("Unknown aggregation type") } @@ -529,9 +542,10 @@ func (node *VectorAggregation) Eval(timestamp clientmodel.Timestamp) Vector { } } result[groupingKey] = &groupedAggregation{ - labels: m, - value: sample.Value, - groupCount: 1, + labels: m, + value: sample.Value, + valuesSquaredSum: sample.Value * sample.Value, + groupCount: 1, } } } diff --git a/rules/ast/printer.go b/rules/ast/printer.go index 7c9ebcade..182f8544a 100644 --- a/rules/ast/printer.go +++ b/rules/ast/printer.go @@ -60,11 +60,13 @@ func (opType BinOpType) String() string { func (aggrType AggrType) String() string { aggrTypeMap := map[AggrType]string{ - Sum: "SUM", - Avg: "AVG", - Min: "MIN", - Max: "MAX", - Count: "COUNT", + Sum: "SUM", + Avg: "AVG", + Min: "MIN", + Max: "MAX", + Count: "COUNT", + Stdvar: "STDVAR", + Stddev: "STDDEV", } return aggrTypeMap[aggrType] } diff --git a/rules/helpers.go b/rules/helpers.go index 9f4162215..0a53fb126 100644 --- a/rules/helpers.go +++ b/rules/helpers.go @@ -78,11 +78,13 @@ func NewVectorAggregation(aggrTypeStr string, vector ast.Node, groupBy clientmod return nil, fmt.Errorf("operand of %v aggregation must be of vector type", aggrTypeStr) } var aggrTypes = map[string]ast.AggrType{ - "SUM": ast.Sum, - "MAX": ast.Max, - "MIN": ast.Min, - "AVG": ast.Avg, - "COUNT": ast.Count, + "SUM": ast.Sum, + "MAX": ast.Max, + "MIN": ast.Min, + "AVG": ast.Avg, + "COUNT": ast.Count, + "STDVAR": ast.Stdvar, + "STDDEV": ast.Stddev, } aggrType, ok := aggrTypes[aggrTypeStr] if !ok { diff --git a/rules/lexer.l b/rules/lexer.l index d4c9d19af..8bb20a2c8 100644 --- a/rules/lexer.l +++ b/rules/lexer.l @@ -89,8 +89,8 @@ GROUP_LEFT|GROUP_RIGHT lval.str = lexer.token(); return MATCH_MOD group_left|group_right lval.str = strings.ToUpper(lexer.token()); return MATCH_MOD KEEPING_EXTRA|keeping_extra return KEEPING_EXTRA OFFSET|offset return OFFSET -AVG|SUM|MAX|MIN|COUNT lval.str = lexer.token(); return AGGR_OP -avg|sum|max|min|count lval.str = strings.ToUpper(lexer.token()); return AGGR_OP +AVG|SUM|MAX|MIN|COUNT|STDVAR|STDDEV lval.str = lexer.token(); return AGGR_OP +avg|sum|max|min|count|stdvar|stddev lval.str = strings.ToUpper(lexer.token()); return AGGR_OP \<|>|AND|OR|and|or lval.str = strings.ToUpper(lexer.token()); return CMP_OP ==|!=|>=|<=|=~|!~ lval.str = lexer.token(); return CMP_OP [+\-] lval.str = lexer.token(); return ADDITIVE_OP diff --git a/rules/lexer.l.go b/rules/lexer.l.go index 892d1befd..ade39fa7f 100644 --- a/rules/lexer.l.go +++ b/rules/lexer.l.go @@ -56,7 +56,7 @@ yystate0: case 0: // start condition: INITIAL goto yystart1 case 1: // start condition: S_COMMENTS - goto yystart197 + goto yystart209 } goto yystate0 // silence unused label error @@ -116,37 +116,37 @@ yystart1: case c == 'S': goto yystate111 case c == 'W': - goto yystate118 + goto yystate124 case c == '\'': goto yystate9 case c == '\t' || c == '\n' || c == '\r' || c == ' ': goto yystate2 case c == 'a': - goto yystate122 + goto yystate128 case c == 'b': - goto yystate129 + goto yystate135 case c == 'c': - goto yystate130 + goto yystate136 case c == 'd': - goto yystate134 + goto yystate140 case c == 'f': - goto yystate144 + goto yystate150 case c == 'g': - goto yystate146 + goto yystate152 case c == 'i': - goto yystate159 + goto yystate165 case c == 'k': - goto yystate160 + goto yystate166 case c == 'm': - goto yystate172 + goto yystate178 case c == 'o': - goto yystate175 + goto yystate181 case c == 'p': - goto yystate180 + goto yystate186 case c == 's': - goto yystate188 - case c == 'w': goto yystate194 + case c == 'w': + goto yystate206 case c >= '0' && c <= '9': goto yystate25 } @@ -1426,9 +1426,11 @@ yystate111: goto yyrule26 case c == ':': goto yystate27 - case c == 'U': + case c == 'T': goto yystate112 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c == 'U': + goto yystate118 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate31 } @@ -1439,13 +1441,93 @@ yystate112: goto yyrule26 case c == ':': goto yystate27 - case c == 'M': + case c == 'D': goto yystate113 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + case c >= '0' && c <= '9' || c >= 'A' && c <= 'C' || c >= 'E' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate31 } yystate113: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'D': + goto yystate114 + case c == 'V': + goto yystate116 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'C' || c >= 'E' && c <= 'U' || c >= 'W' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate31 + } + +yystate114: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'E': + goto yystate115 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate31 + } + +yystate115: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'V': + goto yystate39 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'U' || c >= 'W' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate31 + } + +yystate116: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'A': + goto yystate117 + case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate31 + } + +yystate117: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'R': + goto yystate39 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate31 + } + +yystate118: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'M': + goto yystate119 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': + goto yystate31 + } + +yystate119: c = lexer.getChar() switch { default: @@ -1453,12 +1535,12 @@ yystate113: case c == ':': goto yystate27 case c == 'M': - goto yystate114 + goto yystate120 case c >= '0' && c <= '9' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate31 } -yystate114: +yystate120: c = lexer.getChar() switch { default: @@ -1466,12 +1548,12 @@ yystate114: case c == ':': goto yystate27 case c == 'A': - goto yystate115 + goto yystate121 case c >= '0' && c <= '9' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate31 } -yystate115: +yystate121: c = lexer.getChar() switch { default: @@ -1479,12 +1561,12 @@ yystate115: case c == ':': goto yystate27 case c == 'R': - goto yystate116 + goto yystate122 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate31 } -yystate116: +yystate122: c = lexer.getChar() switch { default: @@ -1492,12 +1574,12 @@ yystate116: case c == ':': goto yystate27 case c == 'Y': - goto yystate117 + goto yystate123 case c >= '0' && c <= '9' || c >= 'A' && c <= 'X' || c == 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate31 } -yystate117: +yystate123: c = lexer.getChar() switch { default: @@ -1508,7 +1590,7 @@ yystate117: goto yystate31 } -yystate118: +yystate124: c = lexer.getChar() switch { default: @@ -1516,12 +1598,12 @@ yystate118: case c == ':': goto yystate27 case c == 'I': - goto yystate119 + goto yystate125 case c >= '0' && c <= '9' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate31 } -yystate119: +yystate125: c = lexer.getChar() switch { default: @@ -1529,12 +1611,12 @@ yystate119: case c == ':': goto yystate27 case c == 'T': - goto yystate120 + goto yystate126 case c >= '0' && c <= '9' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate31 } -yystate120: +yystate126: c = lexer.getChar() switch { default: @@ -1542,12 +1624,12 @@ yystate120: case c == ':': goto yystate27 case c == 'H': - goto yystate121 + goto yystate127 case c >= '0' && c <= '9' || c >= 'A' && c <= 'G' || c >= 'I' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': goto yystate31 } -yystate121: +yystate127: c = lexer.getChar() switch { default: @@ -1558,7 +1640,7 @@ yystate121: goto yystate31 } -yystate122: +yystate128: c = lexer.getChar() switch { default: @@ -1566,16 +1648,16 @@ yystate122: case c == ':': goto yystate27 case c == 'l': - goto yystate123 + goto yystate129 case c == 'n': - goto yystate126 + goto yystate132 case c == 'v': - goto yystate127 + goto yystate133 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c == 'm' || c >= 'o' && c <= 'u' || c >= 'w' && c <= 'z': goto yystate31 } -yystate123: +yystate129: c = lexer.getChar() switch { default: @@ -1583,12 +1665,12 @@ yystate123: case c == ':': goto yystate27 case c == 'e': - goto yystate124 + goto yystate130 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate31 } -yystate124: +yystate130: c = lexer.getChar() switch { default: @@ -1596,12 +1678,12 @@ yystate124: case c == ':': goto yystate27 case c == 'r': - goto yystate125 + goto yystate131 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': goto yystate31 } -yystate125: +yystate131: c = lexer.getChar() switch { default: @@ -1614,7 +1696,7 @@ yystate125: goto yystate31 } -yystate126: +yystate132: c = lexer.getChar() switch { default: @@ -1627,7 +1709,7 @@ yystate126: goto yystate31 } -yystate127: +yystate133: c = lexer.getChar() switch { default: @@ -1635,12 +1717,12 @@ yystate127: case c == ':': goto yystate27 case c == 'g': - goto yystate128 + goto yystate134 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': goto yystate31 } -yystate128: +yystate134: c = lexer.getChar() switch { default: @@ -1651,7 +1733,7 @@ yystate128: goto yystate31 } -yystate129: +yystate135: c = lexer.getChar() switch { default: @@ -1664,7 +1746,7 @@ yystate129: goto yystate31 } -yystate130: +yystate136: c = lexer.getChar() switch { default: @@ -1672,12 +1754,12 @@ yystate130: case c == ':': goto yystate27 case c == 'o': - goto yystate131 + goto yystate137 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': goto yystate31 } -yystate131: +yystate137: c = lexer.getChar() switch { default: @@ -1685,12 +1767,12 @@ yystate131: case c == ':': goto yystate27 case c == 'u': - goto yystate132 + goto yystate138 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': goto yystate31 } -yystate132: +yystate138: c = lexer.getChar() switch { default: @@ -1698,12 +1780,12 @@ yystate132: case c == ':': goto yystate27 case c == 'n': - goto yystate133 + goto yystate139 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': goto yystate31 } -yystate133: +yystate139: c = lexer.getChar() switch { default: @@ -1711,12 +1793,12 @@ yystate133: case c == ':': goto yystate27 case c == 't': - goto yystate128 + goto yystate134 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': goto yystate31 } -yystate134: +yystate140: c = lexer.getChar() switch { default: @@ -1724,12 +1806,12 @@ yystate134: case c == ':': goto yystate27 case c == 'e': - goto yystate135 + goto yystate141 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate31 } -yystate135: +yystate141: c = lexer.getChar() switch { default: @@ -1737,12 +1819,12 @@ yystate135: case c == ':': goto yystate27 case c == 's': - goto yystate136 + goto yystate142 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': goto yystate31 } -yystate136: +yystate142: c = lexer.getChar() switch { default: @@ -1750,12 +1832,12 @@ yystate136: case c == ':': goto yystate27 case c == 'c': - goto yystate137 + goto yystate143 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c == 'a' || c == 'b' || c >= 'd' && c <= 'z': goto yystate31 } -yystate137: +yystate143: c = lexer.getChar() switch { default: @@ -1763,12 +1845,12 @@ yystate137: case c == ':': goto yystate27 case c == 'r': - goto yystate138 + goto yystate144 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': goto yystate31 } -yystate138: +yystate144: c = lexer.getChar() switch { default: @@ -1776,12 +1858,12 @@ yystate138: case c == ':': goto yystate27 case c == 'i': - goto yystate139 + goto yystate145 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': goto yystate31 } -yystate139: +yystate145: c = lexer.getChar() switch { default: @@ -1789,12 +1871,12 @@ yystate139: case c == ':': goto yystate27 case c == 'p': - goto yystate140 + goto yystate146 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'o' || c >= 'q' && c <= 'z': goto yystate31 } -yystate140: +yystate146: c = lexer.getChar() switch { default: @@ -1802,12 +1884,12 @@ yystate140: case c == ':': goto yystate27 case c == 't': - goto yystate141 + goto yystate147 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': goto yystate31 } -yystate141: +yystate147: c = lexer.getChar() switch { default: @@ -1815,12 +1897,12 @@ yystate141: case c == ':': goto yystate27 case c == 'i': - goto yystate142 + goto yystate148 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': goto yystate31 } -yystate142: +yystate148: c = lexer.getChar() switch { default: @@ -1828,12 +1910,12 @@ yystate142: case c == ':': goto yystate27 case c == 'o': - goto yystate143 + goto yystate149 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': goto yystate31 } -yystate143: +yystate149: c = lexer.getChar() switch { default: @@ -1846,7 +1928,7 @@ yystate143: goto yystate31 } -yystate144: +yystate150: c = lexer.getChar() switch { default: @@ -1854,12 +1936,12 @@ yystate144: case c == ':': goto yystate27 case c == 'o': - goto yystate145 + goto yystate151 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': goto yystate31 } -yystate145: +yystate151: c = lexer.getChar() switch { default: @@ -1872,7 +1954,7 @@ yystate145: goto yystate31 } -yystate146: +yystate152: c = lexer.getChar() switch { default: @@ -1880,12 +1962,12 @@ yystate146: case c == ':': goto yystate27 case c == 'r': - goto yystate147 + goto yystate153 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': goto yystate31 } -yystate147: +yystate153: c = lexer.getChar() switch { default: @@ -1893,12 +1975,12 @@ yystate147: case c == ':': goto yystate27 case c == 'o': - goto yystate148 + goto yystate154 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': goto yystate31 } -yystate148: +yystate154: c = lexer.getChar() switch { default: @@ -1906,12 +1988,12 @@ yystate148: case c == ':': goto yystate27 case c == 'u': - goto yystate149 + goto yystate155 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': goto yystate31 } -yystate149: +yystate155: c = lexer.getChar() switch { default: @@ -1919,12 +2001,12 @@ yystate149: case c == ':': goto yystate27 case c == 'p': - goto yystate150 + goto yystate156 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'o' || c >= 'q' && c <= 'z': goto yystate31 } -yystate150: +yystate156: c = lexer.getChar() switch { default: @@ -1932,12 +2014,12 @@ yystate150: case c == ':': goto yystate27 case c == '_': - goto yystate151 + goto yystate157 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z': goto yystate31 } -yystate151: +yystate157: c = lexer.getChar() switch { default: @@ -1945,14 +2027,14 @@ yystate151: case c == ':': goto yystate27 case c == 'l': - goto yystate152 + goto yystate158 case c == 'r': - goto yystate156 + goto yystate162 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c >= 'm' && c <= 'q' || c >= 's' && c <= 'z': goto yystate31 } -yystate152: +yystate158: c = lexer.getChar() switch { default: @@ -1960,12 +2042,12 @@ yystate152: case c == ':': goto yystate27 case c == 'e': - goto yystate153 + goto yystate159 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate31 } -yystate153: +yystate159: c = lexer.getChar() switch { default: @@ -1973,12 +2055,12 @@ yystate153: case c == ':': goto yystate27 case c == 'f': - goto yystate154 + goto yystate160 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'z': goto yystate31 } -yystate154: +yystate160: c = lexer.getChar() switch { default: @@ -1986,12 +2068,12 @@ yystate154: case c == ':': goto yystate27 case c == 't': - goto yystate155 + goto yystate161 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': goto yystate31 } -yystate155: +yystate161: c = lexer.getChar() switch { default: @@ -2002,7 +2084,7 @@ yystate155: goto yystate31 } -yystate156: +yystate162: c = lexer.getChar() switch { default: @@ -2010,12 +2092,12 @@ yystate156: case c == ':': goto yystate27 case c == 'i': - goto yystate157 + goto yystate163 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': goto yystate31 } -yystate157: +yystate163: c = lexer.getChar() switch { default: @@ -2023,12 +2105,12 @@ yystate157: case c == ':': goto yystate27 case c == 'g': - goto yystate158 + goto yystate164 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': goto yystate31 } -yystate158: +yystate164: c = lexer.getChar() switch { default: @@ -2036,12 +2118,12 @@ yystate158: case c == ':': goto yystate27 case c == 'h': - goto yystate154 + goto yystate160 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'g' || c >= 'i' && c <= 'z': goto yystate31 } -yystate159: +yystate165: c = lexer.getChar() switch { default: @@ -2056,7 +2138,7 @@ yystate159: goto yystate31 } -yystate160: +yystate166: c = lexer.getChar() switch { default: @@ -2064,12 +2146,12 @@ yystate160: case c == ':': goto yystate27 case c == 'e': - goto yystate161 + goto yystate167 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate31 } -yystate161: +yystate167: c = lexer.getChar() switch { default: @@ -2077,12 +2159,12 @@ yystate161: case c == ':': goto yystate27 case c == 'e': - goto yystate162 + goto yystate168 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate31 } -yystate162: +yystate168: c = lexer.getChar() switch { default: @@ -2090,12 +2172,12 @@ yystate162: case c == ':': goto yystate27 case c == 'p': - goto yystate163 + goto yystate169 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'o' || c >= 'q' && c <= 'z': goto yystate31 } -yystate163: +yystate169: c = lexer.getChar() switch { default: @@ -2103,12 +2185,12 @@ yystate163: case c == ':': goto yystate27 case c == 'i': - goto yystate164 + goto yystate170 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': goto yystate31 } -yystate164: +yystate170: c = lexer.getChar() switch { default: @@ -2116,12 +2198,12 @@ yystate164: case c == ':': goto yystate27 case c == 'n': - goto yystate165 + goto yystate171 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': goto yystate31 } -yystate165: +yystate171: c = lexer.getChar() switch { default: @@ -2129,12 +2211,12 @@ yystate165: case c == ':': goto yystate27 case c == 'g': - goto yystate166 + goto yystate172 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': goto yystate31 } -yystate166: +yystate172: c = lexer.getChar() switch { default: @@ -2142,12 +2224,12 @@ yystate166: case c == ':': goto yystate27 case c == '_': - goto yystate167 + goto yystate173 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z': goto yystate31 } -yystate167: +yystate173: c = lexer.getChar() switch { default: @@ -2155,12 +2237,12 @@ yystate167: case c == ':': goto yystate27 case c == 'e': - goto yystate168 + goto yystate174 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate31 } -yystate168: +yystate174: c = lexer.getChar() switch { default: @@ -2168,12 +2250,12 @@ yystate168: case c == ':': goto yystate27 case c == 'x': - goto yystate169 + goto yystate175 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'w' || c == 'y' || c == 'z': goto yystate31 } -yystate169: +yystate175: c = lexer.getChar() switch { default: @@ -2181,12 +2263,12 @@ yystate169: case c == ':': goto yystate27 case c == 't': - goto yystate170 + goto yystate176 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': goto yystate31 } -yystate170: +yystate176: c = lexer.getChar() switch { default: @@ -2194,12 +2276,12 @@ yystate170: case c == ':': goto yystate27 case c == 'r': - goto yystate171 + goto yystate177 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': goto yystate31 } -yystate171: +yystate177: c = lexer.getChar() switch { default: @@ -2212,7 +2294,7 @@ yystate171: goto yystate31 } -yystate172: +yystate178: c = lexer.getChar() switch { default: @@ -2220,14 +2302,14 @@ yystate172: case c == ':': goto yystate27 case c == 'a': - goto yystate173 + goto yystate179 case c == 'i': - goto yystate174 + goto yystate180 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'h' || c >= 'j' && c <= 'z': goto yystate31 } -yystate173: +yystate179: c = lexer.getChar() switch { default: @@ -2235,12 +2317,12 @@ yystate173: case c == ':': goto yystate27 case c == 'x': - goto yystate128 + goto yystate134 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'w' || c == 'y' || c == 'z': goto yystate31 } -yystate174: +yystate180: c = lexer.getChar() switch { default: @@ -2248,12 +2330,12 @@ yystate174: case c == ':': goto yystate27 case c == 'n': - goto yystate128 + goto yystate134 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': goto yystate31 } -yystate175: +yystate181: c = lexer.getChar() switch { default: @@ -2261,7 +2343,7 @@ yystate175: case c == ':': goto yystate27 case c == 'f': - goto yystate176 + goto yystate182 case c == 'n': goto yystate101 case c == 'r': @@ -2270,7 +2352,7 @@ yystate175: goto yystate31 } -yystate176: +yystate182: c = lexer.getChar() switch { default: @@ -2278,12 +2360,12 @@ yystate176: case c == ':': goto yystate27 case c == 'f': - goto yystate177 + goto yystate183 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'z': goto yystate31 } -yystate177: +yystate183: c = lexer.getChar() switch { default: @@ -2291,12 +2373,12 @@ yystate177: case c == ':': goto yystate27 case c == 's': - goto yystate178 + goto yystate184 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'r' || c >= 't' && c <= 'z': goto yystate31 } -yystate178: +yystate184: c = lexer.getChar() switch { default: @@ -2304,12 +2386,12 @@ yystate178: case c == ':': goto yystate27 case c == 'e': - goto yystate179 + goto yystate185 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate31 } -yystate179: +yystate185: c = lexer.getChar() switch { default: @@ -2322,7 +2404,7 @@ yystate179: goto yystate31 } -yystate180: +yystate186: c = lexer.getChar() switch { default: @@ -2330,12 +2412,12 @@ yystate180: case c == ':': goto yystate27 case c == 'e': - goto yystate181 + goto yystate187 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate31 } -yystate181: +yystate187: c = lexer.getChar() switch { default: @@ -2343,12 +2425,12 @@ yystate181: case c == ':': goto yystate27 case c == 'r': - goto yystate182 + goto yystate188 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': goto yystate31 } -yystate182: +yystate188: c = lexer.getChar() switch { default: @@ -2356,12 +2438,12 @@ yystate182: case c == ':': goto yystate27 case c == 'm': - goto yystate183 + goto yystate189 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': goto yystate31 } -yystate183: +yystate189: c = lexer.getChar() switch { default: @@ -2369,12 +2451,12 @@ yystate183: case c == ':': goto yystate27 case c == 'a': - goto yystate184 + goto yystate190 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': goto yystate31 } -yystate184: +yystate190: c = lexer.getChar() switch { default: @@ -2382,12 +2464,12 @@ yystate184: case c == ':': goto yystate27 case c == 'n': - goto yystate185 + goto yystate191 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': goto yystate31 } -yystate185: +yystate191: c = lexer.getChar() switch { default: @@ -2395,12 +2477,12 @@ yystate185: case c == ':': goto yystate27 case c == 'e': - goto yystate186 + goto yystate192 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': goto yystate31 } -yystate186: +yystate192: c = lexer.getChar() switch { default: @@ -2408,12 +2490,12 @@ yystate186: case c == ':': goto yystate27 case c == 'n': - goto yystate187 + goto yystate193 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': goto yystate31 } -yystate187: +yystate193: c = lexer.getChar() switch { default: @@ -2426,20 +2508,102 @@ yystate187: goto yystate31 } -yystate188: +yystate194: c = lexer.getChar() switch { default: goto yyrule26 case c == ':': goto yystate27 + case c == 't': + goto yystate195 case c == 'u': - goto yystate189 - case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': + goto yystate201 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'v' && c <= 'z': goto yystate31 } -yystate189: +yystate195: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'd': + goto yystate196 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'z': + goto yystate31 + } + +yystate196: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'd': + goto yystate197 + case c == 'v': + goto yystate199 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'u' || c >= 'w' && c <= 'z': + goto yystate31 + } + +yystate197: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'e': + goto yystate198 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': + goto yystate31 + } + +yystate198: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'v': + goto yystate134 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'u' || c >= 'w' && c <= 'z': + goto yystate31 + } + +yystate199: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'a': + goto yystate200 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': + goto yystate31 + } + +yystate200: + c = lexer.getChar() + switch { + default: + goto yyrule26 + case c == ':': + goto yystate27 + case c == 'r': + goto yystate134 + case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': + goto yystate31 + } + +yystate201: c = lexer.getChar() switch { default: @@ -2447,12 +2611,12 @@ yystate189: case c == ':': goto yystate27 case c == 'm': - goto yystate190 + goto yystate202 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': goto yystate31 } -yystate190: +yystate202: c = lexer.getChar() switch { default: @@ -2460,12 +2624,12 @@ yystate190: case c == ':': goto yystate27 case c == 'm': - goto yystate191 + goto yystate203 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': goto yystate31 } -yystate191: +yystate203: c = lexer.getChar() switch { default: @@ -2473,12 +2637,12 @@ yystate191: case c == ':': goto yystate27 case c == 'a': - goto yystate192 + goto yystate204 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': goto yystate31 } -yystate192: +yystate204: c = lexer.getChar() switch { default: @@ -2486,12 +2650,12 @@ yystate192: case c == ':': goto yystate27 case c == 'r': - goto yystate193 + goto yystate205 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': goto yystate31 } -yystate193: +yystate205: c = lexer.getChar() switch { default: @@ -2499,12 +2663,12 @@ yystate193: case c == ':': goto yystate27 case c == 'y': - goto yystate117 + goto yystate123 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'x' || c == 'z': goto yystate31 } -yystate194: +yystate206: c = lexer.getChar() switch { default: @@ -2512,12 +2676,12 @@ yystate194: case c == ':': goto yystate27 case c == 'i': - goto yystate195 + goto yystate207 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': goto yystate31 } -yystate195: +yystate207: c = lexer.getChar() switch { default: @@ -2525,12 +2689,12 @@ yystate195: case c == ':': goto yystate27 case c == 't': - goto yystate196 + goto yystate208 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': goto yystate31 } -yystate196: +yystate208: c = lexer.getChar() switch { default: @@ -2538,38 +2702,38 @@ yystate196: case c == ':': goto yystate27 case c == 'h': - goto yystate121 + goto yystate127 case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'g' || c >= 'i' && c <= 'z': goto yystate31 } - goto yystate197 // silence unused label error -yystate197: + goto yystate209 // silence unused label error +yystate209: c = lexer.getChar() -yystart197: +yystart209: switch { default: goto yyabort case c == '*': - goto yystate199 + goto yystate211 case c >= '\x01' && c <= ')' || c >= '+' && c <= 'ΓΏ': - goto yystate198 + goto yystate210 } -yystate198: +yystate210: c = lexer.getChar() goto yyrule3 -yystate199: +yystate211: c = lexer.getChar() switch { default: goto yyrule3 case c == '/': - goto yystate200 + goto yystate212 } -yystate200: +yystate212: c = lexer.getChar() goto yyrule2 @@ -2649,13 +2813,13 @@ yyrule17: // OFFSET|offset { return OFFSET } -yyrule18: // AVG|SUM|MAX|MIN|COUNT +yyrule18: // AVG|SUM|MAX|MIN|COUNT|STDVAR|STDDEV { lval.str = lexer.token() return AGGR_OP goto yystate0 } -yyrule19: // avg|sum|max|min|count +yyrule19: // avg|sum|max|min|count|stdvar|stddev { lval.str = strings.ToUpper(lexer.token()) return AGGR_OP diff --git a/rules/manager/manager.go b/rules/manager/manager.go index 0b1a386a5..6865e7df5 100644 --- a/rules/manager/manager.go +++ b/rules/manager/manager.go @@ -99,7 +99,7 @@ type ruleManager struct { notificationHandler *notification.NotificationHandler prometheusURL string - pathPrefix string + pathPrefix string } // RuleManagerOptions bundles options for the RuleManager. @@ -111,7 +111,7 @@ type RuleManagerOptions struct { SampleAppender storage.SampleAppender PrometheusURL string - PathPrefix string + PathPrefix string } // NewRuleManager returns an implementation of RuleManager, ready to be started diff --git a/rules/rules_test.go b/rules/rules_test.go index 1ff76a070..e19069d59 100644 --- a/rules/rules_test.go +++ b/rules/rules_test.go @@ -1197,13 +1197,13 @@ func TestExpressions(t *testing.T) { `{group="canary", instance="0", job="api-server"} => NaN @[%v]`, }, }, - { + { expr: `sqrt(vector_matching_a)`, output: []string{ `{l="x"} => 3.1622776601683795 @[%v]`, `{l="y"} => 4.47213595499958 @[%v]`, }, - }, + }, { expr: `exp(vector_matching_a)`, output: []string{ @@ -1295,6 +1295,32 @@ func TestExpressions(t *testing.T) { `{l="y"} => -Inf @[%v]`, }, }, + { + expr: `stddev(http_requests)`, + output: []string{ + `{} => 229.12878474779 @[%v]`, + }, + }, + { + expr: `stddev by (instance)(http_requests)`, + output: []string{ + `{instance="0"} => 223.60679774998 @[%v]`, + `{instance="1"} => 223.60679774998 @[%v]`, + }, + }, + { + expr: `stdvar(http_requests)`, + output: []string{ + `{} => 52500 @[%v]`, + }, + }, + { + expr: `stdvar by (instance)(http_requests)`, + output: []string{ + `{instance="0"} => 50000 @[%v]`, + `{instance="1"} => 50000 @[%v]`, + }, + }, } storage, closer := newTestStorage(t) diff --git a/templates/templates.go b/templates/templates.go index b07258482..623fd98f1 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -219,7 +219,7 @@ func NewTemplateExpander(text string, name string, data interface{}, timestamp c return fmt.Sprintf("%.4g%ss", v, prefix) }, "pathPrefix": func() string { - return pathPrefix; + return pathPrefix }, }, } diff --git a/web/api/api.go b/web/api/api.go index 90d1c1453..046d70f1d 100644 --- a/web/api/api.go +++ b/web/api/api.go @@ -37,13 +37,13 @@ func (msrv *MetricsService) RegisterHandler(pathPrefix string) { Handler: http.HandlerFunc(h), } } - http.Handle(pathPrefix + "api/query", prometheus.InstrumentHandler( - pathPrefix + "api/query", handler(msrv.Query), + http.Handle(pathPrefix+"api/query", prometheus.InstrumentHandler( + pathPrefix+"api/query", handler(msrv.Query), )) - http.Handle(pathPrefix + "api/query_range", prometheus.InstrumentHandler( - pathPrefix + "api/query_range", handler(msrv.QueryRange), + http.Handle(pathPrefix+"api/query_range", prometheus.InstrumentHandler( + pathPrefix+"api/query_range", handler(msrv.QueryRange), )) - http.Handle(pathPrefix + "api/metrics", prometheus.InstrumentHandler( - pathPrefix + "api/metrics", handler(msrv.Metrics), + http.Handle(pathPrefix+"api/metrics", prometheus.InstrumentHandler( + pathPrefix+"api/metrics", handler(msrv.Metrics), )) } diff --git a/web/consoles.go b/web/consoles.go index d8874aaae..49346a917 100644 --- a/web/consoles.go +++ b/web/consoles.go @@ -33,7 +33,7 @@ var ( // ConsolesHandler implements http.Handler. type ConsolesHandler struct { - Storage local.Storage + Storage local.Storage PathPrefix string } diff --git a/web/status.go b/web/status.go index 2e905dd2b..c641c9aac 100644 --- a/web/status.go +++ b/web/status.go @@ -32,7 +32,7 @@ type PrometheusStatusHandler struct { RuleManager manager.RuleManager TargetPools map[string]*retrieval.TargetPool - Birth time.Time + Birth time.Time PathPrefix string } diff --git a/web/web.go b/web/web.go index 93a6c952a..bd53b0de5 100644 --- a/web/web.go +++ b/web/web.go @@ -63,39 +63,39 @@ func (ws WebService) ServeForever(pathPrefix string) error { http.Handle(pathPrefix, prometheus.InstrumentHandler( pathPrefix, ws.StatusHandler, )) - http.Handle(pathPrefix + "alerts", prometheus.InstrumentHandler( - pathPrefix + "alerts", ws.AlertsHandler, + http.Handle(pathPrefix+"alerts", prometheus.InstrumentHandler( + pathPrefix+"alerts", ws.AlertsHandler, )) - http.Handle(pathPrefix + "consoles/", prometheus.InstrumentHandler( - pathPrefix + "consoles/", http.StripPrefix(pathPrefix + "consoles/", ws.ConsolesHandler), + http.Handle(pathPrefix+"consoles/", prometheus.InstrumentHandler( + pathPrefix+"consoles/", http.StripPrefix(pathPrefix+"consoles/", ws.ConsolesHandler), )) - http.Handle(pathPrefix + "graph", prometheus.InstrumentHandler( - pathPrefix + "graph", ws.GraphsHandler, + http.Handle(pathPrefix+"graph", prometheus.InstrumentHandler( + pathPrefix+"graph", ws.GraphsHandler, )) - http.Handle(pathPrefix + "heap", prometheus.InstrumentHandler( - pathPrefix + "heap", http.HandlerFunc(dumpHeap), + http.Handle(pathPrefix+"heap", prometheus.InstrumentHandler( + pathPrefix+"heap", http.HandlerFunc(dumpHeap), )) ws.MetricsHandler.RegisterHandler(pathPrefix) - http.Handle(pathPrefix + strings.TrimLeft(*metricsPath, "/"), prometheus.Handler()) + http.Handle(pathPrefix+strings.TrimLeft(*metricsPath, "/"), prometheus.Handler()) if *useLocalAssets { - http.Handle(pathPrefix + "static/", prometheus.InstrumentHandler( - pathPrefix + "static/", http.StripPrefix(pathPrefix + "static/", http.FileServer(http.Dir("web/static"))), + http.Handle(pathPrefix+"static/", prometheus.InstrumentHandler( + pathPrefix+"static/", http.StripPrefix(pathPrefix+"static/", http.FileServer(http.Dir("web/static"))), )) } else { - http.Handle(pathPrefix + "static/", prometheus.InstrumentHandler( - pathPrefix + "static/", http.StripPrefix(pathPrefix + "static/", new(blob.Handler)), + http.Handle(pathPrefix+"static/", prometheus.InstrumentHandler( + pathPrefix+"static/", http.StripPrefix(pathPrefix+"static/", new(blob.Handler)), )) } if *userAssetsPath != "" { - http.Handle(pathPrefix + "user/", prometheus.InstrumentHandler( - pathPrefix + "user/", http.StripPrefix(pathPrefix + "user/", http.FileServer(http.Dir(*userAssetsPath))), + http.Handle(pathPrefix+"user/", prometheus.InstrumentHandler( + pathPrefix+"user/", http.StripPrefix(pathPrefix+"user/", http.FileServer(http.Dir(*userAssetsPath))), )) } if *enableQuit { - http.Handle(pathPrefix + "-/quit", http.HandlerFunc(ws.quitHandler)) + http.Handle(pathPrefix+"-/quit", http.HandlerFunc(ws.quitHandler)) } if pathPrefix != "/" {