Skip to content

Commit

Permalink
Add optional interface alias in netstat (#130)
Browse files Browse the repository at this point in the history
* Check creation of CCMessage in NATS receiver

* add optional interface aliases for netstatMetric

* small fix

---------

Co-authored-by: Thomas Roehl <[email protected]>
Co-authored-by: exterr2f <[email protected]>
Co-authored-by: Thomas Gruber <[email protected]>
  • Loading branch information
4 people authored Feb 19, 2025
1 parent 6901b06 commit 0f92f10
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 23 deletions.
56 changes: 39 additions & 17 deletions collectors/netstatMetric.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ import (
"time"

cclog "github.com/ClusterCockpit/cc-metric-collector/pkg/ccLogger"
lp "github.com/ClusterCockpit/cc-energy-manager/pkg/cc-message"
lp "github.com/ClusterCockpit/cc-lib/ccMessage"

Check failure on line 13 in collectors/netstatMetric.go

View workflow job for this annotation

GitHub Actions / build-1-21

no required module provides package github.com/ClusterCockpit/cc-lib/ccMessage; to add it:

Check failure on line 13 in collectors/netstatMetric.go

View workflow job for this annotation

GitHub Actions / build-1-22

no required module provides package github.com/ClusterCockpit/cc-lib/ccMessage; to add it:
)

const NETSTATFILE = "/proc/net/dev"

type NetstatCollectorConfig struct {
IncludeDevices []string `json:"include_devices"`
SendAbsoluteValues bool `json:"send_abs_values"`
SendDerivedValues bool `json:"send_derived_values"`
IncludeDevices []string `json:"include_devices"`
SendAbsoluteValues bool `json:"send_abs_values"`
SendDerivedValues bool `json:"send_derived_values"`
InterfaceAliases map[string][]string `json:"interface_aliases,omitempty"`
}

type NetstatCollectorMetric struct {
Expand All @@ -32,9 +33,26 @@ type NetstatCollectorMetric struct {

type NetstatCollector struct {
metricCollector
config NetstatCollectorConfig
matches map[string][]NetstatCollectorMetric
lastTimestamp time.Time
config NetstatCollectorConfig
aliasToCanonical map[string]string
matches map[string][]NetstatCollectorMetric
lastTimestamp time.Time
}

func (m *NetstatCollector) buildAliasMapping() {
m.aliasToCanonical = make(map[string]string)
for canon, aliases := range m.config.InterfaceAliases {
for _, alias := range aliases {
m.aliasToCanonical[alias] = canon
}
}
}

func getCanonicalName(raw string, aliasToCanonical map[string]string) string {
if canon, ok := aliasToCanonical[raw]; ok {
return canon
}
return raw
}

func (m *NetstatCollector) Init(config json.RawMessage) error {
Expand Down Expand Up @@ -77,6 +95,8 @@ func (m *NetstatCollector) Init(config json.RawMessage) error {
}
}

m.buildAliasMapping()

// Check access to net statistic file
file, err := os.Open(NETSTATFILE)
if err != nil {
Expand All @@ -97,18 +117,20 @@ func (m *NetstatCollector) Init(config json.RawMessage) error {
// Split line into fields
f := strings.Fields(l)

// Get net device entry
dev := strings.Trim(f[0], ": ")
// Get raw and canonical names
raw := strings.Trim(f[0], ": ")
canonical := getCanonicalName(raw, m.aliasToCanonical)

// Check if device is a included device
if _, ok := stringArrayContains(m.config.IncludeDevices, dev); ok {
tags := map[string]string{"stype": "network", "stype-id": dev, "type": "node"}
if _, ok := stringArrayContains(m.config.IncludeDevices, canonical); ok {
// Tag will contain original device name (raw).
tags := map[string]string{"stype": "network", "stype-id": raw, "type": "node"}
meta_unit_byte := map[string]string{"source": m.name, "group": "Network", "unit": "bytes"}
meta_unit_byte_per_sec := map[string]string{"source": m.name, "group": "Network", "unit": "bytes/sec"}
meta_unit_pkts := map[string]string{"source": m.name, "group": "Network", "unit": "packets"}
meta_unit_pkts_per_sec := map[string]string{"source": m.name, "group": "Network", "unit": "packets/sec"}

m.matches[dev] = []NetstatCollectorMetric{
m.matches[canonical] = []NetstatCollectorMetric{
{
name: "net_bytes_in",
index: fieldReceiveBytes,
Expand Down Expand Up @@ -143,7 +165,6 @@ func (m *NetstatCollector) Init(config json.RawMessage) error {
},
}
}

}

if len(m.matches) == 0 {
Expand All @@ -164,7 +185,7 @@ func (m *NetstatCollector) Read(interval time.Duration, output chan lp.CCMessage
// Save current timestamp
m.lastTimestamp = now

file, err := os.Open(string(NETSTATFILE))
file, err := os.Open(NETSTATFILE)
if err != nil {
cclog.ComponentError(m.name, err.Error())
return
Expand All @@ -183,11 +204,12 @@ func (m *NetstatCollector) Read(interval time.Duration, output chan lp.CCMessage
// Split line into fields
f := strings.Fields(l)

// Get net device entry
dev := strings.Trim(f[0], ":")
// Get raw and canonical names
raw := strings.Trim(f[0], ":")
canonical := getCanonicalName(raw, m.aliasToCanonical)

// Check if device is a included device
if devmetrics, ok := m.matches[dev]; ok {
if devmetrics, ok := m.matches[canonical]; ok {
for i := range devmetrics {
metric := &devmetrics[i]

Expand Down
16 changes: 10 additions & 6 deletions collectors/netstatMetric.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@
```json
"netstat": {
"include_devices": [
"eth0"
"eth0",
"eno1"
],
"send_abs_values" : true,
"send_derived_values" : true
"send_abs_values": true,
"send_derived_values": true,
"interface_aliases": {
"eno1": ["eno1np0", "eno1_alt"],
"eth0": ["eth0_alias"]
}
}
```

The `netstat` collector reads data from `/proc/net/dev` and outputs a handful **node** metrics. With the `include_devices` list you can specify which network devices should be measured. **Note**: Most other collectors use an _exclude_ list instead of an include list.
The `netstat` collector reads data from `/proc/net/dev` and outputs a handful **node** metrics. With the `include_devices` list you can specify which network devices should be measured. **Note**: Most other collectors use an _exclude_ list instead of an include list. Optionally, you can define an interface_aliases mapping. For each canonical device (as listed in include_devices), you may provide an array of aliases that may be reported by the system. When an alias is detected, it is preferred for matching, while the output tag stype-id always shows the actual system-reported name.

Metrics:
* `net_bytes_in` (`unit=bytes`)
Expand All @@ -23,5 +28,4 @@ Metrics:
* `net_pkts_in_bw` (`unit=packets/sec` if `send_derived_values == true`)
* `net_pkts_out_bw` (`unit=packets/sec` if `send_derived_values == true`)

The device name is added as tag `stype=network,stype-id=<device>`.

The device name is added as tag `stype=network,stype-id=<device>`.

0 comments on commit 0f92f10

Please sign in to comment.