func readAddRouteConsistentHashing(s *toki.Scanner, table *tbl.Table) error { t := s.Next() if t.Token != word { return errFmtAddRoute } key := string(t.Value) prefix, sub, regex, err := readRouteOpts(s) if err != nil { return err } destinations, err := readDestinations(s, table, false) if err != nil { return err } if len(destinations) < 2 { return fmt.Errorf("must get at least 2 destination for route '%s'", key) } route, err := route.NewConsistentHashing(key, prefix, sub, regex, destinations) if err != nil { return err } table.AddRoute(route) return nil }
func readAddRewriter(s *toki.Scanner, table *tbl.Table) error { var t *toki.Result if t = s.Next(); t.Token != word { return errFmtAddRewriter } old := t.Value if t = s.Next(); t.Token != word { return errFmtAddRewriter } new := t.Value // token can be a word if it's a negative number. we should probably not have a separate number token, since numbers could be in so many formats // and we try out Atoi (or whatever fits) anyway. if t = s.Next(); t.Token != num && t.Token != word { return errFmtAddRewriter } max, err := strconv.Atoi(strings.TrimSpace(string(t.Value))) if err != nil { return errFmtAddRewriter } rw, err := rewriter.NewFromByte(old, new, max) if err != nil { return err } table.AddRewriter(rw) return nil }
func readAddRoute(s *toki.Scanner, table *tbl.Table, constructor func(key, prefix, sub, regex string, destinations []*destination.Destination) (route.Route, error)) error { t := s.Next() if t.Token != word { return errFmtAddRoute } key := string(t.Value) prefix, sub, regex, err := readRouteOpts(s) if err != nil { return err } destinations, err := readDestinations(s, table, true) if err != nil { return err } if len(destinations) == 0 { return fmt.Errorf("must get at least 1 destination for route '%s'", key) } route, err := constructor(key, prefix, sub, regex, destinations) if err != nil { return err } table.AddRoute(route) return nil }
func readDelRoute(s *toki.Scanner, table *tbl.Table) error { t := s.Next() if t.Token != word { return errors.New("need route key") } key := string(t.Value) return table.DelRoute(key) }
func readModDest(s *toki.Scanner, table *tbl.Table) error { t := s.Next() if t.Token != word { return errFmtAddRoute } key := string(t.Value) t = s.Next() if t.Token != num { return errFmtAddRoute } index, err := strconv.Atoi(strings.TrimSpace(string(t.Value))) if err != nil { return err } opts := make(map[string]string) for t.Token != toki.EOF { t = s.Next() switch t.Token { case toki.EOF: break case optAddr: if t = s.Next(); t.Token != word { return errFmtModDest } opts["addr"] = string(t.Value) case optPrefix: if t = s.Next(); t.Token != word { return errFmtModDest } opts["prefix"] = string(t.Value) case optSub: if t = s.Next(); t.Token != word { return errFmtModDest } opts["sub"] = string(t.Value) case optRegex: if t = s.Next(); t.Token != word { return errFmtModDest } opts["regex"] = string(t.Value) default: return errFmtModDest } } if len(opts) == 0 { return errors.New("modDest needs at least 1 option") } return table.UpdateDestination(key, index, opts) }
func readAddAgg(s *toki.Scanner, table *tbl.Table) error { t := s.Next() if t.Token != sumFn && t.Token != avgFn { return errors.New("invalid function. need sum/avg") } fun := string(t.Value) if t = s.Next(); t.Token != word { return errors.New("need a regex string") } regex := string(t.Value) if t = s.Next(); t.Token != word { return errors.New("need a format string") } outFmt := string(t.Value) if t = s.Next(); t.Token != num { return errors.New("need an interval number") } interval, err := strconv.Atoi(strings.TrimSpace(string(t.Value))) if err != nil { return err } if t = s.Next(); t.Token != num { return errors.New("need a wait number") } wait, err := strconv.Atoi(strings.TrimSpace(string(t.Value))) if err != nil { return err } agg, err := aggregator.New(fun, regex, outFmt, uint(interval), uint(wait), table.In) if err != nil { return err } table.AddAggregator(agg) return nil }
func readModRoute(s *toki.Scanner, table *tbl.Table) error { t := s.Next() if t.Token != word { return errFmtAddRoute } key := string(t.Value) opts := make(map[string]string) for t.Token != toki.EOF { t = s.Next() switch t.Token { case toki.EOF: break case optPrefix: if t = s.Next(); t.Token != word { return errFmtModDest } opts["prefix"] = string(t.Value) case optSub: if t = s.Next(); t.Token != word { return errFmtModDest } opts["sub"] = string(t.Value) case optRegex: if t = s.Next(); t.Token != word { return errFmtModDest } opts["regex"] = string(t.Value) default: return errFmtModDest } } if len(opts) == 0 { return errors.New("modRoute needs at least 1 option") } return table.UpdateRoute(key, opts) }
func readAddBlack(s *toki.Scanner, table *tbl.Table) error { prefix_pat := "" sub_pat := "" regex_pat := "" t := s.Next() if t.Token != word { return errFmtAddBlack } method := string(t.Value) switch method { case "prefix": if t = s.Next(); t.Token != word { return errFmtAddBlack } prefix_pat = string(t.Value) case "sub": if t = s.Next(); t.Token != word { return errFmtAddBlack } sub_pat = string(t.Value) case "regex": if t = s.Next(); t.Token != word { return errFmtAddBlack } regex_pat = string(t.Value) default: return errFmtAddBlack } m, err := matcher.New(prefix_pat, sub_pat, regex_pat) if err != nil { return err } table.AddBlacklist(m) return nil }
func readAddRouteGrafanaNet(s *toki.Scanner, table *tbl.Table) error { t := s.Next() if t.Token != word { return errFmtAddRouteGrafanaNet } key := string(t.Value) prefix, sub, regex, err := readRouteOpts(s) if err != nil { return err } t = s.Next() if t.Token != word { return errFmtAddRouteGrafanaNet } addr := string(t.Value) t = s.Next() if t.Token != word { return errFmtAddRouteGrafanaNet } apiKey := string(t.Value) t = s.Next() if t.Token != word { return errFmtAddRouteGrafanaNet } schemasFile := string(t.Value) t = s.Next() var spool bool sslVerify := true var bufSize = int(1e7) // since a message is typically around 100B this is 1GB var flushMaxNum = 10000 // number of metrics var flushMaxWait = 500 // in ms var timeout = 2000 // in ms for ; t.Token != toki.EOF; t = s.Next() { switch t.Token { case optSpool: t = s.Next() if t.Token == optTrue || t.Token == optFalse { spool, err = strconv.ParseBool(string(t.Value)) if err != nil { return err } } else { return errFmtAddRouteGrafanaNet } case optBufSize: t = s.Next() if t.Token == num { bufSize, err = strconv.Atoi(strings.TrimSpace(string(t.Value))) if err != nil { return err } } else { return errFmtAddRouteGrafanaNet } case optFlushMaxNum: t = s.Next() if t.Token == num { flushMaxNum, err = strconv.Atoi(strings.TrimSpace(string(t.Value))) if err != nil { return err } } else { return errFmtAddRouteGrafanaNet } case optFlushMaxWait: t = s.Next() if t.Token == num { flushMaxWait, err = strconv.Atoi(strings.TrimSpace(string(t.Value))) if err != nil { return err } } else { return errFmtAddRouteGrafanaNet } case optTimeout: t = s.Next() if t.Token == num { timeout, err = strconv.Atoi(strings.TrimSpace(string(t.Value))) if err != nil { return err } } else { return errFmtAddRouteGrafanaNet } case optSSLVerify: t = s.Next() if t.Token == optTrue || t.Token == optFalse { sslVerify, err = strconv.ParseBool(string(t.Value)) if err != nil { return err } } else { return errFmtAddRouteGrafanaNet } default: return fmt.Errorf("unexpected token %d %q", t.Token, t.Value) } } route, err := route.NewGrafanaNet(key, prefix, sub, regex, addr, apiKey, schemasFile, spool, sslVerify, bufSize, flushMaxNum, flushMaxWait, timeout) if err != nil { return err } table.AddRoute(route) return nil }
func shutdownOrFatal(table *tbl.Table, t *testing.T) { err := table.Shutdown() if err != nil { t.Fatal(err) } }