1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
package server
import (
"context"
"encoding/json"
"fmt"
"sort"
"strconv"
"time"
"github.com/guptarohit/asciigraph"
"github.com/spf13/cobra"
"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/cmd/cmpl"
"github.com/hetznercloud/cli/internal/cmd/output"
"github.com/hetznercloud/cli/internal/cmd/util"
"github.com/hetznercloud/cli/internal/hcapi2"
"github.com/hetznercloud/cli/internal/state"
"github.com/hetznercloud/hcloud-go/v2/hcloud"
)
var MetricsCommand = base.Cmd{
BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
cmd := &cobra.Command{
Use: "metrics [FLAGS] SERVER",
Short: "[ALPHA] Metrics from a Server",
Args: cobra.ExactArgs(1),
ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)),
TraverseChildren: true,
DisableFlagsInUseLine: true,
}
cmd.Flags().String("type", "", "Type of metrics you want to show")
cmd.MarkFlagRequired("type")
cmd.RegisterFlagCompletionFunc("type", cmpl.SuggestCandidates("cpu", "disk", "network"))
cmd.Flags().String("start", "", "ISO 8601 timestamp")
cmd.Flags().String("end", "", "ISO 8601 timestamp")
output.AddFlag(cmd, output.OptionJSON())
return cmd
},
Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error {
outputFlags := output.FlagsForCommand(cmd)
idOrName := args[0]
server, _, err := client.Server().Get(ctx, idOrName)
if err != nil {
return err
}
if server == nil {
return fmt.Errorf("server not found: %s", idOrName)
}
metricType, _ := cmd.Flags().GetString("type")
start, _ := cmd.Flags().GetString("start")
startTime := time.Now().Add(-30 * time.Minute)
if start != "" {
startTime, err = time.Parse(time.RFC3339, start)
if err != nil {
return fmt.Errorf("start date has an invalid format. It should be ISO 8601, like: %s", time.Now().Format(time.RFC3339))
}
}
end, _ := cmd.Flags().GetString("end")
endTime := time.Now()
if end != "" {
endTime, err = time.Parse(time.RFC3339, end)
if err != nil {
return fmt.Errorf("end date has an invalid format. It should be ISO 8601, like: %s", time.Now().Format(time.RFC3339))
}
}
m, resp, err := client.Server().GetMetrics(ctx, server, hcloud.ServerGetMetricsOpts{
Types: []hcloud.ServerMetricType{hcloud.ServerMetricType(metricType)},
Start: startTime,
End: endTime,
})
if err != nil {
return err
}
switch {
case outputFlags.IsSet("json"):
var data map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return err
}
return util.DescribeJSON(data)
default:
var keys []string
for k := range m.TimeSeries {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
if len(m.TimeSeries[k]) == 0 {
fmt.Printf("Currently there are now metrics available. Please try it again later.")
return nil
}
fmt.Printf("Server: %s \t Metric: %s \t Start: %s \t End: %s\n", server.Name, k, m.Start.String(), m.End.String())
var data []float64
for _, m := range m.TimeSeries[k] {
d, _ := strconv.ParseFloat(m.Value, 64)
data = append(data, d)
}
graph := asciigraph.Plot(data, asciigraph.Height(20), asciigraph.Width(100))
fmt.Println(graph)
fmt.Printf("\n\n")
}
}
return nil
},
}
|