github.com/fastly/cli@v1.7.2-0.20240304164155-9d0f1d77c3bf/pkg/commands/stats/template.go (about) 1 package stats 2 3 import ( 4 "fmt" 5 "io" 6 "text/template" 7 "time" 8 9 "github.com/fastly/go-fastly/v9/fastly" 10 "github.com/mitchellh/mapstructure" 11 ) 12 13 var blockTemplate = template.Must(template.New("stats_block").Parse( 14 `Service ID: {{ .ServiceID }} 15 Start Time: {{ .StartTime }} 16 -------------------------------------------------- 17 Hit Rate: {{ .HitRate }} 18 Avg Hit Time: {{ .AvgHitTime }} 19 Avg Miss Time: {{ .AvgMissTime }} 20 21 Request BW: {{ .RequestBytes }} 22 Headers: {{ .RequestHeaderBytes }} 23 Body: {{ .RequestBodyBytes }} 24 25 Response BW: {{ .ResponseBytes }} 26 Headers: {{ .ResponseHeaderBytes }} 27 Body: {{ .ResponseBodyBytes }} 28 29 Requests: {{ .RequestCount }} 30 Hit: {{ .Hits }} 31 Miss: {{ .Miss }} 32 Pass: {{ .Pass }} 33 Synth: {{ .Synth }} 34 Error: {{ .Errors }} 35 Uncacheable: {{ .Uncacheable }} 36 37 `)) 38 39 func fmtBlock(out io.Writer, service string, block statsResponseData) error { 40 var agg fastly.Stats 41 if err := mapstructure.Decode(block, &agg); err != nil { 42 return err 43 } 44 45 hitRate := 0.0 46 aggHits := fastly.ToValue(agg.Hits) 47 aggMiss := fastly.ToValue(agg.Miss) 48 aggErrs := fastly.ToValue(agg.Errors) 49 if aggHits > 0 { 50 hitRate = float64(aggHits-aggMiss-aggErrs) / float64(aggHits) 51 } 52 53 // TODO: parse the JSON more strictly so this doesn't need to be dynamic. 54 st, ok := block["start_time"].(float64) 55 if !ok { 56 return fmt.Errorf("failed to type assert '%v' to a float64", block["start_time"]) 57 } 58 startTime := time.Unix(int64(st), 0).UTC() 59 60 values := map[string]string{ 61 "ServiceID": fmt.Sprintf("%30s", service), 62 "StartTime": fmt.Sprintf("%30s", startTime), 63 "HitRate": fmt.Sprintf("%29.2f%%", hitRate*100), 64 "AvgHitTime": fmt.Sprintf("%28.2f\u00b5s", fastly.ToValue(agg.HitsTime)*1000), 65 "AvgMissTime": fmt.Sprintf("%28.2f\u00b5s", fastly.ToValue(agg.MissTime)*1000), 66 67 "RequestBytes": fmt.Sprintf("%30d", fastly.ToValue(agg.RequestHeaderBytes)+fastly.ToValue(agg.RequestBodyBytes)), 68 "RequestHeaderBytes": fmt.Sprintf("%30d", fastly.ToValue(agg.RequestHeaderBytes)), 69 "RequestBodyBytes": fmt.Sprintf("%30d", fastly.ToValue(agg.RequestBodyBytes)), 70 "ResponseBytes": fmt.Sprintf("%30d", fastly.ToValue(agg.ResponseHeaderBytes)+fastly.ToValue(agg.ResponseBodyBytes)), 71 "ResponseHeaderBytes": fmt.Sprintf("%30d", fastly.ToValue(agg.ResponseHeaderBytes)), 72 "ResponseBodyBytes": fmt.Sprintf("%30d", fastly.ToValue(agg.ResponseBodyBytes)), 73 74 "RequestCount": fmt.Sprintf("%30d", fastly.ToValue(agg.Requests)), 75 "Hits": fmt.Sprintf("%30d", aggHits), 76 "Miss": fmt.Sprintf("%30d", aggMiss), 77 "Pass": fmt.Sprintf("%30d", fastly.ToValue(agg.Pass)), 78 "Synth": fmt.Sprintf("%30d", fastly.ToValue(agg.Synth)), 79 "Errors": fmt.Sprintf("%30d", aggErrs), 80 "Uncacheable": fmt.Sprintf("%30d", fastly.ToValue(agg.Uncachable)), 81 } 82 83 return blockTemplate.Execute(out, values) 84 }