Skip to content

Commit f418398

Browse files
committed
feat: mark k8s watch api conn with a specific label
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
1 parent 900dd5d commit f418398

4 files changed

Lines changed: 312 additions & 252 deletions

File tree

checks/net.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -742,9 +742,10 @@ const (
742742
httpResponseTime metricName = "http_response_time_seconds"
743743
httpRequestsDelta metricName = "http_requests_delta"
744744

745-
httpStatusCodeTag = "code"
746-
httpPathTag = "path"
747-
httpMethodTag = "method"
745+
httpStatusCodeTag = "code"
746+
httpPathTag = "path"
747+
httpMethodTag = "method"
748+
httpHighLatencyTag = "known_high_latency"
748749

749750
mongoResponseTime metricName = "mongo_response_time_seconds"
750751
mongoRequestsDelta metricName = "mongo_requests_delta"
@@ -795,15 +796,20 @@ func (k aggStatsKey) toMap() map[string]string {
795796
// We need to transform the nanoseconds to seconds here
796797
const nsToS float64 = 0.000000001
797798

798-
func aggregateStats(stats []http.RequestStat) (int, *ddsketch.DDSketch) {
799+
func aggregateStats(stats []http.RequestStat) (int, *ddsketch.DDSketch, bool) {
799800
requestCount := 0
800801
latencies := emptySketch()
802+
highLatency := false
801803

802804
for _, stat := range stats {
803805
if stat.Count == 0 {
804806
continue
805807
}
806808

809+
if stat.IsWatchAPI() {
810+
highLatency = true
811+
}
812+
807813
requestCount += stat.Count
808814

809815
if stat.Count == 1 {
@@ -814,7 +820,7 @@ func aggregateStats(stats []http.RequestStat) (int, *ddsketch.DDSketch) {
814820
latencies.MergeWith(scaled)
815821
}
816822
}
817-
return requestCount, latencies
823+
return requestCount, latencies, highLatency
818824
}
819825

820826
func aggregateHTTPTraceObservations(httpObservations []http.TransactionObservation) map[connKey][]*model.HTTPTraceObservation {
@@ -1016,6 +1022,8 @@ func aggregateHTTPStats(httpStats map[http.Key]*http.RequestStats, sendForPath b
10161022
return connStats
10171023
}
10181024

1025+
// httpStats has the following structure: (coming from datadog tracer)
1026+
// Key: struct{Tuple, Path, Method} -> Value: map[code(100/200/300/...)]struct{Latency, Count, StaticTags}
10191027
for statKey, statsByCode := range httpStats {
10201028
for statusCodeClass := uint16(100); statusCodeClass <= 500; statusCodeClass += 100 {
10211029
stat := statsByCode.Data[statusCodeClass]
@@ -1030,6 +1038,7 @@ func aggregateHTTPStats(httpStats map[http.Key]*http.RequestStats, sendForPath b
10301038

10311039
connStats = appendStatsForStatusGroup(connStats, statusCodeGroup, statKey, stat)
10321040

1041+
// Key: struct{Tuple} -> Value: map[struct{Path(optional), Method, StatusCode}][]struct{Latency, Count, StaticTags}
10331042
regroupedStats[connKey] = connStats
10341043
}
10351044
}
@@ -1039,7 +1048,10 @@ func aggregateHTTPStats(httpStats map[http.Key]*http.RequestStats, sendForPath b
10391048
for connKey, statsByTags := range regroupedStats {
10401049
for tagsKey, stats := range statsByTags {
10411050
data := tagsKey.toMap()
1042-
requestCount, latencies := aggregateStats(stats)
1051+
requestCount, latencies, highLatency := aggregateStats(stats)
1052+
if highLatency {
1053+
data[httpHighLatencyTag] = "true"
1054+
}
10431055
result[connKey] = append(result[connKey],
10441056
makeConnectionMetricWithNumber(
10451057
httpRequestsDelta, data,

checks/net_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,54 @@ func msToNs(ms float64) float64 {
623623
return ms * 1000000
624624
}
625625

626+
func TestHTTPAggregation_HighLatency(t *testing.T) {
627+
// this is not a watch API
628+
conn1 := http.NewKey(
629+
util.AddressFromString("10.0.0.1"), util.AddressFromString("192.168.1.1"), 12345, 80,
630+
[]byte("/api/v1/namespaces/default/pods?limit=500"), true, http.MethodGet, 0)
631+
stats1 := http.NewRequestStats()
632+
stats1.AddRequest(200, msToNs(6.0), 0, nil)
633+
634+
// this is a watch API but on a different dest port, so we have a different conn tuple (source port)
635+
conn2 := http.NewKey(
636+
util.AddressFromString("10.0.0.1"), util.AddressFromString("192.168.1.1"), 12346, 80,
637+
[]byte("/api/v1/namespaces/default/pods?resourceVersion=418&watch=true"), true, http.MethodGet, 0)
638+
stats2 := http.NewRequestStats()
639+
stats2.AddRequest(200, msToNs(60000.0), http.WatchAPI, nil)
640+
641+
metrics := aggregateHTTPStats(map[http.Key]*http.RequestStats{
642+
conn1: stats1,
643+
conn2: stats2,
644+
}, false)
645+
646+
assert.Len(t, metrics, 2)
647+
648+
// conn1 shouldn't have high latency
649+
conn1Metrics := metrics[getConnectionKeyForHTTPStats(conn1)]
650+
// for each metric we have 5 status groups (1xx, 2xx, 3xx, 4xx, 5xx)
651+
// we have 2 metrics:
652+
// - http_requests_delta
653+
// - http_response_time_seconds
654+
assert.Len(t, conn1Metrics, 10)
655+
// all the metrics should have the httpHighLatencyTag
656+
for _, metric := range conn1Metrics {
657+
assert.NotContains(t, metric.Tags, httpHighLatencyTag)
658+
}
659+
660+
// conn2 should have high latency
661+
conn2Metrics := metrics[getConnectionKeyForHTTPStats(conn2)]
662+
assert.Len(t, conn2Metrics, 10)
663+
for _, metric := range conn2Metrics {
664+
// only metrics with 2xx status should have the httpHighLatencyTag
665+
// because are the only one with at least a stat with high latency
666+
if metric.Tags[httpStatusCodeTag] == "2xx" {
667+
assert.Contains(t, metric.Tags, httpHighLatencyTag)
668+
} else {
669+
assert.NotContains(t, metric.Tags, httpHighLatencyTag)
670+
}
671+
}
672+
}
673+
626674
func TestHTTPAggregation_SingleReq(t *testing.T) {
627675

628676
conn1req1 := http.NewKey(

0 commit comments

Comments
 (0)