ptyin commented on code in PR #7:
URL: https://github.com/apache/incubator-seata-ctl/pull/7#discussion_r1811973415


##########
action/prometheus/metrics.go:
##########
@@ -0,0 +1,147 @@
+package prometheus
+
+import (
+       "encoding/json"
+       "fmt"
+       "github.com/guptarohit/asciigraph"
+       "github.com/seata/seata-ctl/model"
+       "github.com/spf13/cobra"
+       "gopkg.in/yaml.v3"
+       "io/ioutil"
+       "log"
+       "net/http"
+       "net/url"
+       "os"
+       "strconv"
+)
+
+var MetricsCmd = &cobra.Command{
+       Use:   "metrics",
+       Short: "Show Prometheus metrics",
+       Run: func(cmd *cobra.Command, args []string) {
+               if err := showMetrics(); err != nil {
+                       fmt.Println(err)
+               }
+       },
+}
+
+var Target string
+
+func init() {
+       MetricsCmd.PersistentFlags().StringVar(&Target, "target", 
"seata_transaction_summary", "Namespace name")
+}
+
+// showMetrics executes the metrics collection and chart generation
+func showMetrics() error {
+       prometheusURL, err := getPrometheusAddress()
+       if err != nil {
+               return err
+       }
+
+       // Query Prometheus for metrics
+       result, err := queryPrometheusMetric(prometheusURL, Target)
+       if err != nil {
+               log.Fatalf("Error querying Prometheus: %v", err)
+       }
+
+       // Generate terminal chart from the queried results
+       if err = generateTerminalLineChart(result, Target); err != nil {
+               return err
+       }
+       return nil
+}
+
+// getPrometheusAddress fetches Prometheus server address from configuration
+func getPrometheusAddress() (string, error) {
+       file, err := os.ReadFile("config.yml")
+       if err != nil {
+               log.Fatalf("Failed to read config.yml: %v", err)
+       }
+
+       // Parse the configuration
+       var config model.Config
+       if err = yaml.Unmarshal(file, &config); err != nil {
+               log.Fatalf("Failed to unmarshal YAML: %v", err)
+       }
+
+       // Extract Prometheus address based on context
+       contextName := config.Context.Prometheus
+       var contextPath string
+       for _, server := range config.Prometheus.Servers {
+               if server.Name == contextName {
+                       contextPath = server.Address
+               }
+       }
+       if contextPath == "" {
+               log.Fatalf("Failed to find Prometheus context in config.yml")
+               return "", err
+       }
+       return contextPath, nil
+}
+
+// PrometheusResponse defines the structure of a Prometheus query response
+type PrometheusResponse struct {
+       Status string `json:"status"`
+       Data   struct {
+               ResultType string `json:"resultType"`
+               Result     []struct {
+                       Metric map[string]string `json:"metric"`
+                       Value  []interface{}     `json:"value"`
+               } `json:"result"`
+       } `json:"data"`
+}
+
+// queryPrometheusMetric sends a query to the Prometheus API and returns the 
response
+func queryPrometheusMetric(prometheusURL, query string) (*PrometheusResponse, 
error) {
+       queryURL := fmt.Sprintf("%s/api/v1/query?query=%s", prometheusURL, 
url.QueryEscape(query))
+       resp, err := http.Get(queryURL)
+       if err != nil {
+               return nil, fmt.Errorf("error querying Prometheus: %w", err)
+       }
+       defer resp.Body.Close()
+
+       // Read the response body
+       body, err := ioutil.ReadAll(resp.Body)
+       if err != nil {
+               return nil, fmt.Errorf("error reading response body: %w", err)
+       }
+
+       // Parse JSON response into the PrometheusResponse structure
+       var result PrometheusResponse
+       if err := json.Unmarshal(body, &result); err != nil {
+               return nil, fmt.Errorf("error unmarshalling JSON: %w", err)
+       }
+       return &result, nil
+}
+
+// generateTerminalLineChart generates and prints an ASCII line chart based on 
the Prometheus response
+func generateTerminalLineChart(response *PrometheusResponse, metricName 
string) error {

Review Comment:
   
![](https://bearsblog.oss-cn-beijing.aliyuncs.com/img/3c0e754d67a3fec83d2b085ce14f8b7e.png)



##########
action/prometheus/metrics.go:
##########
@@ -0,0 +1,147 @@
+package prometheus
+
+import (
+       "encoding/json"
+       "fmt"
+       "github.com/guptarohit/asciigraph"
+       "github.com/seata/seata-ctl/model"
+       "github.com/spf13/cobra"
+       "gopkg.in/yaml.v3"
+       "io/ioutil"
+       "log"
+       "net/http"
+       "net/url"
+       "os"
+       "strconv"
+)
+
+var MetricsCmd = &cobra.Command{
+       Use:   "metrics",
+       Short: "Show Prometheus metrics",
+       Run: func(cmd *cobra.Command, args []string) {
+               if err := showMetrics(); err != nil {
+                       fmt.Println(err)
+               }
+       },
+}
+
+var Target string
+
+func init() {
+       MetricsCmd.PersistentFlags().StringVar(&Target, "target", 
"seata_transaction_summary", "Namespace name")
+}
+
+// showMetrics executes the metrics collection and chart generation
+func showMetrics() error {
+       prometheusURL, err := getPrometheusAddress()
+       if err != nil {
+               return err
+       }
+
+       // Query Prometheus for metrics
+       result, err := queryPrometheusMetric(prometheusURL, Target)
+       if err != nil {
+               log.Fatalf("Error querying Prometheus: %v", err)
+       }
+
+       // Generate terminal chart from the queried results
+       if err = generateTerminalLineChart(result, Target); err != nil {
+               return err
+       }
+       return nil
+}
+
+// getPrometheusAddress fetches Prometheus server address from configuration
+func getPrometheusAddress() (string, error) {
+       file, err := os.ReadFile("config.yml")
+       if err != nil {
+               log.Fatalf("Failed to read config.yml: %v", err)
+       }
+
+       // Parse the configuration
+       var config model.Config
+       if err = yaml.Unmarshal(file, &config); err != nil {
+               log.Fatalf("Failed to unmarshal YAML: %v", err)
+       }
+
+       // Extract Prometheus address based on context
+       contextName := config.Context.Prometheus
+       var contextPath string
+       for _, server := range config.Prometheus.Servers {
+               if server.Name == contextName {
+                       contextPath = server.Address
+               }
+       }
+       if contextPath == "" {
+               log.Fatalf("Failed to find Prometheus context in config.yml")
+               return "", err
+       }
+       return contextPath, nil
+}
+
+// PrometheusResponse defines the structure of a Prometheus query response
+type PrometheusResponse struct {
+       Status string `json:"status"`
+       Data   struct {
+               ResultType string `json:"resultType"`
+               Result     []struct {
+                       Metric map[string]string `json:"metric"`
+                       Value  []interface{}     `json:"value"`
+               } `json:"result"`
+       } `json:"data"`
+}
+
+// queryPrometheusMetric sends a query to the Prometheus API and returns the 
response
+func queryPrometheusMetric(prometheusURL, query string) (*PrometheusResponse, 
error) {
+       queryURL := fmt.Sprintf("%s/api/v1/query?query=%s", prometheusURL, 
url.QueryEscape(query))
+       resp, err := http.Get(queryURL)
+       if err != nil {
+               return nil, fmt.Errorf("error querying Prometheus: %w", err)
+       }
+       defer resp.Body.Close()
+
+       // Read the response body
+       body, err := ioutil.ReadAll(resp.Body)
+       if err != nil {
+               return nil, fmt.Errorf("error reading response body: %w", err)
+       }
+
+       // Parse JSON response into the PrometheusResponse structure
+       var result PrometheusResponse
+       if err := json.Unmarshal(body, &result); err != nil {
+               return nil, fmt.Errorf("error unmarshalling JSON: %w", err)
+       }
+       return &result, nil
+}
+
+// generateTerminalLineChart generates and prints an ASCII line chart based on 
the Prometheus response
+func generateTerminalLineChart(response *PrometheusResponse, metricName 
string) error {

Review Comment:
   LGTM



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@seata.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@seata.apache.org
For additional commands, e-mail: dev-h...@seata.apache.org

Reply via email to