@@ -781,6 +781,18 @@ func (a *agent) reportConnectionsLoop(ctx context.Context, aAPI proto.DRPCAgentC
781781 }
782782}
783783
784+ const (
785+ // reportConnectionBufferLimit limits the number of connection reports we
786+ // buffer to avoid growing the buffer indefinitely. This should not happen
787+ // unless the agent has lost connection to coderd for a long time or if
788+ // the agent is being spammed with connections.
789+ //
790+ // If we assume ~150 byte per connection report, this would be around 300KB
791+ // of memory which seems acceptable. We could reduce this if necessary by
792+ // not using the proto struct directly.
793+ reportConnectionBufferLimit = 2048
794+ )
795+
784796func (a * agent ) reportConnection (id uuid.UUID , connectionType proto.Connection_Type , ip string ) (disconnected func (code int , reason string )) {
785797 // If the experiment hasn't been enabled, we don't report connections.
786798 if ! a .experimentalConnectionReports {
@@ -797,25 +809,45 @@ func (a *agent) reportConnection(id uuid.UUID, connectionType proto.Connection_T
797809
798810 a .reportConnectionsMu .Lock ()
799811 defer a .reportConnectionsMu .Unlock ()
800- a .reportConnections = append (a .reportConnections , & proto.ReportConnectionRequest {
801- Connection : & proto.Connection {
802- Id : id [:],
803- Action : proto .Connection_CONNECT ,
804- Type : connectionType ,
805- Timestamp : timestamppb .New (time .Now ()),
806- Ip : ip ,
807- StatusCode : 0 ,
808- Reason : nil ,
809- },
810- })
811- select {
812- case a .reportConnectionsUpdate <- struct {}{}:
813- default :
812+
813+ if len (a .reportConnections ) >= reportConnectionBufferLimit {
814+ a .logger .Warn (a .hardCtx , "connection report buffer limit reached, dropping connect" ,
815+ slog .F ("limit" , reportConnectionBufferLimit ),
816+ slog .F ("connection_id" , id ),
817+ slog .F ("connection_type" , connectionType ),
818+ slog .F ("ip" , ip ),
819+ )
820+ } else {
821+ a .reportConnections = append (a .reportConnections , & proto.ReportConnectionRequest {
822+ Connection : & proto.Connection {
823+ Id : id [:],
824+ Action : proto .Connection_CONNECT ,
825+ Type : connectionType ,
826+ Timestamp : timestamppb .New (time .Now ()),
827+ Ip : ip ,
828+ StatusCode : 0 ,
829+ Reason : nil ,
830+ },
831+ })
832+ select {
833+ case a .reportConnectionsUpdate <- struct {}{}:
834+ default :
835+ }
814836 }
815837
816838 return func (code int , reason string ) {
817839 a .reportConnectionsMu .Lock ()
818840 defer a .reportConnectionsMu .Unlock ()
841+ if len (a .reportConnections ) >= reportConnectionBufferLimit {
842+ a .logger .Warn (a .hardCtx , "connection report buffer limit reached, dropping connect" ,
843+ slog .F ("limit" , reportConnectionBufferLimit ),
844+ slog .F ("connection_id" , id ),
845+ slog .F ("connection_type" , connectionType ),
846+ slog .F ("ip" , ip ),
847+ )
848+ return
849+ }
850+
819851 a .reportConnections = append (a .reportConnections , & proto.ReportConnectionRequest {
820852 Connection : & proto.Connection {
821853 Id : id [:],
0 commit comments