/* * * Copyright 2024 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package channelz import ( "fmt" "net" "sync/atomic" "google.golang.org/grpc/credentials" ) // SocketMetrics defines the struct that the implementor of Socket interface // should return from ChannelzMetric(). type SocketMetrics struct { // The number of streams that have been started. StreamsStarted atomic.Int64 // The number of streams that have ended successfully: // On client side, receiving frame with eos bit set. // On server side, sending frame with eos bit set. StreamsSucceeded atomic.Int64 // The number of streams that have ended unsuccessfully: // On client side, termination without receiving frame with eos bit set. // On server side, termination without sending frame with eos bit set. StreamsFailed atomic.Int64 // The number of messages successfully sent on this socket. MessagesSent atomic.Int64 MessagesReceived atomic.Int64 // The number of keep alives sent. This is typically implemented with HTTP/2 // ping messages. KeepAlivesSent atomic.Int64 // The last time a stream was created by this endpoint. Usually unset for // servers. LastLocalStreamCreatedTimestamp atomic.Int64 // The last time a stream was created by the remote endpoint. Usually unset // for clients. LastRemoteStreamCreatedTimestamp atomic.Int64 // The last time a message was sent by this endpoint. LastMessageSentTimestamp atomic.Int64 // The last time a message was received by this endpoint. LastMessageReceivedTimestamp atomic.Int64 } // EphemeralSocketMetrics are metrics that change rapidly and are tracked // outside of channelz. type EphemeralSocketMetrics struct { // The amount of window, granted to the local endpoint by the remote endpoint. // This may be slightly out of date due to network latency. This does NOT // include stream level or TCP level flow control info. LocalFlowControlWindow int64 // The amount of window, granted to the remote endpoint by the local endpoint. // This may be slightly out of date due to network latency. This does NOT // include stream level or TCP level flow control info. RemoteFlowControlWindow int64 } // SocketType represents the type of socket. type SocketType string // SocketType can be one of these. const ( SocketTypeNormal = "NormalSocket" SocketTypeListen = "ListenSocket" ) // Socket represents a socket within channelz which includes socket // metrics and data related to socket activity and provides methods // for managing and interacting with sockets. type Socket struct { Entity SocketType SocketType ID int64 Parent Entity cm *channelMap SocketMetrics SocketMetrics EphemeralMetrics func() *EphemeralSocketMetrics RefName string // The locally bound address. Immutable. LocalAddr net.Addr // The remote bound address. May be absent. Immutable. RemoteAddr net.Addr // Optional, represents the name of the remote endpoint, if different than // the original target name. Immutable. RemoteName string // Immutable. SocketOptions *SocketOptionData // Immutable. Security credentials.ChannelzSecurityValue } // String returns a string representation of the Socket, including its parent // entity, socket type, and ID. func (ls *Socket) String() string { return fmt.Sprintf("%s %s #%d", ls.Parent, ls.SocketType, ls.ID) } func (ls *Socket) id() int64 { return ls.ID } func (ls *Socket) addChild(id int64, e entry) { logger.Errorf("cannot add a child (id = %d) of type %T to a listen socket", id, e) } func (ls *Socket) deleteChild(id int64) { logger.Errorf("cannot delete a child (id = %d) from a listen socket", id) } func (ls *Socket) triggerDelete() { ls.cm.deleteEntry(ls.ID) ls.Parent.(entry).deleteChild(ls.ID) } func (ls *Socket) deleteSelfIfReady() { logger.Errorf("cannot call deleteSelfIfReady on a listen socket") } func (ls *Socket) getParentID() int64 { return ls.Parent.id() }