Implement filter in status, website and uri in CLI and Frontend

This commit is contained in:
2026-03-14 21:59:30 +01:00
parent 2962590a74
commit afa65a2b29
15 changed files with 1159 additions and 123 deletions

View File

@@ -4,20 +4,22 @@ import (
"flag"
"fmt"
"os"
"strconv"
"strings"
st "git.ipng.ch/ipng/nginx-logtail/internal/store"
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"
targets []string
jsonOut bool
website string
prefix string
uri string
status string // expression: "200", "!=200", ">=400", etc.
websiteRe string // RE2 regex against website
uriRe string // RE2 regex against request URI
}
// bindShared registers the shared flags on fs and returns a pointer to the
@@ -26,10 +28,12 @@ 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)")
fs.StringVar(&sf.website, "website", "", "filter: exact website match")
fs.StringVar(&sf.prefix, "prefix", "", "filter: exact client prefix match")
fs.StringVar(&sf.uri, "uri", "", "filter: exact request URI match")
fs.StringVar(&sf.status, "status", "", "filter: HTTP status expression (200, !=200, >=400, <500, …)")
fs.StringVar(&sf.websiteRe, "website-re", "", "filter: RE2 regex against website")
fs.StringVar(&sf.uriRe, "uri-re", "", "filter: RE2 regex against request URI")
return sf, target
}
@@ -52,7 +56,7 @@ func parseTargets(s string) []string {
}
func buildFilter(sf *sharedFlags) *pb.Filter {
if sf.website == "" && sf.prefix == "" && sf.uri == "" && sf.status == "" {
if sf.website == "" && sf.prefix == "" && sf.uri == "" && sf.status == "" && sf.websiteRe == "" && sf.uriRe == "" {
return nil
}
f := &pb.Filter{}
@@ -66,13 +70,19 @@ func buildFilter(sf *sharedFlags) *pb.Filter {
f.HttpRequestUri = &sf.uri
}
if sf.status != "" {
n, err := strconv.Atoi(sf.status)
if err != nil {
fmt.Fprintf(os.Stderr, "--status: %v\n", err)
n, op, ok := st.ParseStatusExpr(sf.status)
if !ok {
fmt.Fprintf(os.Stderr, "--status: invalid expression %q; use e.g. 200, !=200, >=400, <500\n", sf.status)
os.Exit(1)
}
n32 := int32(n)
f.HttpResponse = &n32
f.HttpResponse = &n
f.StatusOp = op
}
if sf.websiteRe != "" {
f.WebsiteRegex = &sf.websiteRe
}
if sf.uriRe != "" {
f.UriRegex = &sf.uriRe
}
return f
}