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  }