You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

687 lines
26 KiB

  1. /*
  2. *
  3. * Copyright 2018 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. package service
  19. import (
  20. "context"
  21. "fmt"
  22. "net"
  23. "reflect"
  24. "strconv"
  25. "testing"
  26. "time"
  27. "github.com/golang/protobuf/proto"
  28. "github.com/golang/protobuf/ptypes"
  29. channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
  30. "google.golang.org/grpc/connectivity"
  31. "google.golang.org/grpc/credentials"
  32. "google.golang.org/grpc/internal/channelz"
  33. )
  34. func init() {
  35. channelz.TurnOn()
  36. }
  37. type protoToSocketOptFunc func([]*channelzpb.SocketOption) *channelz.SocketOptionData
  38. // protoToSocketOpt is used in function socketProtoToStruct to extract socket option
  39. // data from unmarshaled proto message.
  40. // It is only defined under linux, non-appengine environment on x86 architecture.
  41. var protoToSocketOpt protoToSocketOptFunc
  42. // emptyTime is used for detecting unset value of time.Time type.
  43. // For go1.7 and earlier, ptypes.Timestamp will fill in the loc field of time.Time
  44. // with &utcLoc. However zero value of a time.Time type value loc field is nil.
  45. // This behavior will make reflect.DeepEqual fail upon unset time.Time field,
  46. // and cause false positive fatal error.
  47. // TODO: Go1.7 is no longer supported - does this need a change?
  48. var emptyTime time.Time
  49. type dummyChannel struct {
  50. state connectivity.State
  51. target string
  52. callsStarted int64
  53. callsSucceeded int64
  54. callsFailed int64
  55. lastCallStartedTimestamp time.Time
  56. }
  57. func (d *dummyChannel) ChannelzMetric() *channelz.ChannelInternalMetric {
  58. return &channelz.ChannelInternalMetric{
  59. State: d.state,
  60. Target: d.target,
  61. CallsStarted: d.callsStarted,
  62. CallsSucceeded: d.callsSucceeded,
  63. CallsFailed: d.callsFailed,
  64. LastCallStartedTimestamp: d.lastCallStartedTimestamp,
  65. }
  66. }
  67. type dummyServer struct {
  68. callsStarted int64
  69. callsSucceeded int64
  70. callsFailed int64
  71. lastCallStartedTimestamp time.Time
  72. }
  73. func (d *dummyServer) ChannelzMetric() *channelz.ServerInternalMetric {
  74. return &channelz.ServerInternalMetric{
  75. CallsStarted: d.callsStarted,
  76. CallsSucceeded: d.callsSucceeded,
  77. CallsFailed: d.callsFailed,
  78. LastCallStartedTimestamp: d.lastCallStartedTimestamp,
  79. }
  80. }
  81. type dummySocket struct {
  82. streamsStarted int64
  83. streamsSucceeded int64
  84. streamsFailed int64
  85. messagesSent int64
  86. messagesReceived int64
  87. keepAlivesSent int64
  88. lastLocalStreamCreatedTimestamp time.Time
  89. lastRemoteStreamCreatedTimestamp time.Time
  90. lastMessageSentTimestamp time.Time
  91. lastMessageReceivedTimestamp time.Time
  92. localFlowControlWindow int64
  93. remoteFlowControlWindow int64
  94. socketOptions *channelz.SocketOptionData
  95. localAddr net.Addr
  96. remoteAddr net.Addr
  97. security credentials.ChannelzSecurityValue
  98. remoteName string
  99. }
  100. func (d *dummySocket) ChannelzMetric() *channelz.SocketInternalMetric {
  101. return &channelz.SocketInternalMetric{
  102. StreamsStarted: d.streamsStarted,
  103. StreamsSucceeded: d.streamsSucceeded,
  104. StreamsFailed: d.streamsFailed,
  105. MessagesSent: d.messagesSent,
  106. MessagesReceived: d.messagesReceived,
  107. KeepAlivesSent: d.keepAlivesSent,
  108. LastLocalStreamCreatedTimestamp: d.lastLocalStreamCreatedTimestamp,
  109. LastRemoteStreamCreatedTimestamp: d.lastRemoteStreamCreatedTimestamp,
  110. LastMessageSentTimestamp: d.lastMessageSentTimestamp,
  111. LastMessageReceivedTimestamp: d.lastMessageReceivedTimestamp,
  112. LocalFlowControlWindow: d.localFlowControlWindow,
  113. RemoteFlowControlWindow: d.remoteFlowControlWindow,
  114. SocketOptions: d.socketOptions,
  115. LocalAddr: d.localAddr,
  116. RemoteAddr: d.remoteAddr,
  117. Security: d.security,
  118. RemoteName: d.remoteName,
  119. }
  120. }
  121. func channelProtoToStruct(c *channelzpb.Channel) *dummyChannel {
  122. dc := &dummyChannel{}
  123. pdata := c.GetData()
  124. switch pdata.GetState().GetState() {
  125. case channelzpb.ChannelConnectivityState_UNKNOWN:
  126. // TODO: what should we set here?
  127. case channelzpb.ChannelConnectivityState_IDLE:
  128. dc.state = connectivity.Idle
  129. case channelzpb.ChannelConnectivityState_CONNECTING:
  130. dc.state = connectivity.Connecting
  131. case channelzpb.ChannelConnectivityState_READY:
  132. dc.state = connectivity.Ready
  133. case channelzpb.ChannelConnectivityState_TRANSIENT_FAILURE:
  134. dc.state = connectivity.TransientFailure
  135. case channelzpb.ChannelConnectivityState_SHUTDOWN:
  136. dc.state = connectivity.Shutdown
  137. }
  138. dc.target = pdata.GetTarget()
  139. dc.callsStarted = pdata.CallsStarted
  140. dc.callsSucceeded = pdata.CallsSucceeded
  141. dc.callsFailed = pdata.CallsFailed
  142. if t, err := ptypes.Timestamp(pdata.GetLastCallStartedTimestamp()); err == nil {
  143. if !t.Equal(emptyTime) {
  144. dc.lastCallStartedTimestamp = t
  145. }
  146. }
  147. return dc
  148. }
  149. func serverProtoToStruct(s *channelzpb.Server) *dummyServer {
  150. ds := &dummyServer{}
  151. pdata := s.GetData()
  152. ds.callsStarted = pdata.CallsStarted
  153. ds.callsSucceeded = pdata.CallsSucceeded
  154. ds.callsFailed = pdata.CallsFailed
  155. if t, err := ptypes.Timestamp(pdata.GetLastCallStartedTimestamp()); err == nil {
  156. if !t.Equal(emptyTime) {
  157. ds.lastCallStartedTimestamp = t
  158. }
  159. }
  160. return ds
  161. }
  162. func socketProtoToStruct(s *channelzpb.Socket) *dummySocket {
  163. ds := &dummySocket{}
  164. pdata := s.GetData()
  165. ds.streamsStarted = pdata.GetStreamsStarted()
  166. ds.streamsSucceeded = pdata.GetStreamsSucceeded()
  167. ds.streamsFailed = pdata.GetStreamsFailed()
  168. ds.messagesSent = pdata.GetMessagesSent()
  169. ds.messagesReceived = pdata.GetMessagesReceived()
  170. ds.keepAlivesSent = pdata.GetKeepAlivesSent()
  171. if t, err := ptypes.Timestamp(pdata.GetLastLocalStreamCreatedTimestamp()); err == nil {
  172. if !t.Equal(emptyTime) {
  173. ds.lastLocalStreamCreatedTimestamp = t
  174. }
  175. }
  176. if t, err := ptypes.Timestamp(pdata.GetLastRemoteStreamCreatedTimestamp()); err == nil {
  177. if !t.Equal(emptyTime) {
  178. ds.lastRemoteStreamCreatedTimestamp = t
  179. }
  180. }
  181. if t, err := ptypes.Timestamp(pdata.GetLastMessageSentTimestamp()); err == nil {
  182. if !t.Equal(emptyTime) {
  183. ds.lastMessageSentTimestamp = t
  184. }
  185. }
  186. if t, err := ptypes.Timestamp(pdata.GetLastMessageReceivedTimestamp()); err == nil {
  187. if !t.Equal(emptyTime) {
  188. ds.lastMessageReceivedTimestamp = t
  189. }
  190. }
  191. if v := pdata.GetLocalFlowControlWindow(); v != nil {
  192. ds.localFlowControlWindow = v.Value
  193. }
  194. if v := pdata.GetRemoteFlowControlWindow(); v != nil {
  195. ds.remoteFlowControlWindow = v.Value
  196. }
  197. if v := pdata.GetOption(); v != nil && protoToSocketOpt != nil {
  198. ds.socketOptions = protoToSocketOpt(v)
  199. }
  200. if v := s.GetSecurity(); v != nil {
  201. ds.security = protoToSecurity(v)
  202. }
  203. if local := s.GetLocal(); local != nil {
  204. ds.localAddr = protoToAddr(local)
  205. }
  206. if remote := s.GetRemote(); remote != nil {
  207. ds.remoteAddr = protoToAddr(remote)
  208. }
  209. ds.remoteName = s.GetRemoteName()
  210. return ds
  211. }
  212. func protoToSecurity(protoSecurity *channelzpb.Security) credentials.ChannelzSecurityValue {
  213. switch v := protoSecurity.Model.(type) {
  214. case *channelzpb.Security_Tls_:
  215. return &credentials.TLSChannelzSecurityValue{StandardName: v.Tls.GetStandardName(), LocalCertificate: v.Tls.GetLocalCertificate(), RemoteCertificate: v.Tls.GetRemoteCertificate()}
  216. case *channelzpb.Security_Other:
  217. sv := &credentials.OtherChannelzSecurityValue{Name: v.Other.GetName()}
  218. var x ptypes.DynamicAny
  219. if err := ptypes.UnmarshalAny(v.Other.GetValue(), &x); err == nil {
  220. sv.Value = x.Message
  221. }
  222. return sv
  223. }
  224. return nil
  225. }
  226. func protoToAddr(a *channelzpb.Address) net.Addr {
  227. switch v := a.Address.(type) {
  228. case *channelzpb.Address_TcpipAddress:
  229. if port := v.TcpipAddress.GetPort(); port != 0 {
  230. return &net.TCPAddr{IP: v.TcpipAddress.GetIpAddress(), Port: int(port)}
  231. }
  232. return &net.IPAddr{IP: v.TcpipAddress.GetIpAddress()}
  233. case *channelzpb.Address_UdsAddress_:
  234. return &net.UnixAddr{Name: v.UdsAddress.GetFilename(), Net: "unix"}
  235. case *channelzpb.Address_OtherAddress_:
  236. // TODO:
  237. }
  238. return nil
  239. }
  240. func convertSocketRefSliceToMap(sktRefs []*channelzpb.SocketRef) map[int64]string {
  241. m := make(map[int64]string)
  242. for _, sr := range sktRefs {
  243. m[sr.SocketId] = sr.Name
  244. }
  245. return m
  246. }
  247. type OtherSecurityValue struct {
  248. LocalCertificate []byte `protobuf:"bytes,1,opt,name=local_certificate,json=localCertificate,proto3" json:"local_certificate,omitempty"`
  249. RemoteCertificate []byte `protobuf:"bytes,2,opt,name=remote_certificate,json=remoteCertificate,proto3" json:"remote_certificate,omitempty"`
  250. }
  251. func (m *OtherSecurityValue) Reset() { *m = OtherSecurityValue{} }
  252. func (m *OtherSecurityValue) String() string { return proto.CompactTextString(m) }
  253. func (*OtherSecurityValue) ProtoMessage() {}
  254. func init() {
  255. // Ad-hoc registering the proto type here to facilitate UnmarshalAny of OtherSecurityValue.
  256. proto.RegisterType((*OtherSecurityValue)(nil), "grpc.credentials.OtherChannelzSecurityValue")
  257. }
  258. func TestGetTopChannels(t *testing.T) {
  259. tcs := []*dummyChannel{
  260. {
  261. state: connectivity.Connecting,
  262. target: "test.channelz:1234",
  263. callsStarted: 6,
  264. callsSucceeded: 2,
  265. callsFailed: 3,
  266. lastCallStartedTimestamp: time.Now().UTC(),
  267. },
  268. {
  269. state: connectivity.Connecting,
  270. target: "test.channelz:1234",
  271. callsStarted: 1,
  272. callsSucceeded: 2,
  273. callsFailed: 3,
  274. lastCallStartedTimestamp: time.Now().UTC(),
  275. },
  276. {
  277. state: connectivity.Shutdown,
  278. target: "test.channelz:8888",
  279. callsStarted: 0,
  280. callsSucceeded: 0,
  281. callsFailed: 0,
  282. },
  283. {},
  284. }
  285. channelz.NewChannelzStorage()
  286. for _, c := range tcs {
  287. channelz.RegisterChannel(c, 0, "")
  288. }
  289. s := newCZServer()
  290. resp, _ := s.GetTopChannels(context.Background(), &channelzpb.GetTopChannelsRequest{StartChannelId: 0})
  291. if !resp.GetEnd() {
  292. t.Fatalf("resp.GetEnd() want true, got %v", resp.GetEnd())
  293. }
  294. for i, c := range resp.GetChannel() {
  295. if !reflect.DeepEqual(channelProtoToStruct(c), tcs[i]) {
  296. t.Fatalf("dummyChannel: %d, want: %#v, got: %#v", i, tcs[i], channelProtoToStruct(c))
  297. }
  298. }
  299. for i := 0; i < 50; i++ {
  300. channelz.RegisterChannel(tcs[0], 0, "")
  301. }
  302. resp, _ = s.GetTopChannels(context.Background(), &channelzpb.GetTopChannelsRequest{StartChannelId: 0})
  303. if resp.GetEnd() {
  304. t.Fatalf("resp.GetEnd() want false, got %v", resp.GetEnd())
  305. }
  306. }
  307. func TestGetServers(t *testing.T) {
  308. ss := []*dummyServer{
  309. {
  310. callsStarted: 6,
  311. callsSucceeded: 2,
  312. callsFailed: 3,
  313. lastCallStartedTimestamp: time.Now().UTC(),
  314. },
  315. {
  316. callsStarted: 1,
  317. callsSucceeded: 2,
  318. callsFailed: 3,
  319. lastCallStartedTimestamp: time.Now().UTC(),
  320. },
  321. {
  322. callsStarted: 1,
  323. callsSucceeded: 0,
  324. callsFailed: 0,
  325. lastCallStartedTimestamp: time.Now().UTC(),
  326. },
  327. }
  328. channelz.NewChannelzStorage()
  329. for _, s := range ss {
  330. channelz.RegisterServer(s, "")
  331. }
  332. svr := newCZServer()
  333. resp, _ := svr.GetServers(context.Background(), &channelzpb.GetServersRequest{StartServerId: 0})
  334. if !resp.GetEnd() {
  335. t.Fatalf("resp.GetEnd() want true, got %v", resp.GetEnd())
  336. }
  337. for i, s := range resp.GetServer() {
  338. if !reflect.DeepEqual(serverProtoToStruct(s), ss[i]) {
  339. t.Fatalf("dummyServer: %d, want: %#v, got: %#v", i, ss[i], serverProtoToStruct(s))
  340. }
  341. }
  342. for i := 0; i < 50; i++ {
  343. channelz.RegisterServer(ss[0], "")
  344. }
  345. resp, _ = svr.GetServers(context.Background(), &channelzpb.GetServersRequest{StartServerId: 0})
  346. if resp.GetEnd() {
  347. t.Fatalf("resp.GetEnd() want false, got %v", resp.GetEnd())
  348. }
  349. }
  350. func TestGetServerSockets(t *testing.T) {
  351. channelz.NewChannelzStorage()
  352. svrID := channelz.RegisterServer(&dummyServer{}, "")
  353. refNames := []string{"listen socket 1", "normal socket 1", "normal socket 2"}
  354. ids := make([]int64, 3)
  355. ids[0] = channelz.RegisterListenSocket(&dummySocket{}, svrID, refNames[0])
  356. ids[1] = channelz.RegisterNormalSocket(&dummySocket{}, svrID, refNames[1])
  357. ids[2] = channelz.RegisterNormalSocket(&dummySocket{}, svrID, refNames[2])
  358. svr := newCZServer()
  359. resp, _ := svr.GetServerSockets(context.Background(), &channelzpb.GetServerSocketsRequest{ServerId: svrID, StartSocketId: 0})
  360. if !resp.GetEnd() {
  361. t.Fatalf("resp.GetEnd() want: true, got: %v", resp.GetEnd())
  362. }
  363. // GetServerSockets only return normal sockets.
  364. want := map[int64]string{
  365. ids[1]: refNames[1],
  366. ids[2]: refNames[2],
  367. }
  368. if !reflect.DeepEqual(convertSocketRefSliceToMap(resp.GetSocketRef()), want) {
  369. t.Fatalf("GetServerSockets want: %#v, got: %#v", want, resp.GetSocketRef())
  370. }
  371. for i := 0; i < 50; i++ {
  372. channelz.RegisterNormalSocket(&dummySocket{}, svrID, "")
  373. }
  374. resp, _ = svr.GetServerSockets(context.Background(), &channelzpb.GetServerSocketsRequest{ServerId: svrID, StartSocketId: 0})
  375. if resp.GetEnd() {
  376. t.Fatalf("resp.GetEnd() want false, got %v", resp.GetEnd())
  377. }
  378. }
  379. // This test makes a GetServerSockets with a non-zero start ID, and expect only
  380. // sockets with ID >= the given start ID.
  381. func TestGetServerSocketsNonZeroStartID(t *testing.T) {
  382. channelz.NewChannelzStorage()
  383. svrID := channelz.RegisterServer(&dummyServer{}, "")
  384. refNames := []string{"listen socket 1", "normal socket 1", "normal socket 2"}
  385. ids := make([]int64, 3)
  386. ids[0] = channelz.RegisterListenSocket(&dummySocket{}, svrID, refNames[0])
  387. ids[1] = channelz.RegisterNormalSocket(&dummySocket{}, svrID, refNames[1])
  388. ids[2] = channelz.RegisterNormalSocket(&dummySocket{}, svrID, refNames[2])
  389. svr := newCZServer()
  390. // Make GetServerSockets with startID = ids[1]+1, so socket-1 won't be
  391. // included in the response.
  392. resp, _ := svr.GetServerSockets(context.Background(), &channelzpb.GetServerSocketsRequest{ServerId: svrID, StartSocketId: ids[1] + 1})
  393. if !resp.GetEnd() {
  394. t.Fatalf("resp.GetEnd() want: true, got: %v", resp.GetEnd())
  395. }
  396. // GetServerSockets only return normal socket-2, socket-1 should be
  397. // filtered by start ID.
  398. want := map[int64]string{
  399. ids[2]: refNames[2],
  400. }
  401. if !reflect.DeepEqual(convertSocketRefSliceToMap(resp.GetSocketRef()), want) {
  402. t.Fatalf("GetServerSockets want: %#v, got: %#v", want, resp.GetSocketRef())
  403. }
  404. }
  405. func TestGetChannel(t *testing.T) {
  406. channelz.NewChannelzStorage()
  407. refNames := []string{"top channel 1", "nested channel 1", "sub channel 2", "nested channel 3"}
  408. ids := make([]int64, 4)
  409. ids[0] = channelz.RegisterChannel(&dummyChannel{}, 0, refNames[0])
  410. channelz.AddTraceEvent(ids[0], &channelz.TraceEventDesc{
  411. Desc: "Channel Created",
  412. Severity: channelz.CtINFO,
  413. })
  414. ids[1] = channelz.RegisterChannel(&dummyChannel{}, ids[0], refNames[1])
  415. channelz.AddTraceEvent(ids[1], &channelz.TraceEventDesc{
  416. Desc: "Channel Created",
  417. Severity: channelz.CtINFO,
  418. Parent: &channelz.TraceEventDesc{
  419. Desc: fmt.Sprintf("Nested Channel(id:%d) created", ids[1]),
  420. Severity: channelz.CtINFO,
  421. },
  422. })
  423. ids[2] = channelz.RegisterSubChannel(&dummyChannel{}, ids[0], refNames[2])
  424. channelz.AddTraceEvent(ids[2], &channelz.TraceEventDesc{
  425. Desc: "SubChannel Created",
  426. Severity: channelz.CtINFO,
  427. Parent: &channelz.TraceEventDesc{
  428. Desc: fmt.Sprintf("SubChannel(id:%d) created", ids[2]),
  429. Severity: channelz.CtINFO,
  430. },
  431. })
  432. ids[3] = channelz.RegisterChannel(&dummyChannel{}, ids[1], refNames[3])
  433. channelz.AddTraceEvent(ids[3], &channelz.TraceEventDesc{
  434. Desc: "Channel Created",
  435. Severity: channelz.CtINFO,
  436. Parent: &channelz.TraceEventDesc{
  437. Desc: fmt.Sprintf("Nested Channel(id:%d) created", ids[3]),
  438. Severity: channelz.CtINFO,
  439. },
  440. })
  441. channelz.AddTraceEvent(ids[0], &channelz.TraceEventDesc{
  442. Desc: fmt.Sprintf("Channel Connectivity change to %v", connectivity.Ready),
  443. Severity: channelz.CtINFO,
  444. })
  445. channelz.AddTraceEvent(ids[0], &channelz.TraceEventDesc{
  446. Desc: "Resolver returns an empty address list",
  447. Severity: channelz.CtWarning,
  448. })
  449. svr := newCZServer()
  450. resp, _ := svr.GetChannel(context.Background(), &channelzpb.GetChannelRequest{ChannelId: ids[0]})
  451. metrics := resp.GetChannel()
  452. subChans := metrics.GetSubchannelRef()
  453. if len(subChans) != 1 || subChans[0].GetName() != refNames[2] || subChans[0].GetSubchannelId() != ids[2] {
  454. t.Fatalf("metrics.GetSubChannelRef() want %#v, got %#v", []*channelzpb.SubchannelRef{{SubchannelId: ids[2], Name: refNames[2]}}, subChans)
  455. }
  456. nestedChans := metrics.GetChannelRef()
  457. if len(nestedChans) != 1 || nestedChans[0].GetName() != refNames[1] || nestedChans[0].GetChannelId() != ids[1] {
  458. t.Fatalf("metrics.GetChannelRef() want %#v, got %#v", []*channelzpb.ChannelRef{{ChannelId: ids[1], Name: refNames[1]}}, nestedChans)
  459. }
  460. trace := metrics.GetData().GetTrace()
  461. want := []struct {
  462. desc string
  463. severity channelzpb.ChannelTraceEvent_Severity
  464. childID int64
  465. childRef string
  466. }{
  467. {desc: "Channel Created", severity: channelzpb.ChannelTraceEvent_CT_INFO},
  468. {desc: fmt.Sprintf("Nested Channel(id:%d) created", ids[1]), severity: channelzpb.ChannelTraceEvent_CT_INFO, childID: ids[1], childRef: refNames[1]},
  469. {desc: fmt.Sprintf("SubChannel(id:%d) created", ids[2]), severity: channelzpb.ChannelTraceEvent_CT_INFO, childID: ids[2], childRef: refNames[2]},
  470. {desc: fmt.Sprintf("Channel Connectivity change to %v", connectivity.Ready), severity: channelzpb.ChannelTraceEvent_CT_INFO},
  471. {desc: "Resolver returns an empty address list", severity: channelzpb.ChannelTraceEvent_CT_WARNING},
  472. }
  473. for i, e := range trace.Events {
  474. if e.GetDescription() != want[i].desc {
  475. t.Fatalf("trace: GetDescription want %#v, got %#v", want[i].desc, e.GetDescription())
  476. }
  477. if e.GetSeverity() != want[i].severity {
  478. t.Fatalf("trace: GetSeverity want %#v, got %#v", want[i].severity, e.GetSeverity())
  479. }
  480. if want[i].childID == 0 && (e.GetChannelRef() != nil || e.GetSubchannelRef() != nil) {
  481. t.Fatalf("trace: GetChannelRef() should return nil, as there is no reference")
  482. }
  483. if e.GetChannelRef().GetChannelId() != want[i].childID || e.GetChannelRef().GetName() != want[i].childRef {
  484. if e.GetSubchannelRef().GetSubchannelId() != want[i].childID || e.GetSubchannelRef().GetName() != want[i].childRef {
  485. t.Fatalf("trace: GetChannelRef/GetSubchannelRef want (child ID: %d, child name: %q), got %#v and %#v", want[i].childID, want[i].childRef, e.GetChannelRef(), e.GetSubchannelRef())
  486. }
  487. }
  488. }
  489. resp, _ = svr.GetChannel(context.Background(), &channelzpb.GetChannelRequest{ChannelId: ids[1]})
  490. metrics = resp.GetChannel()
  491. nestedChans = metrics.GetChannelRef()
  492. if len(nestedChans) != 1 || nestedChans[0].GetName() != refNames[3] || nestedChans[0].GetChannelId() != ids[3] {
  493. t.Fatalf("metrics.GetChannelRef() want %#v, got %#v", []*channelzpb.ChannelRef{{ChannelId: ids[3], Name: refNames[3]}}, nestedChans)
  494. }
  495. }
  496. func TestGetSubChannel(t *testing.T) {
  497. var (
  498. subchanCreated = "SubChannel Created"
  499. subchanConnectivityChange = fmt.Sprintf("Subchannel Connectivity change to %v", connectivity.Ready)
  500. subChanPickNewAddress = fmt.Sprintf("Subchannel picks a new address %q to connect", "0.0.0.0")
  501. )
  502. channelz.NewChannelzStorage()
  503. refNames := []string{"top channel 1", "sub channel 1", "socket 1", "socket 2"}
  504. ids := make([]int64, 4)
  505. ids[0] = channelz.RegisterChannel(&dummyChannel{}, 0, refNames[0])
  506. channelz.AddTraceEvent(ids[0], &channelz.TraceEventDesc{
  507. Desc: "Channel Created",
  508. Severity: channelz.CtINFO,
  509. })
  510. ids[1] = channelz.RegisterSubChannel(&dummyChannel{}, ids[0], refNames[1])
  511. channelz.AddTraceEvent(ids[1], &channelz.TraceEventDesc{
  512. Desc: subchanCreated,
  513. Severity: channelz.CtINFO,
  514. Parent: &channelz.TraceEventDesc{
  515. Desc: fmt.Sprintf("Nested Channel(id:%d) created", ids[0]),
  516. Severity: channelz.CtINFO,
  517. },
  518. })
  519. ids[2] = channelz.RegisterNormalSocket(&dummySocket{}, ids[1], refNames[2])
  520. ids[3] = channelz.RegisterNormalSocket(&dummySocket{}, ids[1], refNames[3])
  521. channelz.AddTraceEvent(ids[1], &channelz.TraceEventDesc{
  522. Desc: subchanConnectivityChange,
  523. Severity: channelz.CtINFO,
  524. })
  525. channelz.AddTraceEvent(ids[1], &channelz.TraceEventDesc{
  526. Desc: subChanPickNewAddress,
  527. Severity: channelz.CtINFO,
  528. })
  529. svr := newCZServer()
  530. resp, _ := svr.GetSubchannel(context.Background(), &channelzpb.GetSubchannelRequest{SubchannelId: ids[1]})
  531. metrics := resp.GetSubchannel()
  532. want := map[int64]string{
  533. ids[2]: refNames[2],
  534. ids[3]: refNames[3],
  535. }
  536. if !reflect.DeepEqual(convertSocketRefSliceToMap(metrics.GetSocketRef()), want) {
  537. t.Fatalf("metrics.GetSocketRef() want %#v: got: %#v", want, metrics.GetSocketRef())
  538. }
  539. trace := metrics.GetData().GetTrace()
  540. wantTrace := []struct {
  541. desc string
  542. severity channelzpb.ChannelTraceEvent_Severity
  543. childID int64
  544. childRef string
  545. }{
  546. {desc: subchanCreated, severity: channelzpb.ChannelTraceEvent_CT_INFO},
  547. {desc: subchanConnectivityChange, severity: channelzpb.ChannelTraceEvent_CT_INFO},
  548. {desc: subChanPickNewAddress, severity: channelzpb.ChannelTraceEvent_CT_INFO},
  549. }
  550. for i, e := range trace.Events {
  551. if e.GetDescription() != wantTrace[i].desc {
  552. t.Fatalf("trace: GetDescription want %#v, got %#v", wantTrace[i].desc, e.GetDescription())
  553. }
  554. if e.GetSeverity() != wantTrace[i].severity {
  555. t.Fatalf("trace: GetSeverity want %#v, got %#v", wantTrace[i].severity, e.GetSeverity())
  556. }
  557. if wantTrace[i].childID == 0 && (e.GetChannelRef() != nil || e.GetSubchannelRef() != nil) {
  558. t.Fatalf("trace: GetChannelRef() should return nil, as there is no reference")
  559. }
  560. if e.GetChannelRef().GetChannelId() != wantTrace[i].childID || e.GetChannelRef().GetName() != wantTrace[i].childRef {
  561. if e.GetSubchannelRef().GetSubchannelId() != wantTrace[i].childID || e.GetSubchannelRef().GetName() != wantTrace[i].childRef {
  562. t.Fatalf("trace: GetChannelRef/GetSubchannelRef want (child ID: %d, child name: %q), got %#v and %#v", wantTrace[i].childID, wantTrace[i].childRef, e.GetChannelRef(), e.GetSubchannelRef())
  563. }
  564. }
  565. }
  566. }
  567. func TestGetSocket(t *testing.T) {
  568. channelz.NewChannelzStorage()
  569. ss := []*dummySocket{
  570. {
  571. streamsStarted: 10,
  572. streamsSucceeded: 2,
  573. streamsFailed: 3,
  574. messagesSent: 20,
  575. messagesReceived: 10,
  576. keepAlivesSent: 2,
  577. lastLocalStreamCreatedTimestamp: time.Now().UTC(),
  578. lastRemoteStreamCreatedTimestamp: time.Now().UTC(),
  579. lastMessageSentTimestamp: time.Now().UTC(),
  580. lastMessageReceivedTimestamp: time.Now().UTC(),
  581. localFlowControlWindow: 65536,
  582. remoteFlowControlWindow: 1024,
  583. localAddr: &net.TCPAddr{IP: net.ParseIP("1.0.0.1"), Port: 10001},
  584. remoteAddr: &net.TCPAddr{IP: net.ParseIP("12.0.0.1"), Port: 10002},
  585. remoteName: "remote.remote",
  586. },
  587. {
  588. streamsStarted: 10,
  589. streamsSucceeded: 2,
  590. streamsFailed: 3,
  591. messagesSent: 20,
  592. messagesReceived: 10,
  593. keepAlivesSent: 2,
  594. lastRemoteStreamCreatedTimestamp: time.Now().UTC(),
  595. lastMessageSentTimestamp: time.Now().UTC(),
  596. lastMessageReceivedTimestamp: time.Now().UTC(),
  597. localFlowControlWindow: 65536,
  598. remoteFlowControlWindow: 1024,
  599. localAddr: &net.UnixAddr{Name: "file.path", Net: "unix"},
  600. remoteAddr: &net.UnixAddr{Name: "another.path", Net: "unix"},
  601. remoteName: "remote.remote",
  602. },
  603. {
  604. streamsStarted: 5,
  605. streamsSucceeded: 2,
  606. streamsFailed: 3,
  607. messagesSent: 20,
  608. messagesReceived: 10,
  609. keepAlivesSent: 2,
  610. lastLocalStreamCreatedTimestamp: time.Now().UTC(),
  611. lastMessageSentTimestamp: time.Now().UTC(),
  612. lastMessageReceivedTimestamp: time.Now().UTC(),
  613. localFlowControlWindow: 65536,
  614. remoteFlowControlWindow: 10240,
  615. localAddr: &net.IPAddr{IP: net.ParseIP("1.0.0.1")},
  616. remoteAddr: &net.IPAddr{IP: net.ParseIP("9.0.0.1")},
  617. remoteName: "",
  618. },
  619. {
  620. localAddr: &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 10001},
  621. },
  622. {
  623. security: &credentials.TLSChannelzSecurityValue{
  624. StandardName: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
  625. RemoteCertificate: []byte{48, 130, 2, 156, 48, 130, 2, 5, 160},
  626. },
  627. },
  628. {
  629. security: &credentials.OtherChannelzSecurityValue{
  630. Name: "XXXX",
  631. },
  632. },
  633. {
  634. security: &credentials.OtherChannelzSecurityValue{
  635. Name: "YYYY",
  636. Value: &OtherSecurityValue{LocalCertificate: []byte{1, 2, 3}, RemoteCertificate: []byte{4, 5, 6}},
  637. },
  638. },
  639. }
  640. svr := newCZServer()
  641. ids := make([]int64, len(ss))
  642. svrID := channelz.RegisterServer(&dummyServer{}, "")
  643. for i, s := range ss {
  644. ids[i] = channelz.RegisterNormalSocket(s, svrID, strconv.Itoa(i))
  645. }
  646. for i, s := range ss {
  647. resp, _ := svr.GetSocket(context.Background(), &channelzpb.GetSocketRequest{SocketId: ids[i]})
  648. metrics := resp.GetSocket()
  649. if !reflect.DeepEqual(metrics.GetRef(), &channelzpb.SocketRef{SocketId: ids[i], Name: strconv.Itoa(i)}) || !reflect.DeepEqual(socketProtoToStruct(metrics), s) {
  650. t.Fatalf("resp.GetSocket() want: metrics.GetRef() = %#v and %#v, got: metrics.GetRef() = %#v and %#v", &channelzpb.SocketRef{SocketId: ids[i], Name: strconv.Itoa(i)}, s, metrics.GetRef(), socketProtoToStruct(metrics))
  651. }
  652. }
  653. }