Skip to content

Commit 9fdfbe8

Browse files
alebsysSuperQ
andauthored
Add udp drops (prometheus#538)
* Add drops field in /proc/net/udp{,6} files for parsing Signed-off-by: Aleksandr Lebedev <[email protected]> Signed-off-by: Александр Лебедев <[email protected]> * Add count of UDP dropped packets Signed-off-by: Aleksandr Lebedev <[email protected]> Signed-off-by: Александр Лебедев <[email protected]> * Change the type of variable isUDP to local Signed-off-by: Александр Лебедев <[email protected]> * Update net_ip_socket.go Co-authored-by: Ben Kochie <[email protected]> Signed-off-by: Aleksandr Lebedev <[email protected]> * Update net_ip_socket.go Co-authored-by: Ben Kochie <[email protected]> Signed-off-by: Aleksandr Lebedev <[email protected]> --------- Signed-off-by: Aleksandr Lebedev <[email protected]> Signed-off-by: Александр Лебедев <[email protected]> Signed-off-by: Aleksandr Lebedev <[email protected]> Co-authored-by: Ben Kochie <[email protected]>
1 parent f11f6e4 commit 9fdfbe8

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

net_ip_socket.go

+23-3
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@ type (
5050
// UsedSockets shows the total number of parsed lines representing the
5151
// number of used sockets.
5252
UsedSockets uint64
53+
// Drops shows the total number of dropped packets of all UPD sockets.
54+
Drops *uint64
5355
}
5456

5557
// netIPSocketLine represents the fields parsed from a single line
5658
// in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped.
59+
// Drops is non-nil for udp{,6}, but nil for tcp{,6}.
5760
// For the proc file format details, see https://linux.die.net/man/5/proc.
5861
netIPSocketLine struct {
5962
Sl uint64
@@ -66,6 +69,7 @@ type (
6669
RxQueue uint64
6770
UID uint64
6871
Inode uint64
72+
Drops *uint64
6973
}
7074
)
7175

@@ -77,13 +81,14 @@ func newNetIPSocket(file string) (NetIPSocket, error) {
7781
defer f.Close()
7882

7983
var netIPSocket NetIPSocket
84+
isUDP := strings.Contains(file, "udp")
8085

8186
lr := io.LimitReader(f, readLimit)
8287
s := bufio.NewScanner(lr)
8388
s.Scan() // skip first line with headers
8489
for s.Scan() {
8590
fields := strings.Fields(s.Text())
86-
line, err := parseNetIPSocketLine(fields)
91+
line, err := parseNetIPSocketLine(fields, isUDP)
8792
if err != nil {
8893
return nil, err
8994
}
@@ -104,19 +109,25 @@ func newNetIPSocketSummary(file string) (*NetIPSocketSummary, error) {
104109
defer f.Close()
105110

106111
var netIPSocketSummary NetIPSocketSummary
112+
var udpPacketDrops uint64
113+
isUDP := strings.Contains(file, "udp")
107114

108115
lr := io.LimitReader(f, readLimit)
109116
s := bufio.NewScanner(lr)
110117
s.Scan() // skip first line with headers
111118
for s.Scan() {
112119
fields := strings.Fields(s.Text())
113-
line, err := parseNetIPSocketLine(fields)
120+
line, err := parseNetIPSocketLine(fields, isUDP)
114121
if err != nil {
115122
return nil, err
116123
}
117124
netIPSocketSummary.TxQueueLength += line.TxQueue
118125
netIPSocketSummary.RxQueueLength += line.RxQueue
119126
netIPSocketSummary.UsedSockets++
127+
if isUDP {
128+
udpPacketDrops += *line.Drops
129+
netIPSocketSummary.Drops = &udpPacketDrops
130+
}
120131
}
121132
if err := s.Err(); err != nil {
122133
return nil, err
@@ -149,7 +160,7 @@ func parseIP(hexIP string) (net.IP, error) {
149160
}
150161

151162
// parseNetIPSocketLine parses a single line, represented by a list of fields.
152-
func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) {
163+
func parseNetIPSocketLine(fields []string, isUDP bool) (*netIPSocketLine, error) {
153164
line := &netIPSocketLine{}
154165
if len(fields) < 10 {
155166
return nil, fmt.Errorf(
@@ -224,5 +235,14 @@ func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) {
224235
return nil, fmt.Errorf("%s: Cannot parse inode value in %q: %w", ErrFileParse, line.Inode, err)
225236
}
226237

238+
// drops
239+
if isUDP {
240+
drops, err := strconv.ParseUint(fields[12], 0, 64)
241+
if err != nil {
242+
return nil, fmt.Errorf("%s: Cannot parse drops value in %q: %w", ErrFileParse, drops, err)
243+
}
244+
line.Drops = &drops
245+
}
246+
227247
return line, nil
228248
}

net_ip_socket_test.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ func Test_parseNetIPSocketLine(t *testing.T) {
2525
name string
2626
want *netIPSocketLine
2727
wantErr bool
28+
isUDP bool
2829
}{
2930
{
3031
name: "reading valid lines, no issue should happened",
@@ -96,10 +97,17 @@ func Test_parseNetIPSocketLine(t *testing.T) {
9697
want: nil,
9798
wantErr: true,
9899
},
100+
{
101+
name: "error case - parse Drops - not a valid uint",
102+
fields: []string{"1:", "00000000:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "10", "0", "39309", "2", "000000009bd60d72", "-5"},
103+
want: nil,
104+
wantErr: true,
105+
isUDP: true,
106+
},
99107
}
100108
for _, tt := range tests {
101109
t.Run(tt.name, func(t *testing.T) {
102-
got, err := parseNetIPSocketLine(tt.fields)
110+
got, err := parseNetIPSocketLine(tt.fields, tt.isUDP)
103111
if (err != nil) != tt.wantErr {
104112
t.Errorf("parseNetIPSocketLine() error = %v, wantErr %v", err, tt.wantErr)
105113
return

net_udp_test.go

+13-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ func Test_newNetUDP(t *testing.T) {
4141
RxQueue: 1,
4242
UID: 0,
4343
Inode: 2740,
44+
Drops: intToU64(100),
4445
},
4546
&netIPSocketLine{
4647
Sl: 1,
@@ -53,6 +54,7 @@ func Test_newNetUDP(t *testing.T) {
5354
RxQueue: 0,
5455
UID: 0,
5556
Inode: 2740,
57+
Drops: intToU64(100),
5658
},
5759
&netIPSocketLine{
5860
Sl: 2,
@@ -65,6 +67,7 @@ func Test_newNetUDP(t *testing.T) {
6567
RxQueue: 1,
6668
UID: 0,
6769
Inode: 2740,
70+
Drops: intToU64(100),
6871
},
6972
},
7073
wantErr: false,
@@ -84,6 +87,7 @@ func Test_newNetUDP(t *testing.T) {
8487
RxQueue: 0,
8588
UID: 981,
8689
Inode: 21040,
90+
Drops: intToU64(0),
8791
},
8892
&netIPSocketLine{
8993
Sl: 6073,
@@ -96,6 +100,7 @@ func Test_newNetUDP(t *testing.T) {
96100
RxQueue: 0,
97101
UID: 1000,
98102
Inode: 11337031,
103+
Drops: intToU64(0),
99104
},
100105
},
101106
wantErr: false,
@@ -137,13 +142,13 @@ func Test_newNetUDPSummary(t *testing.T) {
137142
{
138143
name: "udp file found, no error should come up",
139144
file: "testdata/fixtures/proc/net/udp",
140-
want: &NetUDPSummary{TxQueueLength: 2, RxQueueLength: 2, UsedSockets: 3},
145+
want: &NetUDPSummary{TxQueueLength: 2, RxQueueLength: 2, UsedSockets: 3, Drops: intToU64(300)},
141146
wantErr: false,
142147
},
143148
{
144149
name: "udp6 file found, no error should come up",
145150
file: "testdata/fixtures/proc/net/udp6",
146-
want: &NetUDPSummary{TxQueueLength: 0, RxQueueLength: 0, UsedSockets: 2},
151+
want: &NetUDPSummary{TxQueueLength: 0, RxQueueLength: 0, UsedSockets: 2, Drops: intToU64(0)},
147152
wantErr: false,
148153
},
149154
{
@@ -172,3 +177,9 @@ func Test_newNetUDPSummary(t *testing.T) {
172177
})
173178
}
174179
}
180+
181+
// intToU64 convert int to uint64 and return it pointer.
182+
func intToU64(i int) *uint64 {
183+
cast := uint64(i)
184+
return &cast
185+
}

0 commit comments

Comments
 (0)