From 270d322e7db871c22e27377736292c23bb89e946 Mon Sep 17 00:00:00 2001 From: Weifeng Wang Date: Tue, 16 Jan 2024 23:16:23 +0800 Subject: [PATCH 1/3] init cli Signed-off-by: Weifeng Wang --- go.mod | 3 +++ go.sum | 8 ++++++++ lgtmp/cmd/root.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ lgtmp/main.go | 11 +++++++++++ 4 files changed, 69 insertions(+) create mode 100644 lgtmp/cmd/root.go create mode 100644 lgtmp/main.go diff --git a/go.mod b/go.mod index d705a0af..07021168 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( dagger.io/dagger v0.9.6 github.com/prometheus/client_golang v1.18.0 github.com/prometheus/common v0.46.0 + github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.8.4 ) @@ -17,6 +18,7 @@ require ( github.com/adrg/xdg v0.4.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/google/uuid v1.5.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kr/text v0.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -24,6 +26,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/sosodev/duration v1.2.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect github.com/vektah/gqlparser/v2 v2.5.10 // indirect golang.org/x/exp v0.0.0-20231219180239-dc181d75b848 // indirect golang.org/x/sync v0.5.0 // indirect diff --git a/go.sum b/go.sum index c30b80ae..d99a8c71 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -21,6 +22,8 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -50,10 +53,15 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/sosodev/duration v1.2.0 h1:pqK/FLSjsAADWY74SyWDCjOcd5l7H8GSnnOGEB9A1Us= github.com/sosodev/duration v1.2.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/lgtmp/cmd/root.go b/lgtmp/cmd/root.go new file mode 100644 index 00000000..0ae7c89b --- /dev/null +++ b/lgtmp/cmd/root.go @@ -0,0 +1,47 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package cmd + +import ( + "os" + + "github.com/spf13/cobra" +) + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "lgtmp", + Short: "A brief description of your application", + Long: `A longer description that spans multiple lines and likely contains +examples and usage of using your application. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + // Uncomment the following line if your bare application + // has an action associated with it: + // Run: func(cmd *cobra.Command, args []string) { }, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + err := rootCmd.Execute() + if err != nil { + os.Exit(1) + } +} + +func init() { + // Here you will define your flags and configuration settings. + // Cobra supports persistent flags, which, if defined here, + // will be global for your application. + + // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.lgtmp.yaml)") + + // Cobra also supports local flags, which will only run + // when this action is called directly. + rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/lgtmp/main.go b/lgtmp/main.go new file mode 100644 index 00000000..8dea7361 --- /dev/null +++ b/lgtmp/main.go @@ -0,0 +1,11 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package main + +import "github.com/qclaogui/codelab-monitoring/lgtmp/cmd" + +func main() { + cmd.Execute() +} From 4603bc4ac1aa56af273120dd570c69a8e0c65ab5 Mon Sep 17 00:00:00 2001 From: Weifeng Wang Date: Wed, 17 Jan 2024 18:03:25 +0800 Subject: [PATCH 2/3] LGTMP Stack command line Signed-off-by: Weifeng Wang --- go.mod | 1 + go.sum | 2 + internal/cmd/logs/logs.go | 48 +++++++++++++++++++ internal/cmd/metrics/metrics.go | 84 +++++++++++++++++++++++++++++++++ lgtmp/cmd/delete/delete.go | 30 ++++++++++++ lgtmp/cmd/deploy/deploy.go | 30 ++++++++++++ lgtmp/cmd/down/down.go | 30 ++++++++++++ lgtmp/cmd/root.go | 64 +++++++++++++++---------- lgtmp/cmd/up/up.go | 30 ++++++++++++ 9 files changed, 293 insertions(+), 26 deletions(-) create mode 100644 internal/cmd/logs/logs.go create mode 100644 internal/cmd/metrics/metrics.go create mode 100644 lgtmp/cmd/delete/delete.go create mode 100644 lgtmp/cmd/deploy/deploy.go create mode 100644 lgtmp/cmd/down/down.go create mode 100644 lgtmp/cmd/up/up.go diff --git a/go.mod b/go.mod index 07021168..45a15748 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ toolchain go1.21.5 require ( dagger.io/dagger v0.9.6 + github.com/MakeNowJust/heredoc v1.0.0 github.com/prometheus/client_golang v1.18.0 github.com/prometheus/common v0.46.0 github.com/spf13/cobra v1.8.0 diff --git a/go.sum b/go.sum index d99a8c71..ec852a60 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/99designs/gqlgen v0.17.41 h1:C1/zYMhGVP5TWNCNpmZ9Mb6CqT1Vr5SHEWoTOEJ3 github.com/99designs/gqlgen v0.17.41/go.mod h1:GQ6SyMhwFbgHR0a8r2Wn8fYgEwPxxmndLFPhU63+cJE= github.com/Khan/genqlient v0.6.0 h1:Bwb1170ekuNIVIwTJEqvO8y7RxBxXu639VJOkKSrwAk= github.com/Khan/genqlient v0.6.0/go.mod h1:rvChwWVTqXhiapdhLDV4bp9tz/Xvtewwkon4DpWWCRM= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= diff --git a/internal/cmd/logs/logs.go b/internal/cmd/logs/logs.go new file mode 100644 index 00000000..27df37f8 --- /dev/null +++ b/internal/cmd/logs/logs.go @@ -0,0 +1,48 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package logs + +import ( + "fmt" + "strings" + + "github.com/MakeNowJust/heredoc" + + "github.com/spf13/cobra" +) + +var supportedDeploymentModes = []string{"monolithic-mode", "read-write-mode", "microservices-mode"} +var mode string + +func NewCmdLogs() *cobra.Command { + var logsCmd = &cobra.Command{ + Short: "Run Loki for Logs.", + Use: "logs", + Example: heredoc.Doc(` + # Start up logs in monolithic-mode + $ lgtmp up logs + + # Start up logs in microservices-mode + $ lgtmp up logs --mode microservices-mode + `), + + RunE: func(cmd *cobra.Command, _ []string) error { + // TODO(qc) + action := cmd.Parent().Use + fullCmd := fmt.Sprintf("%s-%s-logs", action, mode) + fmt.Printf("🔥\x1b[91m make %s \x1b[39m\n", fullCmd) + + if err := cmd.Help(); err != nil { + return err + } + return nil + }, + } + + logsCmd.Flags().StringVarP(&mode, "mode", "m", "monolithic-mode", + fmt.Sprintf("deployment mode for logs. Supported modes are: %s.", strings.Join(supportedDeploymentModes, ", "))) + + return logsCmd +} diff --git a/internal/cmd/metrics/metrics.go b/internal/cmd/metrics/metrics.go new file mode 100644 index 00000000..aa746d02 --- /dev/null +++ b/internal/cmd/metrics/metrics.go @@ -0,0 +1,84 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package metrics + +import ( + "fmt" + "os" + "os/exec" + "os/signal" + "strings" + "syscall" + + "github.com/MakeNowJust/heredoc" + + "github.com/spf13/cobra" +) + +var supportedDeploymentModes = []string{"monolithic-mode", "read-write-mode", "microservices-mode"} +var mode string + +func NewCmdMetrics() *cobra.Command { + var metricsCmd = &cobra.Command{ + Short: "Run Mimir for Metrics.", + Use: "metrics", + Example: heredoc.Doc(` + # Start up metrics in monolithic-mode + $ lgtmp up metrics + + # Start up metrics in microservices-mode + $ lgtmp up metrics --mode microservices-mode + `), + + RunE: func(cmd *cobra.Command, _ []string) error { + action := cmd.Parent().Use + target := fmt.Sprintf("%s-%s-metrics", action, mode) + + command := exec.Command("make", "-C", ".", target) + command.Stderr = os.Stderr + command.Stdout = os.Stdout + err := command.Start() + if err != nil { + return err + } + if action == "down" || action == "delete" { + err := command.Wait() + if err != nil { + return err + } + } else { + signalChan := make(chan os.Signal, 1) + signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) + + done := make(chan error, 1) + go func() { done <- command.Wait() }() + + select { + case <-signalChan: + fmt.Printf("Received interrupt signal, stopping %s...\n", target) + _ = command.Process.Signal(os.Interrupt) + select { + case <-signalChan: + fmt.Printf("Forcefully stopping %s...\n", target) + _ = command.Process.Kill() + os.Exit(1) // Exit with a status code of 1 + case <-done: + os.Exit(0) // Exit with a status code of 0 + } + case err := <-done: + if err != nil { + os.Exit(1) // Exit with a status code of 1 upon failure + } + } + } + return nil + }, + } + + metricsCmd.Flags().StringVarP(&mode, "mode", "m", "monolithic-mode", + fmt.Sprintf("deployment mode for metrics. Supported modes are: %s.", strings.Join(supportedDeploymentModes, ", "))) + + return metricsCmd +} diff --git a/lgtmp/cmd/delete/delete.go b/lgtmp/cmd/delete/delete.go new file mode 100644 index 00000000..f3b63104 --- /dev/null +++ b/lgtmp/cmd/delete/delete.go @@ -0,0 +1,30 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package delete + +import ( + "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal/cmd/logs" + "github.com/qclaogui/codelab-monitoring/internal/cmd/metrics" + + "github.com/spf13/cobra" +) + +func NewCmdDelete() *cobra.Command { + var cmd = &cobra.Command{ + Use: "delete", + Short: "Delete LGTMP stack.", + Long: "Provisioning LGTMP stack by Kubernetes.", + Example: heredoc.Doc(` + # lgtmp delete + $ lgtmp delete metrics + `), + } + + cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(logs.NewCmdLogs()) + + return cmd +} diff --git a/lgtmp/cmd/deploy/deploy.go b/lgtmp/cmd/deploy/deploy.go new file mode 100644 index 00000000..516f131a --- /dev/null +++ b/lgtmp/cmd/deploy/deploy.go @@ -0,0 +1,30 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package deploy + +import ( + "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal/cmd/logs" + "github.com/qclaogui/codelab-monitoring/internal/cmd/metrics" + + "github.com/spf13/cobra" +) + +func NewCmdDeploy() *cobra.Command { + var cmd = &cobra.Command{ + Use: "deploy", + Short: "Deploy LGTMP stack.", + Long: "Provisioning LGTMP stack by Kubernetes.", + Example: heredoc.Doc(` + # lgtmp deploy + $ lgtmp deploy metrics + `), + } + + cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(logs.NewCmdLogs()) + + return cmd +} diff --git a/lgtmp/cmd/down/down.go b/lgtmp/cmd/down/down.go new file mode 100644 index 00000000..c911f265 --- /dev/null +++ b/lgtmp/cmd/down/down.go @@ -0,0 +1,30 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package down + +import ( + "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal/cmd/logs" + "github.com/qclaogui/codelab-monitoring/internal/cmd/metrics" + + "github.com/spf13/cobra" +) + +func NewCmdDown() *cobra.Command { + var cmd = &cobra.Command{ + Use: "down", + Short: "Stop LGTMP stack.", + Long: "Provisioning LGTMP stack by Docker Compose.", + Example: heredoc.Doc(` + # lgtmp down + $ lgtmp down metrics + `), + } + + cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(logs.NewCmdLogs()) + + return cmd +} diff --git a/lgtmp/cmd/root.go b/lgtmp/cmd/root.go index 0ae7c89b..0cbf263d 100644 --- a/lgtmp/cmd/root.go +++ b/lgtmp/cmd/root.go @@ -7,41 +7,53 @@ package cmd import ( "os" + "github.com/MakeNowJust/heredoc" + deleteCmd "github.com/qclaogui/codelab-monitoring/lgtmp/cmd/delete" + deployCmd "github.com/qclaogui/codelab-monitoring/lgtmp/cmd/deploy" + downCmd "github.com/qclaogui/codelab-monitoring/lgtmp/cmd/down" + upCmd "github.com/qclaogui/codelab-monitoring/lgtmp/cmd/up" "github.com/spf13/cobra" ) -// rootCmd represents the base command when called without any subcommands -var rootCmd = &cobra.Command{ - Use: "lgtmp", - Short: "A brief description of your application", - Long: `A longer description that spans multiple lines and likely contains -examples and usage of using your application. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, +// NewCmdRoot represents the base command when called without any subcommands +func NewCmdRoot() *cobra.Command { + cmd := &cobra.Command{ + Use: "lgtmp [flags]", + Short: "LGTMP CLI", + // Long: `Grafana LGTMP Stack from the command line.`, + Long: heredoc.Doc(` + Grafana LGTMP Stack from the command line. + L -> Loki Like Prometheus, but for logs. + G -> Grafana The open and composable observability and data visualization platform. + T -> Tempo A high volume, minimal dependency distributed tracing backend. + M -> Mimir The most scalable Prometheus backend. + P -> Pyroscope Continuous Profiling Platform. Debug performance issues down to a single line of code. + `), + + Example: heredoc.Doc(` + $ lgtmp up metrics + `), + } + + cmd.PersistentFlags().Bool("help", false, "Show help for command") + + // Child commands provisioning by Docker Compose + cmd.AddCommand(upCmd.NewCmdUp()) + cmd.AddCommand(downCmd.NewCmdDown()) + + // Child commands provisioning by Kubernetes + cmd.AddCommand(deployCmd.NewCmdDeploy()) + cmd.AddCommand(deleteCmd.NewCmdDelete()) + + return cmd } // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { - err := rootCmd.Execute() + cmd := NewCmdRoot() + err := cmd.Execute() if err != nil { os.Exit(1) } } - -func init() { - // Here you will define your flags and configuration settings. - // Cobra supports persistent flags, which, if defined here, - // will be global for your application. - - // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.lgtmp.yaml)") - - // Cobra also supports local flags, which will only run - // when this action is called directly. - rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") -} diff --git a/lgtmp/cmd/up/up.go b/lgtmp/cmd/up/up.go new file mode 100644 index 00000000..761a6bbd --- /dev/null +++ b/lgtmp/cmd/up/up.go @@ -0,0 +1,30 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package up + +import ( + "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal/cmd/logs" + "github.com/qclaogui/codelab-monitoring/internal/cmd/metrics" + + "github.com/spf13/cobra" +) + +func NewCmdUp() *cobra.Command { + var cmd = &cobra.Command{ + Use: "up", + Short: "Start up LGTMP stack.", + Long: "Provisioning LGTMP stack by Docker Compose.", + Example: heredoc.Doc(` + # lgtmp up + $ lgtmp up metrics + `), + } + + cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(logs.NewCmdLogs()) + + return cmd +} From 9faec40717106754c9fa1f99356d6a4970e59514 Mon Sep 17 00:00:00 2001 From: Weifeng Wang Date: Wed, 17 Jan 2024 23:24:20 +0800 Subject: [PATCH 3/3] code refactor --- internal/cmd/all/all.go | 48 ++++++++++++++++++++++++ internal/cmd/logs/logs.go | 10 ++--- internal/cmd/metrics/metrics.go | 44 ++-------------------- internal/cmd/profiles/profiles.go | 48 ++++++++++++++++++++++++ internal/cmd/traces/traces.go | 48 ++++++++++++++++++++++++ internal/common.go | 61 +++++++++++++++++++++++++++++++ lgtmp/cmd/{delete => }/delete.go | 10 ++++- lgtmp/cmd/{deploy => }/deploy.go | 10 ++++- lgtmp/cmd/{down => }/down.go | 10 ++++- lgtmp/cmd/root.go | 13 ++----- lgtmp/cmd/{up => }/up.go | 10 ++++- 11 files changed, 250 insertions(+), 62 deletions(-) create mode 100644 internal/cmd/all/all.go create mode 100644 internal/cmd/profiles/profiles.go create mode 100644 internal/cmd/traces/traces.go create mode 100644 internal/common.go rename lgtmp/cmd/{delete => }/delete.go (67%) rename lgtmp/cmd/{deploy => }/deploy.go (67%) rename lgtmp/cmd/{down => }/down.go (67%) rename lgtmp/cmd/{up => }/up.go (66%) diff --git a/internal/cmd/all/all.go b/internal/cmd/all/all.go new file mode 100644 index 00000000..76307667 --- /dev/null +++ b/internal/cmd/all/all.go @@ -0,0 +1,48 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package all + +import ( + "fmt" + "strings" + + "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal" + + "github.com/spf13/cobra" +) + +var supportedDeploymentModes = []string{"monolithic-mode"} +var mode string + +func NewCmdAll() *cobra.Command { + var allCmd = &cobra.Command{ + Short: "Run Grafana LGTMP Stack All-in-one.", + Use: "all", + Example: heredoc.Doc(` + # Start up all in monolithic-mode + $ lgtmp up all + + # Start up all in microservices-mode + $ lgtmp up all --mode microservices-mode + `), + + RunE: func(cmd *cobra.Command, _ []string) error { + // up-monolithic-mode-all-in-one Run monolithic-mode all-in-one + // deploy-monolithic-mode-all-in-one Deploy monolithic-mode all-in-one + action := cmd.Parent().Use + target := fmt.Sprintf("%s-%s-all-in-one", action, mode) + if err := internal.ExecuteCommand("make", "-C", ".", target); err != nil { + return err + } + return nil + }, + } + + allCmd.Flags().StringVarP(&mode, "mode", "m", "monolithic-mode", + fmt.Sprintf("deployment mode for all-in-one. Supported modes are: %s.", strings.Join(supportedDeploymentModes, ", "))) + + return allCmd +} diff --git a/internal/cmd/logs/logs.go b/internal/cmd/logs/logs.go index 27df37f8..a1bbb978 100644 --- a/internal/cmd/logs/logs.go +++ b/internal/cmd/logs/logs.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal" "github.com/spf13/cobra" ) @@ -29,12 +30,11 @@ func NewCmdLogs() *cobra.Command { `), RunE: func(cmd *cobra.Command, _ []string) error { - // TODO(qc) + // up-monolithic-mode-logs Run monolithic-mode logs + // deploy-monolithic-mode-logs Deploy monolithic-mode logs action := cmd.Parent().Use - fullCmd := fmt.Sprintf("%s-%s-logs", action, mode) - fmt.Printf("🔥\x1b[91m make %s \x1b[39m\n", fullCmd) - - if err := cmd.Help(); err != nil { + target := fmt.Sprintf("%s-%s-logs", action, mode) + if err := internal.ExecuteCommand("make", "-C", ".", target); err != nil { return err } return nil diff --git a/internal/cmd/metrics/metrics.go b/internal/cmd/metrics/metrics.go index aa746d02..399b948e 100644 --- a/internal/cmd/metrics/metrics.go +++ b/internal/cmd/metrics/metrics.go @@ -6,13 +6,10 @@ package metrics import ( "fmt" - "os" - "os/exec" - "os/signal" "strings" - "syscall" "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal" "github.com/spf13/cobra" ) @@ -33,46 +30,13 @@ func NewCmdMetrics() *cobra.Command { `), RunE: func(cmd *cobra.Command, _ []string) error { + // up-monolithic-mode-metrics Run monolithic-mode metrics + // deploy-monolithic-mode-metrics Deploy monolithic-mode metrics action := cmd.Parent().Use target := fmt.Sprintf("%s-%s-metrics", action, mode) - - command := exec.Command("make", "-C", ".", target) - command.Stderr = os.Stderr - command.Stdout = os.Stdout - err := command.Start() - if err != nil { + if err := internal.ExecuteCommand("make", "-C", ".", target); err != nil { return err } - if action == "down" || action == "delete" { - err := command.Wait() - if err != nil { - return err - } - } else { - signalChan := make(chan os.Signal, 1) - signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) - - done := make(chan error, 1) - go func() { done <- command.Wait() }() - - select { - case <-signalChan: - fmt.Printf("Received interrupt signal, stopping %s...\n", target) - _ = command.Process.Signal(os.Interrupt) - select { - case <-signalChan: - fmt.Printf("Forcefully stopping %s...\n", target) - _ = command.Process.Kill() - os.Exit(1) // Exit with a status code of 1 - case <-done: - os.Exit(0) // Exit with a status code of 0 - } - case err := <-done: - if err != nil { - os.Exit(1) // Exit with a status code of 1 upon failure - } - } - } return nil }, } diff --git a/internal/cmd/profiles/profiles.go b/internal/cmd/profiles/profiles.go new file mode 100644 index 00000000..8bbac401 --- /dev/null +++ b/internal/cmd/profiles/profiles.go @@ -0,0 +1,48 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package profiles + +import ( + "fmt" + "strings" + + "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal" + + "github.com/spf13/cobra" +) + +var supportedDeploymentModes = []string{"monolithic-mode", "microservices-mode"} +var mode string + +func NewCmdProfiles() *cobra.Command { + var profilesCmd = &cobra.Command{ + Short: "Run Pyroscope for Profiles.", + Use: "profiles", + Example: heredoc.Doc(` + # Start up profiles in monolithic-mode + $ lgtmp up profiles + + # Start up profiles in microservices-mode + $ lgtmp up profiles --mode microservices-mode + `), + + RunE: func(cmd *cobra.Command, _ []string) error { + // up-monolithic-mode-profiles Run monolithic-mode profiles + // deploy-monolithic-mode-profiles Deploy monolithic-mode profiles + action := cmd.Parent().Use + target := fmt.Sprintf("%s-%s-profiles", action, mode) + if err := internal.ExecuteCommand("make", "-C", ".", target); err != nil { + return err + } + return nil + }, + } + + profilesCmd.Flags().StringVarP(&mode, "mode", "m", "monolithic-mode", + fmt.Sprintf("deployment mode for profiles. Supported modes are: %s.", strings.Join(supportedDeploymentModes, ", "))) + + return profilesCmd +} diff --git a/internal/cmd/traces/traces.go b/internal/cmd/traces/traces.go new file mode 100644 index 00000000..2814d573 --- /dev/null +++ b/internal/cmd/traces/traces.go @@ -0,0 +1,48 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package traces + +import ( + "fmt" + "strings" + + "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal" + + "github.com/spf13/cobra" +) + +var supportedDeploymentModes = []string{"monolithic-mode", "microservices-mode"} +var mode string + +func NewCmdTraces() *cobra.Command { + var tracesCmd = &cobra.Command{ + Short: "Run Tempo for Traces.", + Use: "traces", + Example: heredoc.Doc(` + # Start up traces in monolithic-mode + $ lgtmp up traces + + # Start up traces in microservices-mode + $ lgtmp up traces --mode microservices-mode + `), + + RunE: func(cmd *cobra.Command, _ []string) error { + // up-monolithic-mode-traces Run monolithic-mode traces + // deploy-monolithic-mode-traces Deploy monolithic-mode traces + action := cmd.Parent().Use + target := fmt.Sprintf("%s-%s-traces", action, mode) + if err := internal.ExecuteCommand("make", "-C", ".", target); err != nil { + return err + } + return nil + }, + } + + tracesCmd.Flags().StringVarP(&mode, "mode", "m", "monolithic-mode", + fmt.Sprintf("deployment mode for traces. Supported modes are: %s.", strings.Join(supportedDeploymentModes, ", "))) + + return tracesCmd +} diff --git a/internal/common.go b/internal/common.go new file mode 100644 index 00000000..629e8d83 --- /dev/null +++ b/internal/common.go @@ -0,0 +1,61 @@ +// Copyright © Weifeng Wang +// +// Licensed under the Apache License 2.0. + +package internal + +import ( + "bytes" + "fmt" + "log" + "os" + "os/exec" + "os/signal" + "strings" + "syscall" +) + +func ExecuteCommand(command string, args ...string) error { + cmd := exec.Command(command, args...) + var stderr bytes.Buffer + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + if err := cmd.Start(); err != nil { + log.Fatalf("Error: %s\n", stderr.String()) + } + + // make target is the last argment + target := args[len(args)-1] + if strings.HasPrefix(target, "down-") || strings.HasPrefix(target, "delete-") { + err := cmd.Wait() + if err != nil { + return err + } + } else { + signalChan := make(chan os.Signal, 1) + signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) + + done := make(chan error, 1) + go func() { done <- cmd.Wait() }() + + select { + case <-signalChan: + fmt.Printf("Received interrupt signal, stopping %s...\n", target) + _ = cmd.Process.Signal(os.Interrupt) + select { + case <-signalChan: + fmt.Printf("Force stopping %s...\n", target) + _ = cmd.Process.Kill() + os.Exit(1) // Exit with a status code of 1 + case <-done: + os.Exit(0) // Exit with a status code of 0 + } + case err := <-done: + if err != nil { + os.Exit(1) // Exit with a status code of 1 upon failure + } + } + } + + return nil +} diff --git a/lgtmp/cmd/delete/delete.go b/lgtmp/cmd/delete.go similarity index 67% rename from lgtmp/cmd/delete/delete.go rename to lgtmp/cmd/delete.go index f3b63104..37727c6c 100644 --- a/lgtmp/cmd/delete/delete.go +++ b/lgtmp/cmd/delete.go @@ -2,12 +2,15 @@ // // Licensed under the Apache License 2.0. -package delete +package cmd import ( "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal/cmd/all" "github.com/qclaogui/codelab-monitoring/internal/cmd/logs" "github.com/qclaogui/codelab-monitoring/internal/cmd/metrics" + "github.com/qclaogui/codelab-monitoring/internal/cmd/profiles" + "github.com/qclaogui/codelab-monitoring/internal/cmd/traces" "github.com/spf13/cobra" ) @@ -23,8 +26,11 @@ func NewCmdDelete() *cobra.Command { `), } - cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(all.NewCmdAll()) cmd.AddCommand(logs.NewCmdLogs()) + cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(profiles.NewCmdProfiles()) + cmd.AddCommand(traces.NewCmdTraces()) return cmd } diff --git a/lgtmp/cmd/deploy/deploy.go b/lgtmp/cmd/deploy.go similarity index 67% rename from lgtmp/cmd/deploy/deploy.go rename to lgtmp/cmd/deploy.go index 516f131a..81489b52 100644 --- a/lgtmp/cmd/deploy/deploy.go +++ b/lgtmp/cmd/deploy.go @@ -2,12 +2,15 @@ // // Licensed under the Apache License 2.0. -package deploy +package cmd import ( "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal/cmd/all" "github.com/qclaogui/codelab-monitoring/internal/cmd/logs" "github.com/qclaogui/codelab-monitoring/internal/cmd/metrics" + "github.com/qclaogui/codelab-monitoring/internal/cmd/profiles" + "github.com/qclaogui/codelab-monitoring/internal/cmd/traces" "github.com/spf13/cobra" ) @@ -23,8 +26,11 @@ func NewCmdDeploy() *cobra.Command { `), } - cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(all.NewCmdAll()) cmd.AddCommand(logs.NewCmdLogs()) + cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(profiles.NewCmdProfiles()) + cmd.AddCommand(traces.NewCmdTraces()) return cmd } diff --git a/lgtmp/cmd/down/down.go b/lgtmp/cmd/down.go similarity index 67% rename from lgtmp/cmd/down/down.go rename to lgtmp/cmd/down.go index c911f265..77bb0d81 100644 --- a/lgtmp/cmd/down/down.go +++ b/lgtmp/cmd/down.go @@ -2,12 +2,15 @@ // // Licensed under the Apache License 2.0. -package down +package cmd import ( "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal/cmd/all" "github.com/qclaogui/codelab-monitoring/internal/cmd/logs" "github.com/qclaogui/codelab-monitoring/internal/cmd/metrics" + "github.com/qclaogui/codelab-monitoring/internal/cmd/profiles" + "github.com/qclaogui/codelab-monitoring/internal/cmd/traces" "github.com/spf13/cobra" ) @@ -23,8 +26,11 @@ func NewCmdDown() *cobra.Command { `), } - cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(all.NewCmdAll()) cmd.AddCommand(logs.NewCmdLogs()) + cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(profiles.NewCmdProfiles()) + cmd.AddCommand(traces.NewCmdTraces()) return cmd } diff --git a/lgtmp/cmd/root.go b/lgtmp/cmd/root.go index 0cbf263d..fe6a6a80 100644 --- a/lgtmp/cmd/root.go +++ b/lgtmp/cmd/root.go @@ -8,10 +8,6 @@ import ( "os" "github.com/MakeNowJust/heredoc" - deleteCmd "github.com/qclaogui/codelab-monitoring/lgtmp/cmd/delete" - deployCmd "github.com/qclaogui/codelab-monitoring/lgtmp/cmd/deploy" - downCmd "github.com/qclaogui/codelab-monitoring/lgtmp/cmd/down" - upCmd "github.com/qclaogui/codelab-monitoring/lgtmp/cmd/up" "github.com/spf13/cobra" ) @@ -20,7 +16,6 @@ func NewCmdRoot() *cobra.Command { cmd := &cobra.Command{ Use: "lgtmp [flags]", Short: "LGTMP CLI", - // Long: `Grafana LGTMP Stack from the command line.`, Long: heredoc.Doc(` Grafana LGTMP Stack from the command line. L -> Loki Like Prometheus, but for logs. @@ -38,12 +33,12 @@ func NewCmdRoot() *cobra.Command { cmd.PersistentFlags().Bool("help", false, "Show help for command") // Child commands provisioning by Docker Compose - cmd.AddCommand(upCmd.NewCmdUp()) - cmd.AddCommand(downCmd.NewCmdDown()) + cmd.AddCommand(NewCmdUp()) + cmd.AddCommand(NewCmdDown()) // Child commands provisioning by Kubernetes - cmd.AddCommand(deployCmd.NewCmdDeploy()) - cmd.AddCommand(deleteCmd.NewCmdDelete()) + cmd.AddCommand(NewCmdDeploy()) + cmd.AddCommand(NewCmdDelete()) return cmd } diff --git a/lgtmp/cmd/up/up.go b/lgtmp/cmd/up.go similarity index 66% rename from lgtmp/cmd/up/up.go rename to lgtmp/cmd/up.go index 761a6bbd..9a337864 100644 --- a/lgtmp/cmd/up/up.go +++ b/lgtmp/cmd/up.go @@ -2,12 +2,15 @@ // // Licensed under the Apache License 2.0. -package up +package cmd import ( "github.com/MakeNowJust/heredoc" + "github.com/qclaogui/codelab-monitoring/internal/cmd/all" "github.com/qclaogui/codelab-monitoring/internal/cmd/logs" "github.com/qclaogui/codelab-monitoring/internal/cmd/metrics" + "github.com/qclaogui/codelab-monitoring/internal/cmd/profiles" + "github.com/qclaogui/codelab-monitoring/internal/cmd/traces" "github.com/spf13/cobra" ) @@ -23,8 +26,11 @@ func NewCmdUp() *cobra.Command { `), } - cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(all.NewCmdAll()) cmd.AddCommand(logs.NewCmdLogs()) + cmd.AddCommand(metrics.NewCmdMetrics()) + cmd.AddCommand(profiles.NewCmdProfiles()) + cmd.AddCommand(traces.NewCmdTraces()) return cmd }