github.com/nsqio/nsq@v1.3.0/internal/quantile/aggregate.go (about)

     1  package quantile
     2  
     3  import (
     4  	"encoding/json"
     5  	"math"
     6  	"sort"
     7  )
     8  
     9  type E2eProcessingLatencyAggregate struct {
    10  	Count       int                  `json:"count"`
    11  	Percentiles []map[string]float64 `json:"percentiles"`
    12  	Topic       string               `json:"topic"`
    13  	Channel     string               `json:"channel"`
    14  	Addr        string               `json:"host"`
    15  }
    16  
    17  func (e *E2eProcessingLatencyAggregate) UnmarshalJSON(b []byte) error {
    18  	var resp struct {
    19  		Count       int                  `json:"count"`
    20  		Percentiles []map[string]float64 `json:"percentiles"`
    21  		Topic       string               `json:"topic"`
    22  		Channel     string               `json:"channel"`
    23  		Addr        string               `json:"host"`
    24  	}
    25  	err := json.Unmarshal(b, &resp)
    26  	if err != nil {
    27  		return err
    28  	}
    29  
    30  	for _, p := range resp.Percentiles {
    31  		p["min"] = p["value"]
    32  		p["max"] = p["value"]
    33  		p["average"] = p["value"]
    34  		p["count"] = float64(resp.Count)
    35  	}
    36  
    37  	e.Count = resp.Count
    38  	e.Percentiles = resp.Percentiles
    39  	e.Topic = resp.Topic
    40  	e.Channel = resp.Channel
    41  	e.Addr = resp.Addr
    42  
    43  	return nil
    44  }
    45  
    46  func (e *E2eProcessingLatencyAggregate) Len() int { return len(e.Percentiles) }
    47  func (e *E2eProcessingLatencyAggregate) Swap(i, j int) {
    48  	e.Percentiles[i], e.Percentiles[j] = e.Percentiles[j], e.Percentiles[i]
    49  }
    50  func (e *E2eProcessingLatencyAggregate) Less(i, j int) bool {
    51  	return e.Percentiles[i]["percentile"] > e.Percentiles[j]["percentile"]
    52  }
    53  
    54  // Add merges e2 into e by averaging the percentiles
    55  func (e *E2eProcessingLatencyAggregate) Add(e2 *E2eProcessingLatencyAggregate) {
    56  	e.Addr = "*"
    57  	p := e.Percentiles
    58  	e.Count += e2.Count
    59  	for _, value := range e2.Percentiles {
    60  		i := -1
    61  		for j, v := range p {
    62  			if value["quantile"] == v["quantile"] {
    63  				i = j
    64  				break
    65  			}
    66  		}
    67  		if i == -1 {
    68  			i = len(p)
    69  			e.Percentiles = append(p, make(map[string]float64))
    70  			p = e.Percentiles
    71  			p[i]["quantile"] = value["quantile"]
    72  		}
    73  		p[i]["max"] = math.Max(value["max"], p[i]["max"])
    74  		p[i]["min"] = math.Min(value["max"], p[i]["max"])
    75  		p[i]["count"] += value["count"]
    76  		if p[i]["count"] == 0 {
    77  			p[i]["average"] = 0
    78  			continue
    79  		}
    80  		delta := value["average"] - p[i]["average"]
    81  		R := delta * value["count"] / p[i]["count"]
    82  		p[i]["average"] = p[i]["average"] + R
    83  	}
    84  	sort.Sort(e)
    85  }