Skip to content

Commit 02705c4

Browse files
committed
TUN-9322: Add metric for unsupported RPC commands for datagram v3
Additionally adds support for the connection index as a label for the datagram v3 specific tunnel metrics. Closes TUN-9322
1 parent ce27840 commit 02705c4

File tree

10 files changed

+133
-96
lines changed

10 files changed

+133
-96
lines changed

connection/quic_datagram_v3.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ package connection
22

33
import (
44
"context"
5-
"fmt"
65
"net"
76
"time"
87

98
"github.com/google/uuid"
9+
"github.com/pkg/errors"
1010
"github.com/quic-go/quic-go"
1111
"github.com/rs/zerolog"
1212

@@ -16,10 +16,17 @@ import (
1616
"github.com/cloudflare/cloudflared/tunnelrpc/pogs"
1717
)
1818

19+
var (
20+
ErrUnsupportedRPCUDPRegistration = errors.New("datagram v3 does not support RegisterUdpSession RPC")
21+
ErrUnsupportedRPCUDPUnregistration = errors.New("datagram v3 does not support UnregisterUdpSession RPC")
22+
)
23+
1924
type datagramV3Connection struct {
20-
conn quic.Connection
25+
conn quic.Connection
26+
index uint8
2127
// datagramMuxer mux/demux datagrams from quic connection
2228
datagramMuxer cfdquic.DatagramConn
29+
metrics cfdquic.Metrics
2330
logger *zerolog.Logger
2431
}
2532

@@ -40,7 +47,9 @@ func NewDatagramV3Connection(ctx context.Context,
4047

4148
return &datagramV3Connection{
4249
conn,
50+
index,
4351
datagramMuxer,
52+
metrics,
4453
logger,
4554
}
4655
}
@@ -50,9 +59,11 @@ func (d *datagramV3Connection) Serve(ctx context.Context) error {
5059
}
5160

5261
func (d *datagramV3Connection) RegisterUdpSession(ctx context.Context, sessionID uuid.UUID, dstIP net.IP, dstPort uint16, closeAfterIdleHint time.Duration, traceContext string) (*pogs.RegisterUdpSessionResponse, error) {
53-
return nil, fmt.Errorf("datagram v3 does not support RegisterUdpSession RPC")
62+
d.metrics.UnsupportedRemoteCommand(d.index, "register_udp_session")
63+
return nil, ErrUnsupportedRPCUDPRegistration
5464
}
5565

5666
func (d *datagramV3Connection) UnregisterUdpSession(ctx context.Context, sessionID uuid.UUID, message string) error {
57-
return fmt.Errorf("datagram v3 does not support UnregisterUdpSession RPC")
67+
d.metrics.UnsupportedRemoteCommand(d.index, "unregister_udp_session")
68+
return ErrUnsupportedRPCUDPUnregistration
5869
}

datagramsession/session.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (s *Session) waitForCloseCondition(ctx context.Context, closeAfterIdle time
8484
// Closing dstConn cancels read so dstToTransport routine in Serve() can return
8585
defer s.dstConn.Close()
8686
if closeAfterIdle == 0 {
87-
// provide deafult is caller doesn't specify one
87+
// provide default is caller doesn't specify one
8888
closeAfterIdle = defaultCloseIdleAfter
8989
}
9090

datagramsession/session_test.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/google/uuid"
1414
"github.com/rs/zerolog"
15+
"github.com/stretchr/testify/assert"
1516
"github.com/stretchr/testify/require"
1617
"golang.org/x/sync/errgroup"
1718

@@ -54,22 +55,22 @@ func testSessionReturns(t *testing.T, closeBy closeMethod, closeAfterIdle time.D
5455
closedByRemote, err := session.Serve(ctx, closeAfterIdle)
5556
switch closeBy {
5657
case closeByContext:
57-
require.Equal(t, context.Canceled, err)
58-
require.False(t, closedByRemote)
58+
assert.Equal(t, context.Canceled, err)
59+
assert.False(t, closedByRemote)
5960
case closeByCallingClose:
60-
require.Equal(t, localCloseReason, err)
61-
require.Equal(t, localCloseReason.byRemote, closedByRemote)
61+
assert.Equal(t, localCloseReason, err)
62+
assert.Equal(t, localCloseReason.byRemote, closedByRemote)
6263
case closeByTimeout:
63-
require.Equal(t, SessionIdleErr(closeAfterIdle), err)
64-
require.False(t, closedByRemote)
64+
assert.Equal(t, SessionIdleErr(closeAfterIdle), err)
65+
assert.False(t, closedByRemote)
6566
}
6667
close(sessionDone)
6768
}()
6869

6970
go func() {
7071
n, err := session.transportToDst(payload)
71-
require.NoError(t, err)
72-
require.Equal(t, len(payload), n)
72+
assert.NoError(t, err)
73+
assert.Equal(t, len(payload), n)
7374
}()
7475

7576
readBuffer := make([]byte, len(payload)+1)
@@ -84,6 +85,8 @@ func testSessionReturns(t *testing.T, closeBy closeMethod, closeAfterIdle time.D
8485
cancel()
8586
case closeByCallingClose:
8687
session.close(localCloseReason)
88+
default:
89+
// ignore
8790
}
8891

8992
<-sessionDone
@@ -128,7 +131,7 @@ func testActiveSessionNotClosed(t *testing.T, readFromDst bool, writeToDst bool)
128131
ctx, cancel := context.WithCancel(context.Background())
129132
errGroup, ctx := errgroup.WithContext(ctx)
130133
errGroup.Go(func() error {
131-
session.Serve(ctx, closeAfterIdle)
134+
_, _ = session.Serve(ctx, closeAfterIdle)
132135
if time.Now().Before(startTime.Add(activeTime)) {
133136
return fmt.Errorf("session closed while it's still active")
134137
}

quic/metrics.go

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@ import (
1111
)
1212

1313
const (
14-
namespace = "quic"
14+
namespace = "quic"
15+
ConnectionIndexMetricLabel = "conn_index"
16+
frameTypeMetricLabel = "frame_type"
17+
packetTypeMetricLabel = "packet_type"
18+
reasonMetricLabel = "reason"
1519
)
1620

1721
var (
18-
clientConnLabels = []string{"conn_index"}
19-
clientMetrics = struct {
22+
clientMetrics = struct {
2023
totalConnections prometheus.Counter
2124
closedConnections prometheus.Counter
2225
maxUDPPayloadSize *prometheus.GaugeVec
@@ -35,15 +38,15 @@ var (
3538
congestionState *prometheus.GaugeVec
3639
}{
3740
totalConnections: prometheus.NewCounter(
38-
prometheus.CounterOpts{
41+
prometheus.CounterOpts{ //nolint:promlinter
3942
Namespace: namespace,
4043
Subsystem: "client",
4144
Name: "total_connections",
4245
Help: "Number of connections initiated",
4346
},
4447
),
4548
closedConnections: prometheus.NewCounter(
46-
prometheus.CounterOpts{
49+
prometheus.CounterOpts{ //nolint:promlinter
4750
Namespace: namespace,
4851
Subsystem: "client",
4952
Name: "closed_connections",
@@ -57,70 +60,70 @@ var (
5760
Name: "max_udp_payload",
5861
Help: "Maximum UDP payload size in bytes for a QUIC packet",
5962
},
60-
clientConnLabels,
63+
[]string{ConnectionIndexMetricLabel},
6164
),
6265
sentFrames: prometheus.NewCounterVec(
63-
prometheus.CounterOpts{
66+
prometheus.CounterOpts{ //nolint:promlinter
6467
Namespace: namespace,
6568
Subsystem: "client",
6669
Name: "sent_frames",
6770
Help: "Number of frames that have been sent through a connection",
6871
},
69-
append(clientConnLabels, "frame_type"),
72+
[]string{ConnectionIndexMetricLabel, frameTypeMetricLabel},
7073
),
7174
sentBytes: prometheus.NewCounterVec(
72-
prometheus.CounterOpts{
75+
prometheus.CounterOpts{ //nolint:promlinter
7376
Namespace: namespace,
7477
Subsystem: "client",
7578
Name: "sent_bytes",
7679
Help: "Number of bytes that have been sent through a connection",
7780
},
78-
clientConnLabels,
81+
[]string{ConnectionIndexMetricLabel},
7982
),
8083
receivedFrames: prometheus.NewCounterVec(
81-
prometheus.CounterOpts{
84+
prometheus.CounterOpts{ //nolint:promlinter
8285
Namespace: namespace,
8386
Subsystem: "client",
8487
Name: "received_frames",
8588
Help: "Number of frames that have been received through a connection",
8689
},
87-
append(clientConnLabels, "frame_type"),
90+
[]string{ConnectionIndexMetricLabel, frameTypeMetricLabel},
8891
),
8992
receivedBytes: prometheus.NewCounterVec(
90-
prometheus.CounterOpts{
93+
prometheus.CounterOpts{ //nolint:promlinter
9194
Namespace: namespace,
9295
Subsystem: "client",
9396
Name: "receive_bytes",
9497
Help: "Number of bytes that have been received through a connection",
9598
},
96-
clientConnLabels,
99+
[]string{ConnectionIndexMetricLabel},
97100
),
98101
bufferedPackets: prometheus.NewCounterVec(
99-
prometheus.CounterOpts{
102+
prometheus.CounterOpts{ //nolint:promlinter
100103
Namespace: namespace,
101104
Subsystem: "client",
102105
Name: "buffered_packets",
103106
Help: "Number of bytes that have been buffered on a connection",
104107
},
105-
append(clientConnLabels, "packet_type"),
108+
[]string{ConnectionIndexMetricLabel, packetTypeMetricLabel},
106109
),
107110
droppedPackets: prometheus.NewCounterVec(
108-
prometheus.CounterOpts{
111+
prometheus.CounterOpts{ //nolint:promlinter
109112
Namespace: namespace,
110113
Subsystem: "client",
111114
Name: "dropped_packets",
112115
Help: "Number of bytes that have been dropped on a connection",
113116
},
114-
append(clientConnLabels, "packet_type", "reason"),
117+
[]string{ConnectionIndexMetricLabel, packetTypeMetricLabel, reasonMetricLabel},
115118
),
116119
lostPackets: prometheus.NewCounterVec(
117-
prometheus.CounterOpts{
120+
prometheus.CounterOpts{ //nolint:promlinter
118121
Namespace: namespace,
119122
Subsystem: "client",
120123
Name: "lost_packets",
121124
Help: "Number of packets that have been lost from a connection",
122125
},
123-
append(clientConnLabels, "reason"),
126+
[]string{ConnectionIndexMetricLabel, reasonMetricLabel},
124127
),
125128
minRTT: prometheus.NewGaugeVec(
126129
prometheus.GaugeOpts{
@@ -129,7 +132,7 @@ var (
129132
Name: "min_rtt",
130133
Help: "Lowest RTT measured on a connection in millisec",
131134
},
132-
clientConnLabels,
135+
[]string{ConnectionIndexMetricLabel},
133136
),
134137
latestRTT: prometheus.NewGaugeVec(
135138
prometheus.GaugeOpts{
@@ -138,7 +141,7 @@ var (
138141
Name: "latest_rtt",
139142
Help: "Latest RTT measured on a connection",
140143
},
141-
clientConnLabels,
144+
[]string{ConnectionIndexMetricLabel},
142145
),
143146
smoothedRTT: prometheus.NewGaugeVec(
144147
prometheus.GaugeOpts{
@@ -147,7 +150,7 @@ var (
147150
Name: "smoothed_rtt",
148151
Help: "Calculated smoothed RTT measured on a connection in millisec",
149152
},
150-
clientConnLabels,
153+
[]string{ConnectionIndexMetricLabel},
151154
),
152155
mtu: prometheus.NewGaugeVec(
153156
prometheus.GaugeOpts{
@@ -156,7 +159,7 @@ var (
156159
Name: "mtu",
157160
Help: "Current maximum transmission unit (MTU) of a connection",
158161
},
159-
clientConnLabels,
162+
[]string{ConnectionIndexMetricLabel},
160163
),
161164
congestionWindow: prometheus.NewGaugeVec(
162165
prometheus.GaugeOpts{
@@ -165,7 +168,7 @@ var (
165168
Name: "congestion_window",
166169
Help: "Current congestion window size",
167170
},
168-
clientConnLabels,
171+
[]string{ConnectionIndexMetricLabel},
169172
),
170173
congestionState: prometheus.NewGaugeVec(
171174
prometheus.GaugeOpts{
@@ -174,13 +177,13 @@ var (
174177
Name: "congestion_state",
175178
Help: "Current congestion control state. See https://pkg.go.dev/github.com/quic-go/[email protected]/logging#CongestionState for what each value maps to",
176179
},
177-
clientConnLabels,
180+
[]string{ConnectionIndexMetricLabel},
178181
),
179182
}
180183

181184
registerClient = sync.Once{}
182185

183-
packetTooBigDropped = prometheus.NewCounter(prometheus.CounterOpts{
186+
packetTooBigDropped = prometheus.NewCounter(prometheus.CounterOpts{ //nolint:promlinter
184187
Namespace: namespace,
185188
Subsystem: "client",
186189
Name: "packet_too_big_dropped",

0 commit comments

Comments
 (0)