github.com/apex/up@v1.7.1/internal/cli/logs/logs.go (about) 1 package logs 2 3 import ( 4 "io" 5 "os" 6 "time" 7 8 "github.com/pkg/errors" 9 "github.com/tj/go/term" 10 "github.com/tj/kingpin" 11 12 "github.com/apex/up" 13 "github.com/apex/up/internal/cli/root" 14 "github.com/apex/up/internal/stats" 15 "github.com/apex/up/internal/util" 16 ) 17 18 func init() { 19 cmd := root.Command("logs", "Show log output.") 20 cmd.Example(`up logs`, "Show logs from the past hour.") 21 cmd.Example(`up logs -S 30m`, "Show logs from the past 30 minutes.") 22 cmd.Example(`up logs -S 5h`, "Show logs from the past 5 hours.") 23 cmd.Example(`up logs -f`, "Show live log output.") 24 cmd.Example(`up logs error`, "Show error logs.") 25 cmd.Example(`up logs 'level != "info"'`, "Show non-info logs.") 26 cmd.Example(`up logs 'production (warn or error)'`, "Show 4xx and 5xx responses in production.") 27 cmd.Example(`up logs 'production error method in ("POST", "PUT", "DELETE")'`, "Show production 5xx responses with a POST, PUT, or DELETE method.") 28 cmd.Example(`up logs 'error or fatal'`, "Show error and fatal logs.") 29 cmd.Example(`up logs 'message = "user login"'`, "Show logs with a specific message.") 30 cmd.Example(`up logs 'status = 200 duration > 1.5s'`, "Show 200 responses with latency above 1500ms.") 31 cmd.Example(`up logs 'size > 100kb'`, "Show responses with bodies larger than 100kb.") 32 cmd.Example(`up logs 'status >= 400'`, "Show 4xx and 5xx responses.") 33 cmd.Example(`up logs 'user.email contains "@apex.sh"'`, "Show emails containing @apex.sh.") 34 cmd.Example(`up logs 'user.email = "*@apex.sh"'`, "Show emails ending with @apex.sh.") 35 cmd.Example(`up logs 'user.email = "tj@*"'`, "Show emails starting with tj@.") 36 cmd.Example(`up logs 'method in ("POST", "PUT") ip = "207.*" status = 200 duration >= 50'`, "Show logs with a more complex query.") 37 cmd.Example(`up logs error | jq`, "Pipe JSON error logs to the jq tool.") 38 39 query := cmd.Arg("query", "Query pattern for filtering logs.").String() 40 follow := cmd.Flag("follow", "Follow or tail the live logs.").Short('f').Bool() 41 since := cmd.Flag("since", "Show logs since duration (30s, 5m, 2h, 1h30m, 3d, 1M).").Short('S').Default("1d").String() 42 expand := cmd.Flag("expand", "Show expanded logs.").Short('e').Bool() 43 44 cmd.Action(func(_ *kingpin.ParseContext) error { 45 c, p, err := root.Init() 46 if err != nil { 47 return errors.Wrap(err, "initializing") 48 } 49 50 var s time.Duration 51 52 if *since != "" { 53 s, err = util.ParseDuration(*since) 54 if err != nil { 55 return errors.Wrap(err, "parsing --since duration") 56 } 57 } 58 59 if *follow { 60 s = time.Duration(0) 61 } 62 63 q := *query 64 65 stats.Track("Logs", map[string]interface{}{ 66 "query": q != "", 67 "query_length": len(q), 68 "follow": *follow, 69 "since": s.Round(time.Second), 70 "expand": *expand, 71 }) 72 73 logs := p.Logs(up.LogsConfig{ 74 Region: c.Regions[0], 75 Since: time.Now().Add(-s), 76 Follow: *follow, 77 Expand: *expand, 78 Query: q, 79 OutputJSON: !term.IsTerminal(os.Stdout.Fd()), 80 }) 81 82 if _, err := io.Copy(os.Stdout, logs); err != nil { 83 return errors.Wrap(err, "writing logs") 84 } 85 86 return nil 87 }) 88 }