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
19package channelz
20
21import (
22 "fmt"
23 "sync/atomic"
24)
25
26// Server is the channelz representation of a server.
27type Server struct {
28 Entity
29 ID int64
30 RefName string
31
32 ServerMetrics ServerMetrics
33
34 closeCalled bool
35 sockets map[int64]string
36 listenSockets map[int64]string
37 cm *channelMap
38}
39
40// ServerMetrics defines a struct containing metrics for servers.
41type ServerMetrics struct {
42 // The number of incoming calls started on the server.
43 CallsStarted atomic.Int64
44 // The number of incoming calls that have completed with an OK status.
45 CallsSucceeded atomic.Int64
46 // The number of incoming calls that have a completed with a non-OK status.
47 CallsFailed atomic.Int64
48 // The last time a call was started on the server.
49 LastCallStartedTimestamp atomic.Int64
50}
51
52// NewServerMetricsForTesting returns an initialized ServerMetrics.
53func NewServerMetricsForTesting(started, succeeded, failed, timestamp int64) *ServerMetrics {
54 sm := &ServerMetrics{}
55 sm.CallsStarted.Store(started)
56 sm.CallsSucceeded.Store(succeeded)
57 sm.CallsFailed.Store(failed)
58 sm.LastCallStartedTimestamp.Store(timestamp)
59 return sm
60}
61
62// CopyFrom copies the metrics data from the provided ServerMetrics
63// instance into the current instance.
64func (sm *ServerMetrics) CopyFrom(o *ServerMetrics) {
65 sm.CallsStarted.Store(o.CallsStarted.Load())
66 sm.CallsSucceeded.Store(o.CallsSucceeded.Load())
67 sm.CallsFailed.Store(o.CallsFailed.Load())
68 sm.LastCallStartedTimestamp.Store(o.LastCallStartedTimestamp.Load())
69}
70
71// ListenSockets returns the listening sockets for s.
72func (s *Server) ListenSockets() map[int64]string {
73 db.mu.RLock()
74 defer db.mu.RUnlock()
75 return copyMap(s.listenSockets)
76}
77
78// String returns a printable description of s.
79func (s *Server) String() string {
80 return fmt.Sprintf("Server #%d", s.ID)
81}
82
83func (s *Server) id() int64 {
84 return s.ID
85}
86
87func (s *Server) addChild(id int64, e entry) {
88 switch v := e.(type) {
89 case *Socket:
90 switch v.SocketType {
91 case SocketTypeNormal:
92 s.sockets[id] = v.RefName
93 case SocketTypeListen:
94 s.listenSockets[id] = v.RefName
95 }
96 default:
97 logger.Errorf("cannot add a child (id = %d) of type %T to a server", id, e)
98 }
99}
100
101func (s *Server) deleteChild(id int64) {
102 delete(s.sockets, id)
103 delete(s.listenSockets, id)
104 s.deleteSelfIfReady()
105}
106
107func (s *Server) triggerDelete() {
108 s.closeCalled = true
109 s.deleteSelfIfReady()
110}
111
112func (s *Server) deleteSelfIfReady() {
113 if !s.closeCalled || len(s.sockets)+len(s.listenSockets) != 0 {
114 return
115 }
116 s.cm.deleteEntry(s.ID)
117}
118
119func (s *Server) getParentID() int64 {
120 return 0
121}