funcs.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  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 channelz defines APIs for enabling channelz service, entry
  19. // registration/deletion, and accessing channelz data. It also defines channelz
  20. // metric struct formats.
  21. //
  22. // All APIs in this package are experimental.
  23. package channelz
  24. import (
  25. "errors"
  26. "sort"
  27. "sync"
  28. "sync/atomic"
  29. "time"
  30. "google.golang.org/grpc/grpclog"
  31. )
  32. const (
  33. defaultMaxTraceEntry int32 = 30
  34. )
  35. var (
  36. // IDGen is the global channelz entity ID generator. It should not be used
  37. // outside this package except by tests.
  38. IDGen IDGenerator
  39. db dbWrapper
  40. // EntryPerPage defines the number of channelz entries to be shown on a web page.
  41. EntryPerPage = int64(50)
  42. curState int32
  43. maxTraceEntry = defaultMaxTraceEntry
  44. )
  45. // TurnOn turns on channelz data collection.
  46. func TurnOn() {
  47. if !IsOn() {
  48. db.set(newChannelMap())
  49. IDGen.Reset()
  50. atomic.StoreInt32(&curState, 1)
  51. }
  52. }
  53. // IsOn returns whether channelz data collection is on.
  54. func IsOn() bool {
  55. return atomic.LoadInt32(&curState) == 1
  56. }
  57. // SetMaxTraceEntry sets maximum number of trace entry per entity (i.e. channel/subchannel).
  58. // Setting it to 0 will disable channel tracing.
  59. func SetMaxTraceEntry(i int32) {
  60. atomic.StoreInt32(&maxTraceEntry, i)
  61. }
  62. // ResetMaxTraceEntryToDefault resets the maximum number of trace entry per entity to default.
  63. func ResetMaxTraceEntryToDefault() {
  64. atomic.StoreInt32(&maxTraceEntry, defaultMaxTraceEntry)
  65. }
  66. func getMaxTraceEntry() int {
  67. i := atomic.LoadInt32(&maxTraceEntry)
  68. return int(i)
  69. }
  70. // dbWarpper wraps around a reference to internal channelz data storage, and
  71. // provide synchronized functionality to set and get the reference.
  72. type dbWrapper struct {
  73. mu sync.RWMutex
  74. DB *channelMap
  75. }
  76. func (d *dbWrapper) set(db *channelMap) {
  77. d.mu.Lock()
  78. d.DB = db
  79. d.mu.Unlock()
  80. }
  81. func (d *dbWrapper) get() *channelMap {
  82. d.mu.RLock()
  83. defer d.mu.RUnlock()
  84. return d.DB
  85. }
  86. // GetTopChannels returns a slice of top channel's ChannelMetric, along with a
  87. // boolean indicating whether there's more top channels to be queried for.
  88. //
  89. // The arg id specifies that only top channel with id at or above it will be included
  90. // in the result. The returned slice is up to a length of the arg maxResults or
  91. // EntryPerPage if maxResults is zero, and is sorted in ascending id order.
  92. func GetTopChannels(id int64, maxResults int64) ([]*ChannelMetric, bool) {
  93. return db.get().GetTopChannels(id, maxResults)
  94. }
  95. // GetServers returns a slice of server's ServerMetric, along with a
  96. // boolean indicating whether there's more servers to be queried for.
  97. //
  98. // The arg id specifies that only server with id at or above it will be included
  99. // in the result. The returned slice is up to a length of the arg maxResults or
  100. // EntryPerPage if maxResults is zero, and is sorted in ascending id order.
  101. func GetServers(id int64, maxResults int64) ([]*ServerMetric, bool) {
  102. return db.get().GetServers(id, maxResults)
  103. }
  104. // GetServerSockets returns a slice of server's (identified by id) normal socket's
  105. // SocketMetric, along with a boolean indicating whether there's more sockets to
  106. // be queried for.
  107. //
  108. // The arg startID specifies that only sockets with id at or above it will be
  109. // included in the result. The returned slice is up to a length of the arg maxResults
  110. // or EntryPerPage if maxResults is zero, and is sorted in ascending id order.
  111. func GetServerSockets(id int64, startID int64, maxResults int64) ([]*SocketMetric, bool) {
  112. return db.get().GetServerSockets(id, startID, maxResults)
  113. }
  114. // GetChannel returns the ChannelMetric for the channel (identified by id).
  115. func GetChannel(id int64) *ChannelMetric {
  116. return db.get().GetChannel(id)
  117. }
  118. // GetSubChannel returns the SubChannelMetric for the subchannel (identified by id).
  119. func GetSubChannel(id int64) *SubChannelMetric {
  120. return db.get().GetSubChannel(id)
  121. }
  122. // GetSocket returns the SocketInternalMetric for the socket (identified by id).
  123. func GetSocket(id int64) *SocketMetric {
  124. return db.get().GetSocket(id)
  125. }
  126. // GetServer returns the ServerMetric for the server (identified by id).
  127. func GetServer(id int64) *ServerMetric {
  128. return db.get().GetServer(id)
  129. }
  130. // RegisterChannel registers the given channel c in the channelz database with
  131. // ref as its reference name, and adds it to the child list of its parent
  132. // (identified by pid). pid == nil means no parent.
  133. //
  134. // Returns a unique channelz identifier assigned to this channel.
  135. //
  136. // If channelz is not turned ON, the channelz database is not mutated.
  137. func RegisterChannel(c Channel, pid *Identifier, ref string) *Identifier {
  138. id := IDGen.genID()
  139. var parent int64
  140. isTopChannel := true
  141. if pid != nil {
  142. isTopChannel = false
  143. parent = pid.Int()
  144. }
  145. if !IsOn() {
  146. return newIdentifer(RefChannel, id, pid)
  147. }
  148. cn := &channel{
  149. refName: ref,
  150. c: c,
  151. subChans: make(map[int64]string),
  152. nestedChans: make(map[int64]string),
  153. id: id,
  154. pid: parent,
  155. trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
  156. }
  157. db.get().addChannel(id, cn, isTopChannel, parent)
  158. return newIdentifer(RefChannel, id, pid)
  159. }
  160. // RegisterSubChannel registers the given subChannel c in the channelz database
  161. // with ref as its reference name, and adds it to the child list of its parent
  162. // (identified by pid).
  163. //
  164. // Returns a unique channelz identifier assigned to this subChannel.
  165. //
  166. // If channelz is not turned ON, the channelz database is not mutated.
  167. func RegisterSubChannel(c Channel, pid *Identifier, ref string) (*Identifier, error) {
  168. if pid == nil {
  169. return nil, errors.New("a SubChannel's parent id cannot be nil")
  170. }
  171. id := IDGen.genID()
  172. if !IsOn() {
  173. return newIdentifer(RefSubChannel, id, pid), nil
  174. }
  175. sc := &subChannel{
  176. refName: ref,
  177. c: c,
  178. sockets: make(map[int64]string),
  179. id: id,
  180. pid: pid.Int(),
  181. trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
  182. }
  183. db.get().addSubChannel(id, sc, pid.Int())
  184. return newIdentifer(RefSubChannel, id, pid), nil
  185. }
  186. // RegisterServer registers the given server s in channelz database. It returns
  187. // the unique channelz tracking id assigned to this server.
  188. //
  189. // If channelz is not turned ON, the channelz database is not mutated.
  190. func RegisterServer(s Server, ref string) *Identifier {
  191. id := IDGen.genID()
  192. if !IsOn() {
  193. return newIdentifer(RefServer, id, nil)
  194. }
  195. svr := &server{
  196. refName: ref,
  197. s: s,
  198. sockets: make(map[int64]string),
  199. listenSockets: make(map[int64]string),
  200. id: id,
  201. }
  202. db.get().addServer(id, svr)
  203. return newIdentifer(RefServer, id, nil)
  204. }
  205. // RegisterListenSocket registers the given listen socket s in channelz database
  206. // with ref as its reference name, and add it to the child list of its parent
  207. // (identified by pid). It returns the unique channelz tracking id assigned to
  208. // this listen socket.
  209. //
  210. // If channelz is not turned ON, the channelz database is not mutated.
  211. func RegisterListenSocket(s Socket, pid *Identifier, ref string) (*Identifier, error) {
  212. if pid == nil {
  213. return nil, errors.New("a ListenSocket's parent id cannot be 0")
  214. }
  215. id := IDGen.genID()
  216. if !IsOn() {
  217. return newIdentifer(RefListenSocket, id, pid), nil
  218. }
  219. ls := &listenSocket{refName: ref, s: s, id: id, pid: pid.Int()}
  220. db.get().addListenSocket(id, ls, pid.Int())
  221. return newIdentifer(RefListenSocket, id, pid), nil
  222. }
  223. // RegisterNormalSocket registers the given normal socket s in channelz database
  224. // with ref as its reference name, and adds it to the child list of its parent
  225. // (identified by pid). It returns the unique channelz tracking id assigned to
  226. // this normal socket.
  227. //
  228. // If channelz is not turned ON, the channelz database is not mutated.
  229. func RegisterNormalSocket(s Socket, pid *Identifier, ref string) (*Identifier, error) {
  230. if pid == nil {
  231. return nil, errors.New("a NormalSocket's parent id cannot be 0")
  232. }
  233. id := IDGen.genID()
  234. if !IsOn() {
  235. return newIdentifer(RefNormalSocket, id, pid), nil
  236. }
  237. ns := &normalSocket{refName: ref, s: s, id: id, pid: pid.Int()}
  238. db.get().addNormalSocket(id, ns, pid.Int())
  239. return newIdentifer(RefNormalSocket, id, pid), nil
  240. }
  241. // RemoveEntry removes an entry with unique channelz tracking id to be id from
  242. // channelz database.
  243. //
  244. // If channelz is not turned ON, this function is a no-op.
  245. func RemoveEntry(id *Identifier) {
  246. if !IsOn() {
  247. return
  248. }
  249. db.get().removeEntry(id.Int())
  250. }
  251. // TraceEventDesc is what the caller of AddTraceEvent should provide to describe
  252. // the event to be added to the channel trace.
  253. //
  254. // The Parent field is optional. It is used for an event that will be recorded
  255. // in the entity's parent trace.
  256. type TraceEventDesc struct {
  257. Desc string
  258. Severity Severity
  259. Parent *TraceEventDesc
  260. }
  261. // AddTraceEvent adds trace related to the entity with specified id, using the
  262. // provided TraceEventDesc.
  263. //
  264. // If channelz is not turned ON, this will simply log the event descriptions.
  265. func AddTraceEvent(l grpclog.DepthLoggerV2, id *Identifier, depth int, desc *TraceEventDesc) {
  266. // Log only the trace description associated with the bottom most entity.
  267. switch desc.Severity {
  268. case CtUnknown, CtInfo:
  269. l.InfoDepth(depth+1, withParens(id)+desc.Desc)
  270. case CtWarning:
  271. l.WarningDepth(depth+1, withParens(id)+desc.Desc)
  272. case CtError:
  273. l.ErrorDepth(depth+1, withParens(id)+desc.Desc)
  274. }
  275. if getMaxTraceEntry() == 0 {
  276. return
  277. }
  278. if IsOn() {
  279. db.get().traceEvent(id.Int(), desc)
  280. }
  281. }
  282. // channelMap is the storage data structure for channelz.
  283. // Methods of channelMap can be divided in two two categories with respect to locking.
  284. // 1. Methods acquire the global lock.
  285. // 2. Methods that can only be called when global lock is held.
  286. // A second type of method need always to be called inside a first type of method.
  287. type channelMap struct {
  288. mu sync.RWMutex
  289. topLevelChannels map[int64]struct{}
  290. servers map[int64]*server
  291. channels map[int64]*channel
  292. subChannels map[int64]*subChannel
  293. listenSockets map[int64]*listenSocket
  294. normalSockets map[int64]*normalSocket
  295. }
  296. func newChannelMap() *channelMap {
  297. return &channelMap{
  298. topLevelChannels: make(map[int64]struct{}),
  299. channels: make(map[int64]*channel),
  300. listenSockets: make(map[int64]*listenSocket),
  301. normalSockets: make(map[int64]*normalSocket),
  302. servers: make(map[int64]*server),
  303. subChannels: make(map[int64]*subChannel),
  304. }
  305. }
  306. func (c *channelMap) addServer(id int64, s *server) {
  307. c.mu.Lock()
  308. s.cm = c
  309. c.servers[id] = s
  310. c.mu.Unlock()
  311. }
  312. func (c *channelMap) addChannel(id int64, cn *channel, isTopChannel bool, pid int64) {
  313. c.mu.Lock()
  314. cn.cm = c
  315. cn.trace.cm = c
  316. c.channels[id] = cn
  317. if isTopChannel {
  318. c.topLevelChannels[id] = struct{}{}
  319. } else {
  320. c.findEntry(pid).addChild(id, cn)
  321. }
  322. c.mu.Unlock()
  323. }
  324. func (c *channelMap) addSubChannel(id int64, sc *subChannel, pid int64) {
  325. c.mu.Lock()
  326. sc.cm = c
  327. sc.trace.cm = c
  328. c.subChannels[id] = sc
  329. c.findEntry(pid).addChild(id, sc)
  330. c.mu.Unlock()
  331. }
  332. func (c *channelMap) addListenSocket(id int64, ls *listenSocket, pid int64) {
  333. c.mu.Lock()
  334. ls.cm = c
  335. c.listenSockets[id] = ls
  336. c.findEntry(pid).addChild(id, ls)
  337. c.mu.Unlock()
  338. }
  339. func (c *channelMap) addNormalSocket(id int64, ns *normalSocket, pid int64) {
  340. c.mu.Lock()
  341. ns.cm = c
  342. c.normalSockets[id] = ns
  343. c.findEntry(pid).addChild(id, ns)
  344. c.mu.Unlock()
  345. }
  346. // removeEntry triggers the removal of an entry, which may not indeed delete the entry, if it has to
  347. // wait on the deletion of its children and until no other entity's channel trace references it.
  348. // It may lead to a chain of entry deletion. For example, deleting the last socket of a gracefully
  349. // shutting down server will lead to the server being also deleted.
  350. func (c *channelMap) removeEntry(id int64) {
  351. c.mu.Lock()
  352. c.findEntry(id).triggerDelete()
  353. c.mu.Unlock()
  354. }
  355. // c.mu must be held by the caller
  356. func (c *channelMap) decrTraceRefCount(id int64) {
  357. e := c.findEntry(id)
  358. if v, ok := e.(tracedChannel); ok {
  359. v.decrTraceRefCount()
  360. e.deleteSelfIfReady()
  361. }
  362. }
  363. // c.mu must be held by the caller.
  364. func (c *channelMap) findEntry(id int64) entry {
  365. var v entry
  366. var ok bool
  367. if v, ok = c.channels[id]; ok {
  368. return v
  369. }
  370. if v, ok = c.subChannels[id]; ok {
  371. return v
  372. }
  373. if v, ok = c.servers[id]; ok {
  374. return v
  375. }
  376. if v, ok = c.listenSockets[id]; ok {
  377. return v
  378. }
  379. if v, ok = c.normalSockets[id]; ok {
  380. return v
  381. }
  382. return &dummyEntry{idNotFound: id}
  383. }
  384. // c.mu must be held by the caller
  385. // deleteEntry simply deletes an entry from the channelMap. Before calling this
  386. // method, caller must check this entry is ready to be deleted, i.e removeEntry()
  387. // has been called on it, and no children still exist.
  388. // Conditionals are ordered by the expected frequency of deletion of each entity
  389. // type, in order to optimize performance.
  390. func (c *channelMap) deleteEntry(id int64) {
  391. var ok bool
  392. if _, ok = c.normalSockets[id]; ok {
  393. delete(c.normalSockets, id)
  394. return
  395. }
  396. if _, ok = c.subChannels[id]; ok {
  397. delete(c.subChannels, id)
  398. return
  399. }
  400. if _, ok = c.channels[id]; ok {
  401. delete(c.channels, id)
  402. delete(c.topLevelChannels, id)
  403. return
  404. }
  405. if _, ok = c.listenSockets[id]; ok {
  406. delete(c.listenSockets, id)
  407. return
  408. }
  409. if _, ok = c.servers[id]; ok {
  410. delete(c.servers, id)
  411. return
  412. }
  413. }
  414. func (c *channelMap) traceEvent(id int64, desc *TraceEventDesc) {
  415. c.mu.Lock()
  416. child := c.findEntry(id)
  417. childTC, ok := child.(tracedChannel)
  418. if !ok {
  419. c.mu.Unlock()
  420. return
  421. }
  422. childTC.getChannelTrace().append(&TraceEvent{Desc: desc.Desc, Severity: desc.Severity, Timestamp: time.Now()})
  423. if desc.Parent != nil {
  424. parent := c.findEntry(child.getParentID())
  425. var chanType RefChannelType
  426. switch child.(type) {
  427. case *channel:
  428. chanType = RefChannel
  429. case *subChannel:
  430. chanType = RefSubChannel
  431. }
  432. if parentTC, ok := parent.(tracedChannel); ok {
  433. parentTC.getChannelTrace().append(&TraceEvent{
  434. Desc: desc.Parent.Desc,
  435. Severity: desc.Parent.Severity,
  436. Timestamp: time.Now(),
  437. RefID: id,
  438. RefName: childTC.getRefName(),
  439. RefType: chanType,
  440. })
  441. childTC.incrTraceRefCount()
  442. }
  443. }
  444. c.mu.Unlock()
  445. }
  446. type int64Slice []int64
  447. func (s int64Slice) Len() int { return len(s) }
  448. func (s int64Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  449. func (s int64Slice) Less(i, j int) bool { return s[i] < s[j] }
  450. func copyMap(m map[int64]string) map[int64]string {
  451. n := make(map[int64]string)
  452. for k, v := range m {
  453. n[k] = v
  454. }
  455. return n
  456. }
  457. func min(a, b int64) int64 {
  458. if a < b {
  459. return a
  460. }
  461. return b
  462. }
  463. func (c *channelMap) GetTopChannels(id int64, maxResults int64) ([]*ChannelMetric, bool) {
  464. if maxResults <= 0 {
  465. maxResults = EntryPerPage
  466. }
  467. c.mu.RLock()
  468. l := int64(len(c.topLevelChannels))
  469. ids := make([]int64, 0, l)
  470. cns := make([]*channel, 0, min(l, maxResults))
  471. for k := range c.topLevelChannels {
  472. ids = append(ids, k)
  473. }
  474. sort.Sort(int64Slice(ids))
  475. idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
  476. count := int64(0)
  477. var end bool
  478. var t []*ChannelMetric
  479. for i, v := range ids[idx:] {
  480. if count == maxResults {
  481. break
  482. }
  483. if cn, ok := c.channels[v]; ok {
  484. cns = append(cns, cn)
  485. t = append(t, &ChannelMetric{
  486. NestedChans: copyMap(cn.nestedChans),
  487. SubChans: copyMap(cn.subChans),
  488. })
  489. count++
  490. }
  491. if i == len(ids[idx:])-1 {
  492. end = true
  493. break
  494. }
  495. }
  496. c.mu.RUnlock()
  497. if count == 0 {
  498. end = true
  499. }
  500. for i, cn := range cns {
  501. t[i].ChannelData = cn.c.ChannelzMetric()
  502. t[i].ID = cn.id
  503. t[i].RefName = cn.refName
  504. t[i].Trace = cn.trace.dumpData()
  505. }
  506. return t, end
  507. }
  508. func (c *channelMap) GetServers(id, maxResults int64) ([]*ServerMetric, bool) {
  509. if maxResults <= 0 {
  510. maxResults = EntryPerPage
  511. }
  512. c.mu.RLock()
  513. l := int64(len(c.servers))
  514. ids := make([]int64, 0, l)
  515. ss := make([]*server, 0, min(l, maxResults))
  516. for k := range c.servers {
  517. ids = append(ids, k)
  518. }
  519. sort.Sort(int64Slice(ids))
  520. idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
  521. count := int64(0)
  522. var end bool
  523. var s []*ServerMetric
  524. for i, v := range ids[idx:] {
  525. if count == maxResults {
  526. break
  527. }
  528. if svr, ok := c.servers[v]; ok {
  529. ss = append(ss, svr)
  530. s = append(s, &ServerMetric{
  531. ListenSockets: copyMap(svr.listenSockets),
  532. })
  533. count++
  534. }
  535. if i == len(ids[idx:])-1 {
  536. end = true
  537. break
  538. }
  539. }
  540. c.mu.RUnlock()
  541. if count == 0 {
  542. end = true
  543. }
  544. for i, svr := range ss {
  545. s[i].ServerData = svr.s.ChannelzMetric()
  546. s[i].ID = svr.id
  547. s[i].RefName = svr.refName
  548. }
  549. return s, end
  550. }
  551. func (c *channelMap) GetServerSockets(id int64, startID int64, maxResults int64) ([]*SocketMetric, bool) {
  552. if maxResults <= 0 {
  553. maxResults = EntryPerPage
  554. }
  555. var svr *server
  556. var ok bool
  557. c.mu.RLock()
  558. if svr, ok = c.servers[id]; !ok {
  559. // server with id doesn't exist.
  560. c.mu.RUnlock()
  561. return nil, true
  562. }
  563. svrskts := svr.sockets
  564. l := int64(len(svrskts))
  565. ids := make([]int64, 0, l)
  566. sks := make([]*normalSocket, 0, min(l, maxResults))
  567. for k := range svrskts {
  568. ids = append(ids, k)
  569. }
  570. sort.Sort(int64Slice(ids))
  571. idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= startID })
  572. count := int64(0)
  573. var end bool
  574. for i, v := range ids[idx:] {
  575. if count == maxResults {
  576. break
  577. }
  578. if ns, ok := c.normalSockets[v]; ok {
  579. sks = append(sks, ns)
  580. count++
  581. }
  582. if i == len(ids[idx:])-1 {
  583. end = true
  584. break
  585. }
  586. }
  587. c.mu.RUnlock()
  588. if count == 0 {
  589. end = true
  590. }
  591. s := make([]*SocketMetric, 0, len(sks))
  592. for _, ns := range sks {
  593. sm := &SocketMetric{}
  594. sm.SocketData = ns.s.ChannelzMetric()
  595. sm.ID = ns.id
  596. sm.RefName = ns.refName
  597. s = append(s, sm)
  598. }
  599. return s, end
  600. }
  601. func (c *channelMap) GetChannel(id int64) *ChannelMetric {
  602. cm := &ChannelMetric{}
  603. var cn *channel
  604. var ok bool
  605. c.mu.RLock()
  606. if cn, ok = c.channels[id]; !ok {
  607. // channel with id doesn't exist.
  608. c.mu.RUnlock()
  609. return nil
  610. }
  611. cm.NestedChans = copyMap(cn.nestedChans)
  612. cm.SubChans = copyMap(cn.subChans)
  613. // cn.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of cn.c when
  614. // holding the lock to prevent potential data race.
  615. chanCopy := cn.c
  616. c.mu.RUnlock()
  617. cm.ChannelData = chanCopy.ChannelzMetric()
  618. cm.ID = cn.id
  619. cm.RefName = cn.refName
  620. cm.Trace = cn.trace.dumpData()
  621. return cm
  622. }
  623. func (c *channelMap) GetSubChannel(id int64) *SubChannelMetric {
  624. cm := &SubChannelMetric{}
  625. var sc *subChannel
  626. var ok bool
  627. c.mu.RLock()
  628. if sc, ok = c.subChannels[id]; !ok {
  629. // subchannel with id doesn't exist.
  630. c.mu.RUnlock()
  631. return nil
  632. }
  633. cm.Sockets = copyMap(sc.sockets)
  634. // sc.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of sc.c when
  635. // holding the lock to prevent potential data race.
  636. chanCopy := sc.c
  637. c.mu.RUnlock()
  638. cm.ChannelData = chanCopy.ChannelzMetric()
  639. cm.ID = sc.id
  640. cm.RefName = sc.refName
  641. cm.Trace = sc.trace.dumpData()
  642. return cm
  643. }
  644. func (c *channelMap) GetSocket(id int64) *SocketMetric {
  645. sm := &SocketMetric{}
  646. c.mu.RLock()
  647. if ls, ok := c.listenSockets[id]; ok {
  648. c.mu.RUnlock()
  649. sm.SocketData = ls.s.ChannelzMetric()
  650. sm.ID = ls.id
  651. sm.RefName = ls.refName
  652. return sm
  653. }
  654. if ns, ok := c.normalSockets[id]; ok {
  655. c.mu.RUnlock()
  656. sm.SocketData = ns.s.ChannelzMetric()
  657. sm.ID = ns.id
  658. sm.RefName = ns.refName
  659. return sm
  660. }
  661. c.mu.RUnlock()
  662. return nil
  663. }
  664. func (c *channelMap) GetServer(id int64) *ServerMetric {
  665. sm := &ServerMetric{}
  666. var svr *server
  667. var ok bool
  668. c.mu.RLock()
  669. if svr, ok = c.servers[id]; !ok {
  670. c.mu.RUnlock()
  671. return nil
  672. }
  673. sm.ListenSockets = copyMap(svr.listenSockets)
  674. c.mu.RUnlock()
  675. sm.ID = svr.id
  676. sm.RefName = svr.refName
  677. sm.ServerData = svr.s.ChannelzMetric()
  678. return sm
  679. }
  680. // IDGenerator is an incrementing atomic that tracks IDs for channelz entities.
  681. type IDGenerator struct {
  682. id int64
  683. }
  684. // Reset resets the generated ID back to zero. Should only be used at
  685. // initialization or by tests sensitive to the ID number.
  686. func (i *IDGenerator) Reset() {
  687. atomic.StoreInt64(&i.id, 0)
  688. }
  689. func (i *IDGenerator) genID() int64 {
  690. return atomic.AddInt64(&i.id, 1)
  691. }