Skip to content

Commit 967e4c8

Browse files
authored
NETOBSERV-1113 implements RTT option in Console Plugin (#365)
* RTT column & filter * metrics query * overview & topology rtt * Itoa feedback * factor feedback * add missing rtt to allowed metricTypes * lowercase ms
1 parent 1ca3b6a commit 967e4c8

39 files changed

+471
-132
lines changed

config/sample-frontend-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ sampling: 50
3131
features:
3232
- pktDrop
3333
- dnsTracking
34+
- flowRTT

mocks/loki/flows.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@
234234
"values": [
235235
[
236236
"1689619351078000128",
237-
"{\"Etype\":2048,\"SrcK8S_HostName\":\"ci-ln-hnd9rjk-72292-hnd5v-master-0\",\"Duplicate\":false,\"Interface\":\"ens4\",\"DstAddr\":\"10.0.0.3\",\"DstK8S_HostIP\":\"10.0.0.3\",\"SrcAddr\":\"10.0.0.5\",\"SrcK8S_Type\":\"Node\",\"SrcK8S_OwnerType\":\"Node\",\"Proto\":6,\"DstPort\":2380,\"Packets\":1,\"AgentIP\":\"10.0.0.5\",\"Bytes\":66,\"SrcPort\":49834,\"DstK8S_Type\":\"Node\",\"SrcMac\":\"42:01:0A:00:00:05\",\"TimeFlowEndMs\":1689619351078,\"TimeFlowStartMs\":1689619351078,\"SrcK8S_HostIP\":\"10.0.0.5\",\"DstK8S_OwnerType\":\"Node\",\"Flags\":16,\"DstMac\":\"42:01:0A:00:00:01\",\"DstK8S_HostName\":\"ci-ln-hnd9rjk-72292-hnd5v-master-2\",\"TimeReceived\":1689619351,\"DstK8S_Name\":\"ci-ln-hnd9rjk-72292-hnd5v-master-2\",\"SrcK8S_Name\":\"ci-ln-hnd9rjk-72292-hnd5v-master-0\",\"IfDirection\":1}"
237+
"{\"Etype\":2048,\"SrcK8S_HostName\":\"ci-ln-hnd9rjk-72292-hnd5v-master-0\",\"Duplicate\":false,\"Interface\":\"ens4\",\"DstAddr\":\"10.0.0.3\",\"DstK8S_HostIP\":\"10.0.0.3\",\"SrcAddr\":\"10.0.0.5\",\"SrcK8S_Type\":\"Node\",\"SrcK8S_OwnerType\":\"Node\",\"Proto\":6,\"DstPort\":2380,\"Packets\":1,\"AgentIP\":\"10.0.0.5\",\"Bytes\":66,\"SrcPort\":49834,\"DstK8S_Type\":\"Node\",\"SrcMac\":\"42:01:0A:00:00:05\",\"TimeFlowEndMs\":1689619351078,\"TimeFlowRttNs\":12345678,\"TimeFlowStartMs\":1689619351078,\"SrcK8S_HostIP\":\"10.0.0.5\",\"DstK8S_OwnerType\":\"Node\",\"Flags\":16,\"DstMac\":\"42:01:0A:00:00:01\",\"DstK8S_HostName\":\"ci-ln-hnd9rjk-72292-hnd5v-master-2\",\"TimeReceived\":1689619351,\"DstK8S_Name\":\"ci-ln-hnd9rjk-72292-hnd5v-master-2\",\"SrcK8S_Name\":\"ci-ln-hnd9rjk-72292-hnd5v-master-0\",\"IfDirection\":1}"
238238
],
239239
[
240240
"1689619351032000000",
@@ -308,7 +308,7 @@
308308
"values": [
309309
[
310310
"1689619351079000064",
311-
"{\"SrcMac\":\"42:01:0A:00:00:01\",\"DstPort\":6443,\"SrcPort\":54082,\"Etype\":2048,\"SrcK8S_Type\":\"Node\",\"AgentIP\":\"10.0.0.5\",\"Bytes\":66,\"Packets\":1,\"SrcK8S_HostIP\":\"10.0.0.4\",\"SrcK8S_HostName\":\"ci-ln-hnd9rjk-72292-hnd5v-master-1\",\"SrcK8S_OwnerType\":\"Node\",\"Proto\":6,\"Flags\":16,\"SrcAddr\":\"10.0.0.4\",\"SrcK8S_Name\":\"ci-ln-hnd9rjk-72292-hnd5v-master-1\",\"DstMac\":\"42:01:0A:00:00:05\",\"TimeFlowStartMs\":1689619351079,\"Duplicate\":false,\"IfDirection\":0,\"TimeFlowEndMs\":1689619351079,\"TimeReceived\":1689619351,\"DstAddr\":\"10.0.0.2\",\"Interface\":\"br-ex\"}"
311+
"{\"SrcMac\":\"42:01:0A:00:00:01\",\"DstPort\":6443,\"SrcPort\":54082,\"Etype\":2048,\"SrcK8S_Type\":\"Node\",\"AgentIP\":\"10.0.0.5\",\"Bytes\":66,\"Packets\":1,\"SrcK8S_HostIP\":\"10.0.0.4\",\"SrcK8S_HostName\":\"ci-ln-hnd9rjk-72292-hnd5v-master-1\",\"SrcK8S_OwnerType\":\"Node\",\"Proto\":6,\"Flags\":16,\"SrcAddr\":\"10.0.0.4\",\"SrcK8S_Name\":\"ci-ln-hnd9rjk-72292-hnd5v-master-1\",\"DstMac\":\"42:01:0A:00:00:05\",\"TimeFlowStartMs\":1689619351079,\"Duplicate\":false,\"IfDirection\":0,\"TimeFlowEndMs\":1689619351079,\"TimeFlowRttNs\":1234,\"TimeReceived\":1689619351,\"DstAddr\":\"10.0.0.2\",\"Interface\":\"br-ex\"}"
312312
],
313313
[
314314
"1689619350793999872",

pkg/handler/validation.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ func getMetricType(params url.Values) (constants.MetricType, error) {
101101
metricType == constants.MetricTypeDroppedPackets ||
102102
metricType == constants.MetricTypePackets ||
103103
metricType == constants.MetricTypeDNSLatencies ||
104-
metricType == constants.MetricTypeCountDNS {
104+
metricType == constants.MetricTypeCountDNS ||
105+
metricType == constants.MetricTypeFlowRTT {
105106
return metricType, nil
106107
}
107108
return "", fmt.Errorf("invalid metric type: %s", mt)

pkg/loki/filter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func moreThanRegex(sb *strings.Builder, value string) {
208208
intVal, _ := strconv.Atoi(value)
209209
for i := 1; i < len(value); i++ {
210210
nextMin := int((intVal / int(math.Pow10(i))) + 1)
211-
nextMinStr := fmt.Sprintf("%d", nextMin)
211+
nextMinStr := strconv.Itoa(nextMin)
212212

213213
sb.WriteRune('|')
214214
if nextMin >= 10 {

pkg/loki/flow_query.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,14 @@ func (q *FlowQueryBuilder) appendDNSRCodeFilter(sb *strings.Builder) {
279279
sb.WriteString("`")
280280
}
281281

282+
func (q *FlowQueryBuilder) appendRTTFilter(sb *strings.Builder) {
283+
// ensure at TimeFlowRttNs field is specified
284+
// |~`"TimeFlowRttNs"`
285+
sb.WriteString("|~`")
286+
sb.WriteString(`"TimeFlowRttNs"`)
287+
sb.WriteString("`")
288+
}
289+
282290
func (q *FlowQueryBuilder) appendJSON(sb *strings.Builder, forceAppend bool) {
283291
if forceAppend || len(q.jsonFilters) > 0 {
284292
sb.WriteString("|json")

pkg/loki/topology_query.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ type Topology struct {
2222
skipEmptyDropCause bool
2323
skipNonDNS bool
2424
skipEmptyDNSRCode bool
25+
skipEmptyRTT bool
26+
factor string
2527
}
2628

2729
type TopologyQueryBuilder struct {
@@ -39,6 +41,7 @@ func NewTopologyQuery(cfg *Config, start, end, limit, rateInterval, step string,
3941

4042
fields := getFields(aggregate, groups)
4143
var f, t string
44+
factor := ""
4245
switch metricType {
4346
case constants.MetricTypeCount, constants.MetricTypeCountDNS:
4447
f = "count_over_time"
@@ -57,6 +60,10 @@ func NewTopologyQuery(cfg *Config, start, end, limit, rateInterval, step string,
5760
case constants.MetricTypeBytes:
5861
f = "rate"
5962
t = "Bytes"
63+
case constants.MetricTypeFlowRTT:
64+
f = "avg_over_time"
65+
t = "TimeFlowRttNs"
66+
factor = "/1000000" // nanoseconds to miliseconds
6067
}
6168

6269
var d bool
@@ -80,8 +87,10 @@ func NewTopologyQuery(cfg *Config, start, end, limit, rateInterval, step string,
8087
fields: fields,
8188
skipEmptyDropState: aggregate == "droppedState",
8289
skipEmptyDropCause: aggregate == "droppedCause",
83-
skipNonDNS: metricType == "dnsLatencies" || metricType == "countDns",
90+
skipNonDNS: metricType == constants.MetricTypeDNSLatencies || metricType == constants.MetricTypeCountDNS,
8491
skipEmptyDNSRCode: aggregate == "dnsRCode",
92+
skipEmptyRTT: metricType == constants.MetricTypeFlowRTT,
93+
factor: factor,
8594
},
8695
}, nil
8796
}
@@ -139,7 +148,7 @@ func (q *TopologyQueryBuilder) Build() string {
139148
// <function>(
140149
// {<label filters>}|<line filters>|json|<json filters>
141150
// |unwrap Bytes|__error__=""[<interval>]
142-
// )
151+
// ) <factor>
143152
// )
144153
// )
145154
// &<query params>&step=<step>
@@ -172,6 +181,10 @@ func (q *TopologyQueryBuilder) Build() string {
172181
q.appendDNSFilter(sb)
173182
}
174183

184+
if q.topology.skipEmptyRTT {
185+
q.appendRTTFilter(sb)
186+
}
187+
175188
q.appendJSON(sb, true)
176189
if len(q.topology.dataField) > 0 {
177190
sb.WriteString("|unwrap ")
@@ -184,7 +197,11 @@ func (q *TopologyQueryBuilder) Build() string {
184197
} else {
185198
sb.WriteString(q.topology.rateInterval)
186199
}
187-
sb.WriteString("])))")
200+
sb.WriteString("])")
201+
if len(q.topology.factor) > 0 {
202+
sb.WriteString(q.topology.factor)
203+
}
204+
sb.WriteString("))")
188205
q.appendQueryParams(sb)
189206
sb.WriteString("&step=")
190207
sb.WriteString(q.topology.step)

pkg/model/fields/fields.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ const (
3939
DNSID = "DnsId"
4040
DNSLatency = "DnsLatencyMs"
4141
Duplicate = "Duplicate"
42+
TimeFlowRTT = "TimeFlowRttNs"
4243
)
4344

4445
func IsNumeric(v string) bool {
4546
switch v {
4647
case
4748
DNSID,
4849
DNSLatency,
50+
TimeFlowRTT,
4951
Port,
5052
SrcPort,
5153
DstPort,

pkg/utils/constants/constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const (
1212
MetricTypePackets MetricType = "packets"
1313
MetricTypeCount MetricType = "count"
1414
MetricTypeCountDNS MetricType = "countDns"
15+
MetricTypeFlowRTT MetricType = "flowRtt"
1516
MetricTypeDNSLatencies MetricType = "dnsLatencies"
1617
MetricTypeDroppedBytes MetricType = "droppedBytes"
1718
MetricTypeDroppedPackets MetricType = "droppedPackets"

web/locales/en/plugin__netobserv-plugin.json

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
"Grid": "Grid",
1919
"ColaGroups": "ColaGroups",
2020
"Invalid": "Invalid",
21+
"rate": "rate",
2122
"Total": "Total",
22-
"Latest rate": "Latest rate",
23-
"Max rate": "Max rate",
24-
"Average rate": "Average rate",
23+
"Latest": "Latest",
24+
"Max": "Max",
25+
"Average": "Average",
26+
"Only average is available for RTT": "Only average is available for RTT",
2527
"Packets": "Packets",
2628
"Bytes": "Bytes",
29+
"RTT": "RTT",
2730
"Type of measurement to show in graphs.": "Type of measurement to show in graphs.",
2831
"Metric type": "Metric type",
2932
"The level of details represented.": "The level of details represented.",
@@ -208,6 +211,7 @@
208211
"Unable to get overview": "Unable to get overview",
209212
"Clear or reset filters and try again.": "Clear or reset filters and try again.",
210213
"Average latency": "Average latency",
214+
"Average RTT": "Average RTT",
211215
"Total flow count": "Total flow count",
212216
"Show total traffic for the selected filters": "Show total traffic for the selected filters",
213217
"Show total": "Show total",
@@ -248,12 +252,15 @@
248252
"IP": "IP",
249253
"No information available for this content. Change scope to get more details.": "No information available for this content. Change scope to get more details.",
250254
"Stats": "Stats",
255+
"Flow RTT": "Flow RTT",
251256
"Top 5 rates": "Top 5 rates",
252257
"A -> B": "A -> B",
253258
"In": "In",
254259
"B -> A": "B -> A",
255260
"Out": "Out",
256261
"Both": "Both",
262+
"Average rate": "Average rate",
263+
"Latest rate": "Latest rate",
257264
"Edge": "Edge",
258265
"Unable to get topology": "Unable to get topology",
259266
"Query is slow": "Query is slow",
@@ -298,6 +305,9 @@
298305
"Filtered byte rate": "Filtered byte rate",
299306
"Filtered sum of top-k packets / filtered total packets": "Filtered sum of top-k packets / filtered total packets",
300307
"packets": "packets",
308+
"Filtered avg RTT / filtered total avg RTT": "Filtered avg RTT / filtered total avg RTT",
309+
"Filtered avg RTT": "Filtered avg RTT",
310+
"ms": "ms",
301311
"Configuration": "Configuration",
302312
"Sampling": "Sampling",
303313
"Version": "Version",
@@ -365,6 +375,7 @@
365375
"The total aggregated number of bytes.": "The total aggregated number of bytes.",
366376
"The total aggregated number of packets.": "The total aggregated number of packets.",
367377
"Time elapsed between Start Time and End Time.": "Time elapsed between Start Time and End Time.",
378+
"Flow Round Trip Time": "Flow Round Trip Time",
368379
"Collection Time": "Collection Time",
369380
"Reception time of the record by the collector.": "Reception time of the record by the collector.",
370381
"Collection Latency": "Collection Latency",
@@ -459,8 +470,8 @@
459470
"Specify a single DNS RCODE name like:": "Specify a single DNS RCODE name like:",
460471
"A IANA RCODE number like 0, 3, 9": "A IANA RCODE number like 0, 3, 9",
461472
"A IANA RCODE name like NoError, NXDomain, NotAuth": "A IANA RCODE name like NoError, NXDomain, NotAuth",
473+
"Specify a Flow Round Trip Time in nanoseconds.": "Specify a Flow Round Trip Time in nanoseconds.",
462474
"P": "P",
463-
"Ms": "Ms",
464475
"Pps": "Pps",
465476
"Network overview": "Network overview",
466477
"Top {{limit}} {{type}} rates stacked": "Top {{limit}} {{type}} rates stacked",
@@ -488,6 +499,8 @@
488499
"The top dropped rates (dropped by the kernel) as bar compared to total as line over the selected interval": "The top dropped rates (dropped by the kernel) as bar compared to total as line over the selected interval",
489500
"Top {{limit}} average DNS latencies": "Top {{limit}} average DNS latencies",
490501
"The average DNS latencies over the selected interval": "The average DNS latencies over the selected interval",
502+
"Top {{limit}} average flow RTT": "Top {{limit}} average flow RTT",
503+
"The average flow Round Trip Time over the selected interval": "The average flow Round Trip Time over the selected interval",
491504
"Top {{limit}} DNS response code": "Top {{limit}} DNS response code",
492505
"The top DNS response code extracted from DNS response headers over the selected interval": "The top DNS response code extracted from DNS response headers over the selected interval",
493506
"Top {{limit}} DNS response code stacked with total": "Top {{limit}} DNS response code stacked with total",

web/src/api/ipfix.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ export interface Fields {
122122
TimeFlowEndMs: number;
123123
/** Timestamp when this flow was received and processed by the flow collector, in seconds */
124124
TimeReceived: number;
125+
/** Flow Round Trip Time (RTT) in nanoseconds */
126+
TimeFlowRttNs?: number;
125127
/** In conversation tracking, the conversation identifier */
126128
_HashId?: string;
127129
/** In conversation tracking, a flag identifying the first flow */

0 commit comments

Comments
 (0)