Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split out logs into subcommands #151

Merged
merged 7 commits into from
Mar 15, 2021
Merged
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 124 additions & 59 deletions internal/cli/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,79 @@ import (
"gopkg.in/auth0.v5/management"
)

func getLatestLogs(cli *cli, n int, clientID string) ([]*management.Log, error) {
page := 0
perPage := n
func logsCmd(cli *cli) *cobra.Command {
cmd := &cobra.Command{
Use: "logs",
Short: "View tenant logs",
}

if perPage > 1000 {
// Pagination max out at 1000 entries in total
// https://auth0.com/docs/logs/retrieve-log-events-using-mgmt-api#limitations
perPage = 1000
cmd.SetUsageTemplate(resourceUsageTemplate())
cmd.AddCommand(listLogsCmd(cli))
cmd.AddCommand(tailLogsCmd(cli))

return cmd
}

func listLogsCmd(cli *cli) *cobra.Command {
var flags struct {
Num int
NoColor bool
}

queryParams := []management.RequestOption{
management.Parameter("sort", "date:-1"),
management.Parameter("page", fmt.Sprintf("%d", page)),
management.Parameter("per_page", fmt.Sprintf("%d", perPage))}
var inputs struct {
ClientID string
}

if clientID != "" {
queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, clientID)))
cmd := &cobra.Command{
Use: "list [client-id]",
Args: cobra.MaximumNArgs(1),
Short: "Show the tenant logs",
Long: `Show the tenant logs:

auth0 logs list [client-id]
`,
RunE: func(cmd *cobra.Command, args []string) error {
inputs.ClientID = ""
if len(args) == 1 {
inputs.ClientID = args[0]
}

list, err := getLatestLogs(cli, flags.Num, inputs.ClientID)
if err != nil {
return fmt.Errorf("An unexpected error occurred while getting logs: %v", err)
}

// TODO(cyx): This is a hack for now to make the
// streaming work faster.
//
// Create a `set` to detect duplicates clientside.
// set := make(map[string]struct{})
// list = dedupLogs(list, set)

var logsCh chan []*management.Log

// We create an execution API decorator which provides
// a leaky bucket implementation for Read. This
// protects us from being rate limited since we
// potentially have an N+1 querying situation.
actionExecutionAPI := actions.NewSampledExecutionAPI(
cli.api.ActionExecution, time.Second,
)

cli.renderer.LogList(list, logsCh, actionExecutionAPI, flags.NoColor, !cli.debug)
return nil
},
}

return cli.api.Log.List(queryParams...)
cmd.Flags().IntVarP(&flags.Num, "num-entries", "n", 100, "the number of log entries to print")
cmd.Flags().BoolVar(&flags.NoColor, "no-color", false, "turn off colored print")

return cmd
}

func logsCmd(cli *cli) *cobra.Command {
func tailLogsCmd(cli *cli) *cobra.Command {
var flags struct {
Num int
Follow bool
NoColor bool
}

Expand All @@ -44,12 +91,12 @@ func logsCmd(cli *cli) *cobra.Command {
}

cmd := &cobra.Command{
Use: "logs [client-id]",
Use: "tail [client-id]",
Args: cobra.MaximumNArgs(1),
Short: "Show the tenant logs",
Long: `Show the tenant logs:
Short: "Tail the tenant logs",
Long: `Tail the tenant logs:

auth0 logs [client-id]
auth0 logs tail [client-id]
`,
RunE: func(cmd *cobra.Command, args []string) error {
inputs.ClientID = ""
Expand All @@ -73,46 +120,43 @@ auth0 logs [client-id]
lastLogID = list[len(list)-1].GetLogID()
}

var logsCh chan []*management.Log
if flags.Follow && lastLogID != "" {
logsCh = make(chan []*management.Log)

go func() {
// This is pretty important and allows
// us to close / terminate the command.
defer close(logsCh)

for {
queryParams := []management.RequestOption{
management.Query(fmt.Sprintf("log_id:[%s TO *]", lastLogID)),
management.Parameter("page", "0"),
management.Parameter("per_page", "100"),
management.Parameter("sort", "date:-1"),
}

if inputs.ClientID != "" {
queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, inputs.ClientID)))
}

list, err = cli.api.Log.List(queryParams...)
if err != nil {
cli.renderer.Errorf("An unexpected error occurred while getting logs: %v", err)
return
}

if len(list) > 0 {
logsCh <- dedupLogs(list, set)
lastLogID = list[len(list)-1].GetLogID()
}

if len(list) < 90 {
// Not a lot is happening, sleep on it
time.Sleep(1 * time.Second)
}
logsCh := make(chan []*management.Log)

go func() {
// This is pretty important and allows
// us to close / terminate the command.
defer close(logsCh)

for {
queryParams := []management.RequestOption{
management.Query(fmt.Sprintf("log_id:[%s TO *]", lastLogID)),
management.Parameter("page", "0"),
management.Parameter("per_page", "100"),
management.Parameter("sort", "date:-1"),
}

}()
}
if inputs.ClientID != "" {
queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, inputs.ClientID)))
}

list, err = cli.api.Log.List(queryParams...)
if err != nil {
cli.renderer.Errorf("An unexpected error occurred while getting logs: %v", err)
return
}

if len(list) > 0 {
logsCh <- dedupLogs(list, set)
lastLogID = list[len(list)-1].GetLogID()
}

if len(list) < 90 {
// Not a lot is happening, sleep on it
time.Sleep(1 * time.Second)
}
}

}()

// We create an execution API decorator which provides
// a leaky bucket implementation for Read. This
Expand All @@ -128,12 +172,33 @@ auth0 logs [client-id]
}

cmd.Flags().IntVarP(&flags.Num, "num-entries", "n", 100, "the number of log entries to print")
cmd.Flags().BoolVarP(&flags.Follow, "follow", "f", false, "Specify if the logs should be streamed")
cmd.Flags().BoolVar(&flags.NoColor, "no-color", false, "turn off colored print")

return cmd
}

func getLatestLogs(cli *cli, n int, clientID string) ([]*management.Log, error) {
page := 0
perPage := n

if perPage > 1000 {
// Pagination max out at 1000 entries in total
// https://auth0.com/docs/logs/retrieve-log-events-using-mgmt-api#limitations
perPage = 1000
}

queryParams := []management.RequestOption{
management.Parameter("sort", "date:-1"),
management.Parameter("page", fmt.Sprintf("%d", page)),
management.Parameter("per_page", fmt.Sprintf("%d", perPage))}

if clientID != "" {
queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, clientID)))
}

return cli.api.Log.List(queryParams...)
}

func dedupLogs(list []*management.Log, set map[string]struct{}) []*management.Log {
res := make([]*management.Log, 0, len(list))

Expand Down