Skip to content

Commit 41f6ba3

Browse files
authored
Expose inbound.cancels.{requested,honored} metrics (#912)
This commit adds `inbound.cancels.requested` and `inbound.cancels.honored` metrics. The [documentation mentions these metrics](https://tchannel.readthedocs.io/en/latest/metrics/#inboundcancelsrequested), but they were not yet implemented.
1 parent 7576b14 commit 41f6ba3

4 files changed

Lines changed: 58 additions & 3 deletions

File tree

connection_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,9 @@ func TestServerClientCancellation(t *testing.T) {
496496
opts.DefaultConnectionOptions.SendCancelOnContextCanceled = true
497497
opts.DefaultConnectionOptions.PropagateCancel = true
498498

499+
serverStats := newRecordingStatsReporter()
500+
opts.StatsReporter = serverStats
501+
499502
testutils.WithTestServer(t, opts, func(t testing.TB, ts *testutils.TestServer) {
500503
callReceived := make(chan struct{})
501504
testutils.RegisterFunc(ts.Server(), "ctxWait", func(ctx context.Context, args *raw.Args) (*raw.Res, error) {
@@ -519,16 +522,23 @@ func TestServerClientCancellation(t *testing.T) {
519522
_, _, _, err := raw.Call(ctx, ts.Server(), ts.HostPort(), ts.ServiceName(), "ctxWait", nil, nil)
520523
assert.Equal(t, ErrRequestCancelled, err, "client call result")
521524

525+
statsTags := ts.Server().StatsTags()
526+
serverStats.Expected.IncCounter("inbound.cancels.requested", statsTags, 1)
527+
serverStats.Expected.IncCounter("inbound.cancels.honored", statsTags, 1)
528+
522529
calls := relaytest.NewMockStats()
523530
calls.Add(ts.ServiceName(), ts.ServiceName(), "ctxWait").Failed("canceled").End()
524531
ts.AssertRelayStats(calls)
525532
})
533+
534+
serverStats.ValidateExpected(t)
526535
}
527536

528537
func TestCancelWithoutSendCancelOnContextCanceled(t *testing.T) {
529538
tests := []struct {
530539
msg string
531540
sendCancelOnContextCanceled bool
541+
wantCancelRequested bool
532542
}{
533543
{
534544
msg: "no send or process cancel",
@@ -537,6 +547,7 @@ func TestCancelWithoutSendCancelOnContextCanceled(t *testing.T) {
537547
{
538548
msg: "only enable cancels on outbounds",
539549
sendCancelOnContextCanceled: true,
550+
wantCancelRequested: true,
540551
},
541552
}
542553

@@ -545,7 +556,12 @@ func TestCancelWithoutSendCancelOnContextCanceled(t *testing.T) {
545556
opts := testutils.NewOpts()
546557
opts.DefaultConnectionOptions.SendCancelOnContextCanceled = tt.sendCancelOnContextCanceled
547558

559+
serverStats := newRecordingStatsReporter()
560+
opts.StatsReporter = serverStats
561+
548562
testutils.WithTestServer(t, opts, func(t testing.TB, ts *testutils.TestServer) {
563+
serverStats.Reset()
564+
549565
callReceived := make(chan struct{})
550566
testutils.RegisterFunc(ts.Server(), "ctxWait", func(ctx context.Context, args *raw.Args) (*raw.Res, error) {
551567
require.NoError(t, ctx.Err(), "context valid before cancellation")
@@ -571,6 +587,17 @@ func TestCancelWithoutSendCancelOnContextCanceled(t *testing.T) {
571587
calls := relaytest.NewMockStats()
572588
calls.Add(ts.ServiceName(), ts.ServiceName(), "ctxWait").Failed("timeout").End()
573589
ts.AssertRelayStats(calls)
590+
591+
ts.AddPostFn(func() {
592+
// Validating these at the end of the test, when server has fully processed the cancellation.
593+
if tt.wantCancelRequested && !ts.HasRelay() {
594+
serverStats.Expected.IncCounter("inbound.cancels.requested", ts.Server().StatsTags(), 1)
595+
serverStats.ValidateExpected(t)
596+
} else {
597+
serverStats.EnsureNotPresent(t, "inbound.cancels.requested")
598+
}
599+
serverStats.EnsureNotPresent(t, "inbound.cancels.honored")
600+
})
574601
})
575602
})
576603
}

inbound.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,17 @@ func (c *Connection) handleCallReqContinue(frame *Frame) bool {
144144
}
145145

146146
func (c *Connection) handleCancel(frame *Frame) bool {
147+
c.statsReporter.IncCounter("inbound.cancels.requested", c.commonStatsTags, 1)
148+
147149
if !c.opts.PropagateCancel {
148150
if c.log.Enabled(LogLevelDebug) {
149151
c.log.Debugf("Ignoring cancel for %v", frame.Header.ID)
150152
}
151153
return true
152154
}
153155

156+
c.statsReporter.IncCounter("inbound.cancels.honored", c.commonStatsTags, 1)
157+
154158
c.inbound.handleCancel(frame)
155159

156160
// Free the frame, as it's consumed immediately.

stats_utils_test.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,28 @@ func (r *recordingStatsReporter) Validate(t *testing.T) {
125125

126126
assert.Equal(t, keysMap(r.Expected.Values), keysMap(r.Values),
127127
"Metric keys are different")
128-
for counterKey, counter := range r.Values {
129-
expectedCounter, ok := r.Expected.Values[counterKey]
130-
if !ok {
128+
r.validateExpectedLocked(t)
129+
}
130+
131+
// ValidateExpected only validates metrics added to expected rather than all recorded metrics.
132+
func (r *recordingStatsReporter) ValidateExpected(t testing.TB) {
133+
r.Lock()
134+
defer r.Unlock()
135+
136+
r.validateExpectedLocked(t)
137+
}
138+
139+
func (r *recordingStatsReporter) EnsureNotPresent(t testing.TB, counter string) {
140+
r.Lock()
141+
defer r.Unlock()
142+
143+
assert.NotContains(t, r.Values, counter, "metric should not be present")
144+
}
145+
146+
func (r *recordingStatsReporter) validateExpectedLocked(t testing.TB) {
147+
for counterKey, expectedCounter := range r.Expected.Values {
148+
counter, ok := r.Values[counterKey]
149+
if !assert.True(t, ok, "expected %v not found", counterKey) {
131150
continue
132151
}
133152

testutils/test_server.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,11 @@ func (ts *TestServer) verify(ch *tchannel.Channel) {
400400
assert.NoError(ts, errs, "Verification failed. Channel state:\n%v", IntrospectJSON(ch, nil /* opts */))
401401
}
402402

403+
// AddPostFn registers a function that will be executed after channels are closed.
404+
func (ts *TestServer) AddPostFn(fn func()) {
405+
ts.postFns = append(ts.postFns, fn)
406+
}
407+
403408
func (ts *TestServer) post() {
404409
if !ts.Failed() {
405410
for _, ch := range ts.channels {

0 commit comments

Comments
 (0)