Files
faas-cli/commands/logs.go
Lucas Roesler 893972afff Add flags to control the log output format
**What**
- Add new flags to toggle the name, instance, and timestamp fields.
Additionally, the new `time-format` also allows controlling the actual
timestamp format.
- Also provide the log format flag to allow printing the output as JSON,
key-values, or the plain format.  This should make it easy to integrate
with other tools, like JQ etc.

Signed-off-by: Lucas Roesler <roesler.lucas@gmail.com>
2019-08-19 15:00:32 +01:00

126 lines
4.1 KiB
Go

// Copyright (c) OpenFaaS Author(s) 2019. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
package commands
import (
"fmt"
"os"
"time"
"github.com/openfaas/faas-cli/flags"
"github.com/openfaas/faas-provider/logs"
"github.com/openfaas/faas-cli/proxy"
"github.com/spf13/cobra"
)
var (
logFlagValues logFlags
nowFunc = time.Now
)
type logFlags struct {
instance string
since time.Duration
sinceTime flags.TimestampFlag
follow bool
tail int
token string
logFormat flags.LogFormat
includeName bool
includeInstance bool
timeFormat flags.TimeFormat
}
func init() {
initLogCmdFlags(functionLogsCmd)
faasCmd.AddCommand(functionLogsCmd)
}
var functionLogsCmd = &cobra.Command{
Use: `logs <NAME> [--tls-no-verify] [--gateway]`,
Aliases: []string{"ls"},
Short: "Tail logs from your functions",
Long: "Tail logs from your functions",
Example: `faas-cli logs echo
faas-cli logs echo --tail=5
faas-cli logs echo --follow=false
faas-cli logs echo --follow=false --since=10m
faas-cli logs echo --follow=false --since=2010-01-01T00:00:00Z`,
Args: cobra.MaximumNArgs(1),
RunE: runLogs,
PreRunE: noopPreRunCmd,
}
func noopPreRunCmd(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("function name is required")
}
return nil
}
// initLogCmdFlags configures the logs command flags, this allows the developer to
// reset and reinitialize the flags on the command in unit tests
func initLogCmdFlags(cmd *cobra.Command) {
logFlagValues = logFlags{}
cmd.Flags().StringVarP(&gateway, "gateway", "g", defaultGateway, "Gateway URL starting with http(s)://")
cmd.Flags().BoolVar(&tlsInsecure, "tls-no-verify", false, "Disable TLS validation")
cmd.Flags().DurationVar(&logFlagValues.since, "since", 0*time.Second, "return logs newer than a relative duration like 5s")
cmd.Flags().Var(&logFlagValues.sinceTime, "since-time", "include logs since the given timestamp (RFC3339)")
cmd.Flags().IntVar(&logFlagValues.tail, "tail", -1, "number of recent log lines file to display. Defaults to -1, unlimited if <=0")
cmd.Flags().BoolVar(&logFlagValues.follow, "follow", true, "continue printing new logs until the end of the request, up to 30s")
cmd.Flags().StringVarP(&logFlagValues.token, "token", "k", "", "Pass a JWT token to use instead of basic auth")
logFlagValues.timeFormat = flags.TimeFormat(time.RFC3339)
cmd.Flags().Var(&logFlagValues.logFormat, "format", "output format. Note that JSON format will always include all log message keys (plain|key-value|json)")
cmd.Flags().Var(&logFlagValues.timeFormat, "time-format", "string format for the timestamp, any value go time format string is allowed, empty will not print the timestamp")
cmd.Flags().BoolVar(&logFlagValues.includeName, "name", true, "print the function name")
cmd.Flags().BoolVar(&logFlagValues.includeInstance, "instance", true, "print the function instance name/id")
}
func runLogs(cmd *cobra.Command, args []string) error {
gatewayAddress := getGatewayURL(gateway, defaultGateway, "", os.Getenv(openFaaSURLEnvironment))
if msg := checkTLSInsecure(gatewayAddress, tlsInsecure); len(msg) > 0 {
fmt.Println(msg)
}
logRequest := logRequestFromFlags(cmd, args)
logEvents, err := proxy.GetLogs(gatewayAddress, tlsInsecure, logRequest, logFlagValues.token)
if err != nil {
return err
}
formatter := GetLogFormatter(string(logFlagValues.logFormat))
for logMsg := range logEvents {
fmt.Fprintln(os.Stdout, formatter(logMsg, logFlagValues.timeFormat.String(), logFlagValues.includeName, logFlagValues.includeInstance))
}
return nil
}
func logRequestFromFlags(cmd *cobra.Command, args []string) logs.Request {
return logs.Request{
Name: args[0],
Tail: logFlagValues.tail,
Since: sinceValue(logFlagValues.sinceTime.AsTime(), logFlagValues.since),
Follow: logFlagValues.follow,
}
}
func sinceValue(t time.Time, d time.Duration) *time.Time {
if !t.IsZero() {
return &t
}
if d.String() != "0s" {
ts := nowFunc().Add(-1 * d)
return &ts
}
return nil
}