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  }