Browse Source

Move durationToString to common place and cleanup error handling.

pull/70/head
Julius Volz 12 years ago
parent
commit
c3d31febd6
  1. 25
      config/config.go
  2. 30
      config/helpers.go
  3. 8
      config/printer.go
  4. 26
      rules/ast/printer.go
  5. 53
      rules/helpers.go
  6. 4
      rules/lexer.l
  7. 4
      rules/lexer.l.go
  8. 72
      utility/strconv.go

25
config/config.go

@ -17,6 +17,7 @@ import (
"errors"
"fmt"
"github.com/prometheus/prometheus/model"
"github.com/prometheus/prometheus/utility"
"time"
)
@ -55,7 +56,7 @@ func (config *Config) AddJob(options map[string]string, targets []Targets) error
return errors.New("Missing job name")
}
if len(targets) == 0 {
return errors.New(fmt.Sprintf("No targets configured for job '%v'", name))
return fmt.Errorf("No targets configured for job '%v'", name)
}
job := &JobConfig{
Targets: tmpJobTargets,
@ -69,18 +70,18 @@ func (config *Config) AddJob(options map[string]string, targets []Targets) error
return nil
}
func (config *GlobalConfig) SetOption(option string, value string) error {
func (config *GlobalConfig) SetOption(option string, value string) (err error) {
switch option {
case "scrape_interval":
config.ScrapeInterval = stringToDuration(value)
config.ScrapeInterval, err = utility.StringToDuration(value)
return nil
case "evaluation_interval":
config.EvaluationInterval = stringToDuration(value)
return nil
config.EvaluationInterval, err = utility.StringToDuration(value)
return err
default:
return errors.New(fmt.Sprintf("Unrecognized global configuration option '%v'", option))
err = fmt.Errorf("Unrecognized global configuration option '%v'", option)
}
return nil
return
}
func (config *GlobalConfig) SetLabels(labels model.LabelSet) {
@ -95,18 +96,16 @@ func (config *GlobalConfig) AddRuleFiles(ruleFiles []string) {
}
}
func (job *JobConfig) SetOption(option string, value string) error {
func (job *JobConfig) SetOption(option string, value string) (err error) {
switch option {
case "name":
job.Name = value
return nil
case "scrape_interval":
job.ScrapeInterval = stringToDuration(value)
return nil
job.ScrapeInterval, err = utility.StringToDuration(value)
default:
return errors.New(fmt.Sprintf("Unrecognized job configuration option '%v'", option))
err = fmt.Errorf("Unrecognized job configuration option '%v'", option)
}
return nil
return
}
func (job *JobConfig) AddTargets(endpoints []string, labels model.LabelSet) {

30
config/helpers.go

@ -17,9 +17,6 @@ import (
"fmt"
"github.com/prometheus/prometheus/model"
"log"
"regexp"
"strconv"
"time"
)
// Unfortunately, more global variables that are needed for parsing.
@ -30,7 +27,9 @@ var tmpTargetLabels = model.LabelSet{}
func configError(error string, v ...interface{}) {
message := fmt.Sprintf(error, v...)
log.Fatal(fmt.Sprintf("Line %v, char %v: %s", yyline, yypos, message))
// TODO: Don't just die here. Pass errors back all the way to the caller
// instead.
log.Fatalf("Line %v, char %v: %s", yyline, yypos, message)
}
func PushJobOption(option string, value string) {
@ -66,26 +65,3 @@ func PopJob() {
tmpJobOptions = map[string]string{}
tmpJobTargets = []Targets{}
}
func stringToDuration(durationStr string) time.Duration {
durationRE := regexp.MustCompile("^([0-9]+)([ywdhms]+)$")
matches := durationRE.FindStringSubmatch(durationStr)
if len(matches) != 3 {
configError("Not a valid duration string: '%v'", durationStr)
}
value, _ := strconv.Atoi(matches[1])
unit := matches[2]
switch unit {
case "y":
value *= 60 * 60 * 24 * 365
case "w":
value *= 60 * 60 * 24 * 7
case "d":
value *= 60 * 60 * 24
case "h":
value *= 60 * 60
case "m":
value *= 60
}
return time.Duration(value) * time.Second
}

8
config/printer.go

@ -16,6 +16,7 @@ package config
import (
"fmt"
"github.com/prometheus/prometheus/model"
"github.com/prometheus/prometheus/utility"
"strings"
)
@ -47,8 +48,8 @@ func labelsToString(indent int, labels model.LabelSet) string {
func (global *GlobalConfig) ToString(indent int) string {
str := indentStr(indent, "global {\n")
str += indentStr(indent+1, "scrape_interval = \"%vs\"\n", global.ScrapeInterval)
str += indentStr(indent+1, "evaluation_interval = \"%vs\"\n", global.EvaluationInterval)
str += indentStr(indent+1, "scrape_interval = \"%s\"\n", utility.DurationToString(global.ScrapeInterval))
str += indentStr(indent+1, "evaluation_interval = \"%s\"\n", utility.DurationToString(global.EvaluationInterval))
str += labelsToString(indent+1, global.Labels)
str += indentStr(indent, "}\n")
str += indentStr(indent+1, "rule_files = [\n")
@ -61,9 +62,8 @@ func (global *GlobalConfig) ToString(indent int) string {
func (job *JobConfig) ToString(indent int) string {
str := indentStr(indent, "job {\n")
str += indentStr(indent+1, "job {\n")
str += indentStr(indent+1, "name = \"%v\"\n", job.Name)
str += indentStr(indent+1, "scrape_interval = \"%vs\"\n", job.ScrapeInterval)
str += indentStr(indent+1, "scrape_interval = \"%s\"\n", utility.DurationToString(job.ScrapeInterval))
for _, targets := range job.Targets {
str += indentStr(indent+1, "targets {\n")
str += indentStr(indent+2, "endpoints = [\n")

26
rules/ast/printer.go

@ -16,6 +16,7 @@ package ast
import (
"encoding/json"
"fmt"
"github.com/prometheus/prometheus/utility"
"sort"
"strings"
"time"
@ -65,29 +66,6 @@ func exprTypeToString(exprType ExprType) string {
return exprTypeMap[exprType]
}
func durationToString(duration time.Duration) string {
seconds := int64(duration / time.Second)
factors := map[string]int64{
"y": 60 * 60 * 24 * 365,
"d": 60 * 60 * 24,
"h": 60 * 60,
"m": 60,
"s": 1,
}
unit := "s"
switch int64(0) {
case seconds % factors["y"]:
unit = "y"
case seconds % factors["d"]:
unit = "d"
case seconds % factors["h"]:
unit = "h"
case seconds % factors["m"]:
unit = "m"
}
return fmt.Sprintf("%v%v", seconds/factors[unit], unit)
}
func (vector Vector) ToString() string {
metricStrings := []string{}
for _, sample := range vector {
@ -228,7 +206,7 @@ func (node *VectorLiteral) ToString() string {
func (node *MatrixLiteral) ToString() string {
vectorString := (&VectorLiteral{labels: node.labels}).ToString()
intervalString := fmt.Sprintf("['%v']", durationToString(node.interval))
intervalString := fmt.Sprintf("['%v']", utility.DurationToString(node.interval))
return vectorString + intervalString
}

53
rules/helpers.go

@ -14,48 +14,15 @@
package rules
import (
"errors"
"fmt"
"github.com/prometheus/prometheus/model"
"github.com/prometheus/prometheus/rules/ast"
"regexp"
"strconv"
"time"
"github.com/prometheus/prometheus/utility"
)
func rulesError(error string, v ...interface{}) error {
return errors.New(fmt.Sprintf(error, v...))
}
// TODO move to common place, currently duplicated in config/
func stringToDuration(durationStr string) (time.Duration, error) {
durationRE := regexp.MustCompile("^([0-9]+)([ywdhms]+)$")
matches := durationRE.FindStringSubmatch(durationStr)
if len(matches) != 3 {
return 0, rulesError("Not a valid duration string: '%v'", durationStr)
}
value, _ := strconv.Atoi(matches[1])
unit := matches[2]
switch unit {
case "y":
value *= 60 * 60 * 24 * 365
case "w":
value *= 60 * 60 * 24
case "d":
value *= 60 * 60 * 24
case "h":
value *= 60 * 60
case "m":
value *= 60
case "s":
value *= 1
}
return time.Duration(value) * time.Second, nil
}
func CreateRule(name string, labels model.LabelSet, root ast.Node, permanent bool) (*Rule, error) {
if root.Type() != ast.VECTOR {
return nil, rulesError("Rule %v does not evaluate to vector type", name)
return nil, fmt.Errorf("Rule %v does not evaluate to vector type", name)
}
return NewRule(name, labels, root.(ast.VectorNode), permanent), nil
}
@ -63,18 +30,18 @@ func CreateRule(name string, labels model.LabelSet, root ast.Node, permanent boo
func NewFunctionCall(name string, args []ast.Node) (ast.Node, error) {
function, err := ast.GetFunction(name)
if err != nil {
return nil, rulesError("Unknown function \"%v\"", name)
return nil, fmt.Errorf("Unknown function \"%v\"", name)
}
functionCall, err := ast.NewFunctionCall(function, args)
if err != nil {
return nil, rulesError(err.Error())
return nil, fmt.Errorf(err.Error())
}
return functionCall, nil
}
func NewVectorAggregation(aggrTypeStr string, vector ast.Node, groupBy []model.LabelName) (*ast.VectorAggregation, error) {
if vector.Type() != ast.VECTOR {
return nil, rulesError("Operand of %v aggregation must be of vector type", aggrTypeStr)
return nil, fmt.Errorf("Operand of %v aggregation must be of vector type", aggrTypeStr)
}
var aggrTypes = map[string]ast.AggrType{
"SUM": ast.SUM,
@ -84,7 +51,7 @@ func NewVectorAggregation(aggrTypeStr string, vector ast.Node, groupBy []model.L
}
aggrType, ok := aggrTypes[aggrTypeStr]
if !ok {
return nil, rulesError("Unknown aggregation type '%v'", aggrTypeStr)
return nil, fmt.Errorf("Unknown aggregation type '%v'", aggrTypeStr)
}
return ast.NewVectorAggregation(aggrType, vector.(ast.VectorNode), groupBy), nil
}
@ -107,11 +74,11 @@ func NewArithExpr(opTypeStr string, lhs ast.Node, rhs ast.Node) (ast.Node, error
}
opType, ok := opTypes[opTypeStr]
if !ok {
return nil, rulesError("Invalid binary operator \"%v\"", opTypeStr)
return nil, fmt.Errorf("Invalid binary operator \"%v\"", opTypeStr)
}
expr, err := ast.NewArithExpr(opType, lhs, rhs)
if err != nil {
return nil, rulesError(err.Error())
return nil, fmt.Errorf(err.Error())
}
return expr, nil
}
@ -123,9 +90,9 @@ func NewMatrix(vector ast.Node, intervalStr string) (ast.MatrixNode, error) {
break
}
default:
return nil, rulesError("Intervals are currently only supported for vector literals.")
return nil, fmt.Errorf("Intervals are currently only supported for vector literals.")
}
interval, err := stringToDuration(intervalStr)
interval, err := utility.StringToDuration(intervalStr)
if err != nil {
return nil, err
}

4
rules/lexer.l

@ -48,7 +48,9 @@ AVG|SUM|MAX|MIN { yylval.str = yytext; return AGGR_OP }
{L}({L}|{D})+ { yylval.str = yytext; return IDENTIFIER }
\-?{D}+(\.{D}*)? { num, err := strconv.ParseFloat(yytext, 32);
if (err != nil) { rulesError("Invalid float %v", yytext) }
if (err != nil && err.(*strconv.NumError).Err == strconv.ErrSyntax) {
panic("Invalid float")
}
yylval.num = model.SampleValue(num)
return NUMBER }

4
rules/lexer.l.go

@ -436,8 +436,8 @@ var yyrules []yyrule = []yyrule{{regexp.MustCompile("[^\\n]"), nil, []yystartcon
}()
{
num, err := strconv.ParseFloat(yytext, 32)
if err != nil {
rulesError("Invalid float %v", yytext)
if err != nil && err.(*strconv.NumError).Err == strconv.ErrSyntax {
panic("Invalid float")
}
yylval.num = model.SampleValue(num)
return yyactionreturn{NUMBER, yyRT_USER_RETURN}

72
utility/strconv.go

@ -0,0 +1,72 @@
// Copyright 2013 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utility
import (
"fmt"
"regexp"
"strconv"
"time"
)
var durationRE = regexp.MustCompile("^([0-9]+)([ywdhms]+)$")
func DurationToString(duration time.Duration) string {
seconds := int64(duration / time.Second)
factors := map[string]int64{
"y": 60 * 60 * 24 * 365,
"d": 60 * 60 * 24,
"h": 60 * 60,
"m": 60,
"s": 1,
}
unit := "s"
switch int64(0) {
case seconds % factors["y"]:
unit = "y"
case seconds % factors["d"]:
unit = "d"
case seconds % factors["h"]:
unit = "h"
case seconds % factors["m"]:
unit = "m"
}
return fmt.Sprintf("%v%v", seconds/factors[unit], unit)
}
func StringToDuration(durationStr string) (duration time.Duration, err error) {
matches := durationRE.FindStringSubmatch(durationStr)
if len(matches) != 3 {
err = fmt.Errorf("Not a valid duration string: '%v'", durationStr)
return
}
durationSeconds, _ := strconv.Atoi(matches[1])
duration = time.Duration(durationSeconds) * time.Second
unit := matches[2]
switch unit {
case "y":
duration *= 60 * 60 * 24 * 365
case "w":
duration *= 60 * 60 * 24 * 7
case "d":
duration *= 60 * 60 * 24
case "h":
duration *= 60 * 60
case "m":
duration *= 60
case "s":
duration *= 1
}
return
}
Loading…
Cancel
Save