package main import ( "flag" "fmt" "os" "strconv" "strings" pb "git.ipng.ch/ipng/nginx-logtail/proto/logtailpb" ) // sharedFlags holds the flags common to every subcommand. type sharedFlags struct { targets []string jsonOut bool website string prefix string uri string status string // kept as string so we can tell "unset" from "0" } // bindShared registers the shared flags on fs and returns a pointer to the // populated struct. Call fs.Parse before reading the struct. func bindShared(fs *flag.FlagSet) (*sharedFlags, *string) { sf := &sharedFlags{} target := fs.String("target", "localhost:9090", "comma-separated host:port list") fs.BoolVar(&sf.jsonOut, "json", false, "emit newline-delimited JSON") fs.StringVar(&sf.website, "website", "", "filter: website") fs.StringVar(&sf.prefix, "prefix", "", "filter: client prefix") fs.StringVar(&sf.uri, "uri", "", "filter: request URI") fs.StringVar(&sf.status, "status", "", "filter: HTTP status code (integer)") return sf, target } func (sf *sharedFlags) resolve(target string) { sf.targets = parseTargets(target) } func parseTargets(s string) []string { seen := make(map[string]bool) var out []string for _, t := range strings.Split(s, ",") { t = strings.TrimSpace(t) if t == "" || seen[t] { continue } seen[t] = true out = append(out, t) } return out } func buildFilter(sf *sharedFlags) *pb.Filter { if sf.website == "" && sf.prefix == "" && sf.uri == "" && sf.status == "" { return nil } f := &pb.Filter{} if sf.website != "" { f.Website = &sf.website } if sf.prefix != "" { f.ClientPrefix = &sf.prefix } if sf.uri != "" { f.HttpRequestUri = &sf.uri } if sf.status != "" { n, err := strconv.Atoi(sf.status) if err != nil { fmt.Fprintf(os.Stderr, "--status: %v\n", err) os.Exit(1) } n32 := int32(n) f.HttpResponse = &n32 } return f } func parseWindow(s string) pb.Window { switch s { case "1m": return pb.Window_W1M case "5m": return pb.Window_W5M case "15m": return pb.Window_W15M case "60m": return pb.Window_W60M case "6h": return pb.Window_W6H case "24h": return pb.Window_W24H default: fmt.Fprintf(os.Stderr, "--window: unknown value %q; valid: 1m 5m 15m 60m 6h 24h\n", s) os.Exit(1) panic("unreachable") } } func parseGroupBy(s string) pb.GroupBy { switch s { case "website": return pb.GroupBy_WEBSITE case "prefix": return pb.GroupBy_CLIENT_PREFIX case "uri": return pb.GroupBy_REQUEST_URI case "status": return pb.GroupBy_HTTP_RESPONSE default: fmt.Fprintf(os.Stderr, "--group-by: unknown value %q; valid: website prefix uri status\n", s) os.Exit(1) panic("unreachable") } } func dieUsage(fs *flag.FlagSet, msg string) { fmt.Fprintln(os.Stderr, msg) fs.PrintDefaults() os.Exit(1) }