Skip to content

Commit 20a4ba5

Browse files
committed
Add collector for netstats tcp packet counters for FreeBSD.
Signed-off-by: K Rin <rin@sandb0x.tw>
1 parent 0fddfd1 commit 20a4ba5

2 files changed

Lines changed: 162 additions & 0 deletions

File tree

collector/netstat_freebsd.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2015 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
//go:build freebsd
15+
// +build freebsd
16+
17+
package collector
18+
19+
import (
20+
"errors"
21+
"fmt"
22+
"github.com/prometheus/client_golang/prometheus"
23+
"golang.org/x/sys/unix"
24+
"log/slog"
25+
"unsafe"
26+
)
27+
28+
/*
29+
#include <sys/types.h>
30+
#include <netinet/in.h>
31+
#include <netinet/ip.h>
32+
#include <netinet/tcp.h>
33+
#include <netinet/tcp_var.h>
34+
#include <netinet/udp.h>
35+
*/
36+
import "C"
37+
38+
var metrics = []string{
39+
"tcp_send_packet_total",
40+
"tcp_recv_packet_total",
41+
}
42+
43+
type netStatCollector struct {
44+
netStatMetric *prometheus.Desc
45+
}
46+
47+
func init() {
48+
registerCollector("netstat", defaultEnabled, NewNetStatCollector)
49+
}
50+
51+
func NewNetStatCollector(logger *slog.Logger) (Collector, error) {
52+
return &netStatCollector{}, nil
53+
}
54+
55+
func (c *netStatCollector) Describe(ch chan<- *prometheus.Desc) {
56+
ch <- c.netStatMetric
57+
}
58+
59+
func (c *netStatCollector) Collect(ch chan<- prometheus.Metric) {
60+
_ = c.Update(ch)
61+
}
62+
63+
func getData(queryString string) ([]byte, error) {
64+
data, err := unix.SysctlRaw(queryString)
65+
if err != nil {
66+
fmt.Println("Error:", err)
67+
return nil, err
68+
}
69+
70+
if len(data) < int(unsafe.Sizeof(C.struct_tcpstat{})) {
71+
return nil, errors.New("Data Size mismatch")
72+
}
73+
return data, nil
74+
}
75+
76+
func (c *netStatCollector) Update(ch chan<- prometheus.Metric) error {
77+
78+
var result []float64
79+
80+
tcpData, err := getData("net.inet.tcp.stats")
81+
if err != nil {
82+
return err
83+
}
84+
85+
tcpStats := *(*C.struct_tcpstat)(unsafe.Pointer(&tcpData[0]))
86+
87+
result = append(result, float64(tcpStats.tcps_sndtotal))
88+
result = append(result, float64(tcpStats.tcps_rcvtotal))
89+
90+
for index, value := range metrics {
91+
ch <- prometheus.MustNewConstMetric(
92+
prometheus.NewDesc(
93+
value,
94+
value,
95+
nil, nil,
96+
),
97+
prometheus.UntypedValue,
98+
result[index],
99+
)
100+
}
101+
102+
return nil
103+
}

collector/netstat_freebsd_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2015 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
//go:build freebsd
15+
// +build freebsd
16+
17+
package collector
18+
19+
import (
20+
"github.com/prometheus/client_golang/prometheus"
21+
"github.com/stretchr/testify/assert"
22+
"golang.org/x/sys/unix"
23+
"testing"
24+
)
25+
26+
func TestNetStatCollectorDescribe(t *testing.T) {
27+
ch := make(chan *prometheus.Desc, 1)
28+
collector := &netStatCollector{
29+
netStatMetric: prometheus.NewDesc("dummy_metric", "dummy", nil, nil),
30+
}
31+
collector.Describe(ch)
32+
desc := <-ch
33+
assert.Equal(t, "dummy_metric", desc.String())
34+
}
35+
36+
func TestGetData(t *testing.T) {
37+
data, err := getData("net.inet.tcp.stats")
38+
assert.NoError(t, err)
39+
assert.GreaterOrEqual(t, len(data), int(unsafe.Sizeof(C.struct_tcpstat{})))
40+
}
41+
42+
func TestNetStatCollectorUpdate(t *testing.T) {
43+
ch := make(chan prometheus.Metric, len(metrics))
44+
collector := &netStatCollector{
45+
netStatMetric: prometheus.NewDesc("netstat_metric", "NetStat Metric", nil, nil),
46+
}
47+
err := collector.Update(ch)
48+
assert.NoError(t, err)
49+
assert.Equal(t, len(metrics), len(ch))
50+
for range metrics {
51+
<-ch
52+
}
53+
}
54+
55+
func TestNewNetStatCollector(t *testing.T) {
56+
collector, err := NewNetStatCollector(nil)
57+
assert.NoError(t, err)
58+
assert.NotNil(t, collector)
59+
}

0 commit comments

Comments
 (0)