Skip to content

Commit fc3f327

Browse files
authored
channelz: refactor to move proto API to a separate package (#7065)
1 parent b78c0eb commit fc3f327

File tree

9 files changed

+475
-274
lines changed

9 files changed

+475
-274
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
*
3+
* Copyright 2024 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package protoconv
20+
21+
import (
22+
"time"
23+
24+
"github.com/golang/protobuf/ptypes"
25+
"google.golang.org/grpc/codes"
26+
"google.golang.org/grpc/connectivity"
27+
"google.golang.org/grpc/internal/channelz"
28+
"google.golang.org/grpc/status"
29+
30+
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
31+
)
32+
33+
func connectivityStateToProto(s *connectivity.State) *channelzpb.ChannelConnectivityState {
34+
if s == nil {
35+
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_UNKNOWN}
36+
}
37+
switch *s {
38+
case connectivity.Idle:
39+
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_IDLE}
40+
case connectivity.Connecting:
41+
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_CONNECTING}
42+
case connectivity.Ready:
43+
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_READY}
44+
case connectivity.TransientFailure:
45+
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_TRANSIENT_FAILURE}
46+
case connectivity.Shutdown:
47+
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_SHUTDOWN}
48+
default:
49+
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_UNKNOWN}
50+
}
51+
}
52+
53+
func channelTraceToProto(ct *channelz.ChannelTrace) *channelzpb.ChannelTrace {
54+
pbt := &channelzpb.ChannelTrace{}
55+
if ct == nil {
56+
return pbt
57+
}
58+
pbt.NumEventsLogged = ct.EventNum
59+
if ts, err := ptypes.TimestampProto(ct.CreationTime); err == nil {
60+
pbt.CreationTimestamp = ts
61+
}
62+
events := make([]*channelzpb.ChannelTraceEvent, 0, len(ct.Events))
63+
for _, e := range ct.Events {
64+
cte := &channelzpb.ChannelTraceEvent{
65+
Description: e.Desc,
66+
Severity: channelzpb.ChannelTraceEvent_Severity(e.Severity),
67+
}
68+
if ts, err := ptypes.TimestampProto(e.Timestamp); err == nil {
69+
cte.Timestamp = ts
70+
}
71+
if e.RefID != 0 {
72+
switch e.RefType {
73+
case channelz.RefChannel:
74+
cte.ChildRef = &channelzpb.ChannelTraceEvent_ChannelRef{ChannelRef: &channelzpb.ChannelRef{ChannelId: e.RefID, Name: e.RefName}}
75+
case channelz.RefSubChannel:
76+
cte.ChildRef = &channelzpb.ChannelTraceEvent_SubchannelRef{SubchannelRef: &channelzpb.SubchannelRef{SubchannelId: e.RefID, Name: e.RefName}}
77+
}
78+
}
79+
events = append(events, cte)
80+
}
81+
pbt.Events = events
82+
return pbt
83+
}
84+
85+
func channelToProto(cm *channelz.Channel) *channelzpb.Channel {
86+
c := &channelzpb.Channel{}
87+
c.Ref = &channelzpb.ChannelRef{ChannelId: cm.ID, Name: cm.RefName}
88+
89+
c.Data = &channelzpb.ChannelData{
90+
State: connectivityStateToProto(cm.ChannelMetrics.State.Load()),
91+
Target: strFromPointer(cm.ChannelMetrics.Target.Load()),
92+
CallsStarted: cm.ChannelMetrics.CallsStarted.Load(),
93+
CallsSucceeded: cm.ChannelMetrics.CallsSucceeded.Load(),
94+
CallsFailed: cm.ChannelMetrics.CallsFailed.Load(),
95+
}
96+
if ts, err := ptypes.TimestampProto(time.Unix(0, cm.ChannelMetrics.LastCallStartedTimestamp.Load())); err == nil {
97+
c.Data.LastCallStartedTimestamp = ts
98+
}
99+
ncs := cm.NestedChans()
100+
nestedChans := make([]*channelzpb.ChannelRef, 0, len(ncs))
101+
for id, ref := range ncs {
102+
nestedChans = append(nestedChans, &channelzpb.ChannelRef{ChannelId: id, Name: ref})
103+
}
104+
c.ChannelRef = nestedChans
105+
106+
scs := cm.SubChans()
107+
subChans := make([]*channelzpb.SubchannelRef, 0, len(scs))
108+
for id, ref := range scs {
109+
subChans = append(subChans, &channelzpb.SubchannelRef{SubchannelId: id, Name: ref})
110+
}
111+
c.SubchannelRef = subChans
112+
113+
c.Data.Trace = channelTraceToProto(cm.Trace())
114+
return c
115+
}
116+
117+
// GetTopChannels returns the protobuf representation of the channels starting
118+
// at startID (max of len), and returns end=true if no top channels exist with
119+
// higher IDs.
120+
func GetTopChannels(startID int64, len int) (channels []*channelzpb.Channel, end bool) {
121+
chans, end := channelz.GetTopChannels(startID, len)
122+
for _, ch := range chans {
123+
channels = append(channels, channelToProto(ch))
124+
}
125+
return channels, end
126+
}
127+
128+
// GetChannel returns the protobuf representation of the channel with the given
129+
// ID.
130+
func GetChannel(id int64) (*channelzpb.Channel, error) {
131+
ch := channelz.GetChannel(id)
132+
if ch == nil {
133+
return nil, status.Errorf(codes.NotFound, "requested channel %d not found", id)
134+
}
135+
return channelToProto(ch), nil
136+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
*
3+
* Copyright 2024 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package protoconv
20+
21+
import (
22+
"time"
23+
24+
"github.com/golang/protobuf/ptypes"
25+
"google.golang.org/grpc/codes"
26+
"google.golang.org/grpc/internal/channelz"
27+
"google.golang.org/grpc/status"
28+
29+
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
30+
)
31+
32+
func serverToProto(sm *channelz.Server) *channelzpb.Server {
33+
s := &channelzpb.Server{}
34+
s.Ref = &channelzpb.ServerRef{ServerId: sm.ID, Name: sm.RefName}
35+
36+
s.Data = &channelzpb.ServerData{
37+
CallsStarted: sm.ServerMetrics.CallsStarted.Load(),
38+
CallsSucceeded: sm.ServerMetrics.CallsSucceeded.Load(),
39+
CallsFailed: sm.ServerMetrics.CallsFailed.Load(),
40+
}
41+
42+
if ts, err := ptypes.TimestampProto(time.Unix(0, sm.ServerMetrics.LastCallStartedTimestamp.Load())); err == nil {
43+
s.Data.LastCallStartedTimestamp = ts
44+
}
45+
lss := sm.ListenSockets()
46+
sockets := make([]*channelzpb.SocketRef, 0, len(lss))
47+
for id, ref := range lss {
48+
sockets = append(sockets, &channelzpb.SocketRef{SocketId: id, Name: ref})
49+
}
50+
s.ListenSocket = sockets
51+
return s
52+
}
53+
54+
// GetServers returns the protobuf representation of the servers starting at
55+
// startID (max of len), and returns end=true if no servers exist with higher
56+
// IDs.
57+
func GetServers(startID int64, len int) (servers []*channelzpb.Server, end bool) {
58+
srvs, end := channelz.GetServers(startID, len)
59+
for _, srv := range srvs {
60+
servers = append(servers, serverToProto(srv))
61+
}
62+
return servers, end
63+
}
64+
65+
// GetServer returns the protobuf representation of the server with the given
66+
// ID.
67+
func GetServer(id int64) (*channelzpb.Server, error) {
68+
srv := channelz.GetServer(id)
69+
if srv == nil {
70+
return nil, status.Errorf(codes.NotFound, "requested server %d not found", id)
71+
}
72+
return serverToProto(srv), nil
73+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
*
3+
* Copyright 2024 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package protoconv
20+
21+
import (
22+
"net"
23+
"time"
24+
25+
"github.com/golang/protobuf/ptypes"
26+
"google.golang.org/grpc/codes"
27+
"google.golang.org/grpc/credentials"
28+
"google.golang.org/grpc/internal/channelz"
29+
"google.golang.org/grpc/status"
30+
"google.golang.org/protobuf/protoadapt"
31+
"google.golang.org/protobuf/types/known/anypb"
32+
33+
wrpb "github.com/golang/protobuf/ptypes/wrappers"
34+
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
35+
)
36+
37+
func securityToProto(se credentials.ChannelzSecurityValue) *channelzpb.Security {
38+
switch v := se.(type) {
39+
case *credentials.TLSChannelzSecurityValue:
40+
return &channelzpb.Security{Model: &channelzpb.Security_Tls_{Tls: &channelzpb.Security_Tls{
41+
CipherSuite: &channelzpb.Security_Tls_StandardName{StandardName: v.StandardName},
42+
LocalCertificate: v.LocalCertificate,
43+
RemoteCertificate: v.RemoteCertificate,
44+
}}}
45+
case *credentials.OtherChannelzSecurityValue:
46+
otherSecurity := &channelzpb.Security_OtherSecurity{
47+
Name: v.Name,
48+
}
49+
if anyval, err := anypb.New(protoadapt.MessageV2Of(v.Value)); err == nil {
50+
otherSecurity.Value = anyval
51+
}
52+
return &channelzpb.Security{Model: &channelzpb.Security_Other{Other: otherSecurity}}
53+
}
54+
return nil
55+
}
56+
57+
func addrToProto(a net.Addr) *channelzpb.Address {
58+
if a == nil {
59+
return nil
60+
}
61+
switch a.Network() {
62+
case "udp":
63+
// TODO: Address_OtherAddress{}. Need proto def for Value.
64+
case "ip":
65+
// Note zone info is discarded through the conversion.
66+
return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.IPAddr).IP}}}
67+
case "ip+net":
68+
// Note mask info is discarded through the conversion.
69+
return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.IPNet).IP}}}
70+
case "tcp":
71+
// Note zone info is discarded through the conversion.
72+
return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.TCPAddr).IP, Port: int32(a.(*net.TCPAddr).Port)}}}
73+
case "unix", "unixgram", "unixpacket":
74+
return &channelzpb.Address{Address: &channelzpb.Address_UdsAddress_{UdsAddress: &channelzpb.Address_UdsAddress{Filename: a.String()}}}
75+
default:
76+
}
77+
return &channelzpb.Address{}
78+
}
79+
80+
func socketToProto(skt *channelz.Socket) *channelzpb.Socket {
81+
s := &channelzpb.Socket{}
82+
s.Ref = &channelzpb.SocketRef{SocketId: skt.ID, Name: skt.RefName}
83+
84+
s.Data = &channelzpb.SocketData{
85+
StreamsStarted: skt.SocketMetrics.StreamsStarted.Load(),
86+
StreamsSucceeded: skt.SocketMetrics.StreamsSucceeded.Load(),
87+
StreamsFailed: skt.SocketMetrics.StreamsFailed.Load(),
88+
MessagesSent: skt.SocketMetrics.MessagesSent.Load(),
89+
MessagesReceived: skt.SocketMetrics.MessagesReceived.Load(),
90+
KeepAlivesSent: skt.SocketMetrics.KeepAlivesSent.Load(),
91+
}
92+
if ts, err := ptypes.TimestampProto(time.Unix(0, skt.SocketMetrics.LastLocalStreamCreatedTimestamp.Load())); err == nil {
93+
s.Data.LastLocalStreamCreatedTimestamp = ts
94+
}
95+
if ts, err := ptypes.TimestampProto(time.Unix(0, skt.SocketMetrics.LastRemoteStreamCreatedTimestamp.Load())); err == nil {
96+
s.Data.LastRemoteStreamCreatedTimestamp = ts
97+
}
98+
if ts, err := ptypes.TimestampProto(time.Unix(0, skt.SocketMetrics.LastMessageSentTimestamp.Load())); err == nil {
99+
s.Data.LastMessageSentTimestamp = ts
100+
}
101+
if ts, err := ptypes.TimestampProto(time.Unix(0, skt.SocketMetrics.LastMessageReceivedTimestamp.Load())); err == nil {
102+
s.Data.LastMessageReceivedTimestamp = ts
103+
}
104+
if skt.EphemeralMetrics != nil {
105+
e := skt.EphemeralMetrics()
106+
s.Data.LocalFlowControlWindow = &wrpb.Int64Value{Value: e.LocalFlowControlWindow}
107+
s.Data.RemoteFlowControlWindow = &wrpb.Int64Value{Value: e.RemoteFlowControlWindow}
108+
}
109+
110+
s.Data.Option = sockoptToProto(skt.SocketOptions)
111+
s.Security = securityToProto(skt.Security)
112+
s.Local = addrToProto(skt.LocalAddr)
113+
s.Remote = addrToProto(skt.RemoteAddr)
114+
s.RemoteName = skt.RemoteName
115+
return s
116+
}
117+
118+
// GetServerSockets returns the protobuf representation of the server (listen)
119+
// sockets starting at startID (max of len), and returns end=true if no server
120+
// sockets exist with higher IDs.
121+
func GetServerSockets(serverID, startID int64, len int) (sockets []*channelzpb.SocketRef, end bool) {
122+
skts, end := channelz.GetServerSockets(serverID, startID, len)
123+
for _, m := range skts {
124+
sockets = append(sockets, &channelzpb.SocketRef{SocketId: m.ID, Name: m.RefName})
125+
}
126+
return sockets, end
127+
}
128+
129+
// GetSocket returns the protobuf representation of the socket with the given
130+
// ID.
131+
func GetSocket(id int64) (*channelzpb.Socket, error) {
132+
skt := channelz.GetSocket(id)
133+
if skt == nil {
134+
return nil, status.Errorf(codes.NotFound, "requested socket %d not found", id)
135+
}
136+
return socketToProto(skt), nil
137+
}

channelz/service/func_linux.go renamed to channelz/internal/protoconv/sockopt_linux.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
*/
1818

19-
package service
19+
package protoconv
2020

2121
import (
2222
"time"

channelz/service/func_nonlinux.go renamed to channelz/internal/protoconv/sockopt_nonlinux.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
*
2020
*/
2121

22-
package service
22+
package protoconv
2323

2424
import (
2525
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"

0 commit comments

Comments
 (0)