From 3ffedf3cb694d5d0907b2dcd71241e031fe52ee3 Mon Sep 17 00:00:00 2001 From: "Aryan Singh K." <70511529+aryansk@users.noreply.github.com> Date: Thu, 6 Aug 2026 11:49:56 +0530 Subject: [PATCH 1/4] stats: expose client authority in OutHeader --- internal/transport/http2_client.go | 1 + stats/stats.go | 3 +++ stats/stats_test.go | 29 ++++++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/internal/transport/http2_client.go b/internal/transport/http2_client.go index b2db61a1f86d..b5a895a1e5ba 100644 --- a/internal/transport/http2_client.go +++ b/internal/transport/http2_client.go @@ -946,6 +946,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr, handler s LocalAddr: t.localAddr, Compression: callHdr.SendCompress, Header: header, + Authority: callHdr.Host, }) } if transportDrainRequired { diff --git a/stats/stats.go b/stats/stats.go index 10bf998aa5be..c6996724c95c 100644 --- a/stats/stats.go +++ b/stats/stats.go @@ -190,6 +190,9 @@ type OutHeader struct { Compression string // Header contains the header metadata sent. Header metadata.MD + // Authority is the :authority pseudo-header sent for the RPC. + // It is valid only if Client is true. + Authority string // The following fields are valid only if Client is true. // FullMethod is the full RPC method string, i.e., /package.service/method. diff --git a/stats/stats_test.go b/stats/stats_test.go index cc33062260af..bf39a258240e 100644 --- a/stats/stats_test.go +++ b/stats/stats_test.go @@ -297,6 +297,7 @@ type rpcConfig struct { count int // Number of requests and responses for streaming RPCs. success bool // Whether the RPC should succeed or return error. failfast bool + authority string // Authority override for the RPC. callType rpcType // Type of RPC. } @@ -315,7 +316,11 @@ func (te *test) doUnaryCall(c *rpcConfig) (*testpb.SimpleRequest, *testpb.Simple req = &testpb.SimpleRequest{Payload: idToPayload(errorID)} } - resp, err = tc.UnaryCall(metadata.NewOutgoingContext(tCtx, testMetadata), req, grpc.WaitForReady(!c.failfast)) + callOpts := []grpc.CallOption{grpc.WaitForReady(!c.failfast)} + if c.authority != "" { + callOpts = append(callOpts, grpc.CallAuthority(c.authority)) + } + resp, err = tc.UnaryCall(metadata.NewOutgoingContext(tCtx, testMetadata), req, callOpts...) return req, resp, err } @@ -427,6 +432,7 @@ type expectedData struct { isServerStream bool serverAddr string compression string + authority string reqIdx int requests []proto.Message respIdx int @@ -620,6 +626,9 @@ func checkOutHeader(t *testing.T, d *gotData, e *expectedData) { if st.RemoteAddr.String() != e.serverAddr { t.Fatalf("st.RemoteAddr = %v, want %v", st.RemoteAddr, e.serverAddr) } + if e.authority != "" && st.Authority != e.authority { + t.Fatalf("st.Authority = %s, want %s", st.Authority, e.authority) + } // additional headers might be injected so instead of testing equality, test that all the // expected headers keys have the expected header values. for key := range testMetadata { @@ -1215,6 +1224,7 @@ func testClientStats(t *testing.T, tc *testConfig, cc *rpcConfig, checkFuncs map h.mu.Lock() checkConnStats(t, h.gotConn) h.mu.Unlock() + expect.authority = cc.authority checkClientStats(t, h.gotRPC, expect, checkFuncs) } @@ -1230,6 +1240,23 @@ func (s) TestClientStatsUnaryRPC(t *testing.T) { }) } +func (s) TestClientStatsUnaryRPCAuthority(t *testing.T) { + testClientStats(t, &testConfig{compress: ""}, &rpcConfig{ + success: true, + failfast: false, + authority: "authority-override.example.com", + callType: unaryRPC, + }, map[int]*checkFuncWithCount{ + begin: {checkBegin, 1}, + outHeader: {checkOutHeader, 1}, + outPayload: {checkOutPayload, 1}, + inHeader: {checkInHeader, 1}, + inPayload: {checkInPayload, 1}, + inTrailer: {checkInTrailer, 1}, + end: {checkEnd, 1}, + }) +} + func (s) TestClientStatsUnaryRPCError(t *testing.T) { testClientStats(t, &testConfig{compress: ""}, &rpcConfig{success: false, failfast: false, callType: unaryRPC}, map[int]*checkFuncWithCount{ begin: {checkBegin, 1}, From df0c7800e6b73c8e5c57ba567face53a762491b2 Mon Sep 17 00:00:00 2001 From: "Aryan Singh K." <70511529+aryansk@users.noreply.github.com> Date: Thu, 6 Aug 2026 12:23:11 +0530 Subject: [PATCH 2/4] gofmt stats authority regression test --- stats/stats_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stats/stats_test.go b/stats/stats_test.go index bf39a258240e..daaee2b9284d 100644 --- a/stats/stats_test.go +++ b/stats/stats_test.go @@ -294,11 +294,11 @@ const ( ) type rpcConfig struct { - count int // Number of requests and responses for streaming RPCs. - success bool // Whether the RPC should succeed or return error. - failfast bool - authority string // Authority override for the RPC. - callType rpcType // Type of RPC. + count int // Number of requests and responses for streaming RPCs. + success bool // Whether the RPC should succeed or return error. + failfast bool + authority string // Authority override for the RPC. + callType rpcType // Type of RPC. } func (te *test) doUnaryCall(c *rpcConfig) (*testpb.SimpleRequest, *testpb.SimpleResponse, error) { From efbf74467e6c27ed31febb5fc3d17c736cda1a27 Mon Sep 17 00:00:00 2001 From: "Aryan Singh K." <70511529+aryansk@users.noreply.github.com> Date: Tue, 11 Aug 2026 21:01:53 +0530 Subject: [PATCH 3/4] Test default authority in client stats --- stats/stats_test.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stats/stats_test.go b/stats/stats_test.go index daaee2b9284d..c0603265978e 100644 --- a/stats/stats_test.go +++ b/stats/stats_test.go @@ -626,8 +626,12 @@ func checkOutHeader(t *testing.T, d *gotData, e *expectedData) { if st.RemoteAddr.String() != e.serverAddr { t.Fatalf("st.RemoteAddr = %v, want %v", st.RemoteAddr, e.serverAddr) } - if e.authority != "" && st.Authority != e.authority { - t.Fatalf("st.Authority = %s, want %s", st.Authority, e.authority) + wantAuthority := e.authority + if wantAuthority == "" { + wantAuthority = e.serverAddr + } + if st.Authority != wantAuthority { + t.Fatalf("st.Authority = %s, want %s", st.Authority, wantAuthority) } // additional headers might be injected so instead of testing equality, test that all the // expected headers keys have the expected header values. From fef007fba94861b81499f88f3941cf4d0439af60 Mon Sep 17 00:00:00 2001 From: "Aryan Singh K." <70511529+aryansk@users.noreply.github.com> Date: Fri, 14 Aug 2026 00:14:11 +0530 Subject: [PATCH 4/4] Initialize authority field in expectedData struct literal --- stats/stats_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stats/stats_test.go b/stats/stats_test.go index c0603265978e..86faba1bdd7d 100644 --- a/stats/stats_test.go +++ b/stats/stats_test.go @@ -1223,12 +1223,12 @@ func testClientStats(t *testing.T, tc *testConfig, cc *rpcConfig, checkFuncs map err: err, isClientStream: isClientStream, isServerStream: isServerStream, + authority: cc.authority, } h.mu.Lock() checkConnStats(t, h.gotConn) h.mu.Unlock() - expect.authority = cc.authority checkClientStats(t, h.gotRPC, expect, checkFuncs) }