mirror of
https://github.com/akvorado/akvorado.git
synced 2025-12-11 22:14:02 +01:00
outlet/core: accept flows where interface names are missing
This matches the pre-2.0.0 behavior. This may not be a bug, but the idea is that one interface is enough to be valid. Some implementations seem to use bogus indexes. See https://github.com/akvorado/akvorado/discussions/1998#discussioncomment-14992940
This commit is contained in:
@@ -17,6 +17,7 @@ identified with a specific icon:
|
||||
false by default)
|
||||
- 🩹 *outlet*: provide additional gracetime for a worker to send to ClickHouse
|
||||
- 🩹 *outlet*: enhance scaling up and down workers to avoid hysteresis
|
||||
- 🩹 *outlet*: accept flows where interface names or descriptions are missing
|
||||
- 🩹 *docker*: update Traefik to 3.6.1 (for compatibility with Docker Engine 29)
|
||||
- 🌱 *common*: enable block and mutex profiling
|
||||
- 🌱 *config*: rename `verify` to `skip-verify` in TLS configurations for
|
||||
|
||||
@@ -38,10 +38,7 @@ func (w *worker) enrichFlow(exporterIP netip.Addr, exporterStr string) bool {
|
||||
|
||||
if flow.InIf != 0 {
|
||||
answer := c.d.Metadata.Lookup(t, exporterIP, uint(flow.InIf))
|
||||
if !answer.Found {
|
||||
c.metrics.flowsErrors.WithLabelValues(exporterStr, "metadata cache miss").Inc()
|
||||
skip = true
|
||||
} else {
|
||||
if answer.Found {
|
||||
flowExporterName = answer.Exporter.Name
|
||||
expClassification.Region = answer.Exporter.Region
|
||||
expClassification.Role = answer.Exporter.Role
|
||||
@@ -61,14 +58,7 @@ func (w *worker) enrichFlow(exporterIP netip.Addr, exporterStr string) bool {
|
||||
|
||||
if flow.OutIf != 0 {
|
||||
answer := c.d.Metadata.Lookup(t, exporterIP, uint(flow.OutIf))
|
||||
if !answer.Found {
|
||||
// Only register a cache miss if we don't have one.
|
||||
// TODO: maybe we could do one SNMP query for both interfaces.
|
||||
if !skip {
|
||||
c.metrics.flowsErrors.WithLabelValues(exporterStr, "metadata cache miss").Inc()
|
||||
skip = true
|
||||
}
|
||||
} else {
|
||||
if answer.Found {
|
||||
flowExporterName = answer.Exporter.Name
|
||||
expClassification.Region = answer.Exporter.Region
|
||||
expClassification.Role = answer.Exporter.Role
|
||||
@@ -90,6 +80,9 @@ func (w *worker) enrichFlow(exporterIP netip.Addr, exporterStr string) bool {
|
||||
if flow.OutIf == 0 && flow.InIf == 0 {
|
||||
c.metrics.flowsErrors.WithLabelValues(exporterStr, "input and output interfaces missing").Inc()
|
||||
skip = true
|
||||
} else if flowExporterName == "" {
|
||||
c.metrics.flowsErrors.WithLabelValues(exporterStr, "metadata cache miss").Inc()
|
||||
skip = true
|
||||
}
|
||||
|
||||
if samplingRate, ok := c.config.OverrideSamplingRate.Lookup(exporterIP); ok && samplingRate > 0 {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net/netip"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -35,6 +36,7 @@ func TestEnrich(t *testing.T) {
|
||||
Configuration gin.H
|
||||
InputFlow func() *schema.FlowMessage
|
||||
OutputFlow *schema.FlowMessage
|
||||
ExpectedMetrics map[string]string
|
||||
}{
|
||||
{
|
||||
Name: "no rule",
|
||||
@@ -583,6 +585,38 @@ ClassifyProviderRegex(Interface.Description, "^Transit: ([^ ]+)", "$1")`,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "flow with missing interfaces",
|
||||
Configuration: gin.H{},
|
||||
InputFlow: func() *schema.FlowMessage {
|
||||
return &schema.FlowMessage{
|
||||
SamplingRate: 1000,
|
||||
ExporterAddress: netip.MustParseAddr("::ffff:192.0.2.142"),
|
||||
InIf: 0,
|
||||
OutIf: 0,
|
||||
}
|
||||
},
|
||||
OutputFlow: nil,
|
||||
ExpectedMetrics: map[string]string{
|
||||
`flows_errors_total{error="input and output interfaces missing",exporter="192.0.2.142"}`: "1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "flow with metadata cache miss",
|
||||
Configuration: gin.H{},
|
||||
InputFlow: func() *schema.FlowMessage {
|
||||
return &schema.FlowMessage{
|
||||
SamplingRate: 1000,
|
||||
ExporterAddress: netip.MustParseAddr("::ffff:192.0.2.142"),
|
||||
InIf: 999,
|
||||
OutIf: 0,
|
||||
}
|
||||
},
|
||||
OutputFlow: nil,
|
||||
ExpectedMetrics: map[string]string{
|
||||
`flows_errors_total{error="metadata cache miss",exporter="192.0.2.142"}`: "1",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
@@ -684,6 +718,7 @@ ClassifyProviderRegex(Interface.Description, "^Transit: ([^ ]+)", "$1")`,
|
||||
if tc.OutputFlow != nil {
|
||||
expectedMetrics[`forwarded_flows_total{exporter="192.0.2.142"}`] = "1"
|
||||
}
|
||||
maps.Copy(expectedMetrics, tc.ExpectedMetrics)
|
||||
if diff := helpers.Diff(gotMetrics, expectedMetrics); diff != "" {
|
||||
t.Fatalf("Metrics (-got, +want):\n%s", diff)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user