Skip to content

Commit

Permalink
all: imp code
Browse files Browse the repository at this point in the history
  • Loading branch information
schzhn committed Jul 28, 2023
1 parent 5251a89 commit 2cb2d0d
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 29 deletions.
7 changes: 5 additions & 2 deletions internal/stats/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import (
// The key is either a client's address or a requested address.
type topAddrs = map[string]uint64

// topAddrsFloat is like [topAddrs] but the value is float64 number.
type topAddrsFloat = map[string]float64

// StatsResp is a response to the GET /control/stats.
type StatsResp struct {
TimeUnits string `json:"time_units"`
Expand All @@ -27,8 +30,8 @@ type StatsResp struct {
TopClients []topAddrs `json:"top_clients"`
TopBlocked []topAddrs `json:"top_blocked_domains"`

TopUpstreamsResponses []topAddrs `json:"top_upstreams_responses"`
TopUpstreamsAvgTime []topAddrs `json:"top_upstreams_avg_time"`
TopUpstreamsResponses []topAddrs `json:"top_upstreams_responses"`
TopUpstreamsAvgTime []topAddrsFloat `json:"top_upstreams_avg_time"`

DNSQueries []uint64 `json:"dns_queries"`

Expand Down
4 changes: 2 additions & 2 deletions internal/stats/stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func TestStats(t *testing.T) {
TopClients: []map[string]uint64{0: {cliIPStr: 2}},
TopBlocked: []map[string]uint64{0: {reqDomain: 1}},
TopUpstreamsResponses: []map[string]uint64{0: {respUpstream: 2}},
TopUpstreamsAvgTime: []map[string]uint64{0: {respUpstream: 123}},
TopUpstreamsAvgTime: []map[string]float64{0: {respUpstream: 0.123456}},
DNSQueries: []uint64{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
Expand Down Expand Up @@ -149,7 +149,7 @@ func TestStats(t *testing.T) {
TopClients: []map[string]uint64{},
TopBlocked: []map[string]uint64{},
TopUpstreamsResponses: []map[string]uint64{},
TopUpstreamsAvgTime: []map[string]uint64{},
TopUpstreamsAvgTime: []map[string]float64{},
DNSQueries: _24zeroes[:],
BlockedFiltering: _24zeroes[:],
ReplacedSafebrowsing: _24zeroes[:],
Expand Down
44 changes: 31 additions & 13 deletions internal/stats/unit.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/stringutil"
"go.etcd.io/bbolt"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
)

Expand Down Expand Up @@ -427,7 +428,7 @@ func (s *StatsCtx) getData(limit uint32) (StatsResp, bool) {
TopClients: []topAddrs{},
TopQueried: []topAddrs{},
TopUpstreamsResponses: []topAddrs{},
TopUpstreamsAvgTime: []topAddrs{},
TopUpstreamsAvgTime: []topAddrsFloat{},

BlockedFiltering: []uint64{},
DNSQueries: []uint64{},
Expand Down Expand Up @@ -516,39 +517,56 @@ func topClientPairs(s *StatsCtx) (pg pairsGetter) {
}
}

// topUpstreamsPairs returns sorted lists of number of total responses and sum
// of processing times for each upstream.
func topUpstreamsPairs(units []*unitDB) (topUpstreamsResponses, topUpstreamsAvgTime []topAddrs) {
// topUpstreamsPairs returns sorted lists of number of total responses and the
// average of processing time for each upstream.
func topUpstreamsPairs(
units []*unitDB,
) (topUpstreamsResponses []topAddrs, topUpstreamsAvgTime []topAddrsFloat) {
upstreamsResponses := topAddrs{}
upstreamsTimeSum := topAddrs{}
upstreamsTimeSum := topAddrsFloat{}

for _, u := range units {
for _, cp := range u.UpstreamsResponses {
upstreamsResponses[cp.Name] += cp.Count
}

for _, cp := range u.UpstreamsTimeSum {
// Convert from microseconds to milliseconds and calculate the sum.
upstreamsTimeSum[cp.Name] += cp.Count / uint64(time.Microsecond)
// Convert from microseconds to seconds and calculate the sum.
upstreamsTimeSum[cp.Name] += float64(cp.Count) / float64(time.Millisecond)
}
}

upstreamsAvgTime := make(topAddrs)
upstreamsAvgTime := topAddrsFloat{}

for u, n := range upstreamsResponses {
total := upstreamsTimeSum[u]

if total != 0 {
// Calculate average and convert from microseconds to milliseconds.
upstreamsAvgTime[u] = total / n
upstreamsAvgTime[u] = total / float64(n)
}
}

upstreamsPairs := convertMapToSlice(upstreamsResponses, maxUpstreams)
topUpstreamsResponses = convertTopSlice(upstreamsPairs)

upstreamsPairs = convertMapToSlice(upstreamsAvgTime, maxUpstreams)
topUpstreamsAvgTime = convertTopSlice(upstreamsPairs)
return topUpstreamsResponses, prepareTopUpstreamsAvgTime(upstreamsAvgTime)
}

// prepareTopUpstreamsAvgTime returns sorted list of average processing times
// of the DNS requests from each upstream.
func prepareTopUpstreamsAvgTime(
upstreamsAvgTime topAddrsFloat,
) (topUpstreamsAvgTime []topAddrsFloat) {
keys := maps.Keys(upstreamsAvgTime)

slices.SortFunc(keys, func(a, b string) (sortsBefore bool) {
return upstreamsAvgTime[a] > upstreamsAvgTime[b]
})

topUpstreamsAvgTime = make([]topAddrsFloat, 0, len(upstreamsAvgTime))
for _, k := range keys {
topUpstreamsAvgTime = append(topUpstreamsAvgTime, topAddrsFloat{k: upstreamsAvgTime[k]})
}

return topUpstreamsResponses, topUpstreamsAvgTime
return topUpstreamsAvgTime
}
18 changes: 9 additions & 9 deletions internal/stats/unit_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func TestTopUpstreamsPairs(t *testing.T) {
db *unitDB
name string
wantResponses []topAddrs
wantAvgTime []topAddrs
wantAvgTime []topAddrsFloat
}{{
name: "empty",
db: &unitDB{
Expand All @@ -108,7 +108,7 @@ func TestTopUpstreamsPairs(t *testing.T) {
UpstreamsTimeSum: []countPair{},
},
wantResponses: []topAddrs{},
wantAvgTime: []topAddrs{},
wantAvgTime: []topAddrsFloat{},
}, {
name: "basic",
db: &unitDB{
Expand All @@ -128,8 +128,8 @@ func TestTopUpstreamsPairs(t *testing.T) {
wantResponses: []topAddrs{{
"1.2.3.4": 2,
}},
wantAvgTime: []topAddrs{{
"1.2.3.4": 123,
wantAvgTime: []topAddrsFloat{{
"1.2.3.4": 0.123456,
}},
}, {
name: "sorted",
Expand All @@ -147,10 +147,10 @@ func TestTopUpstreamsPairs(t *testing.T) {
{"1.1.1.1", 2},
},
UpstreamsTimeSum: []countPair{
{"3.3.3.3", 800_000},
{"2.2.2.2", 40_000},
{"4.4.4.4", 16_000_000},
{"1.1.1.1", 2_000},
{"3.3.3.3", 800_000_000},
{"2.2.2.2", 40_000_000},
{"4.4.4.4", 16_000_000_000},
{"1.1.1.1", 2_000_000},
},
},
wantResponses: []topAddrs{
Expand All @@ -159,7 +159,7 @@ func TestTopUpstreamsPairs(t *testing.T) {
{"2.2.2.2": 4},
{"1.1.1.1": 2},
},
wantAvgTime: []topAddrs{
wantAvgTime: []topAddrsFloat{
{"4.4.4.4": 1000},
{"3.3.3.3": 100},
{"2.2.2.2": 10},
Expand Down
2 changes: 1 addition & 1 deletion openapi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
shows the total number of responses from each upstream.

* The new field `"top_upstrems_avg_time"` in `GET /control/stats` method shows
the average processing time in milliseconds of requests from each upstream.
the average processing time in seconds of requests from each upstream.

## v0.107.30: API changes

Expand Down
4 changes: 2 additions & 2 deletions openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1750,8 +1750,8 @@
'maxItems': 100
'top_upstreams_avg_time':
'type': 'array'
'description': 'Average processing time in milliseconds of requests
from each upstream.'
'description': 'Average processing time in seconds of requests from
each upstream.'
'items':
'$ref': '#/components/schemas/TopArrayEntry'
'maxItems': 100
Expand Down

0 comments on commit 2cb2d0d

Please sign in to comment.