@@ -781,6 +781,18 @@ func (a *agent) reportConnectionsLoop(ctx context.Context, aAPI proto.DRPCAgentC
781
781
}
782
782
}
783
783
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
+
784
796
func (a * agent ) reportConnection (id uuid.UUID , connectionType proto.Connection_Type , ip string ) (disconnected func (code int , reason string )) {
785
797
// If the experiment hasn't been enabled, we don't report connections.
786
798
if ! a .experimentalConnectionReports {
@@ -797,25 +809,45 @@ func (a *agent) reportConnection(id uuid.UUID, connectionType proto.Connection_T
797
809
798
810
a .reportConnectionsMu .Lock ()
799
811
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
+ }
814
836
}
815
837
816
838
return func (code int , reason string ) {
817
839
a .reportConnectionsMu .Lock ()
818
840
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
+
819
851
a .reportConnections = append (a .reportConnections , & proto.ReportConnectionRequest {
820
852
Connection : & proto.Connection {
821
853
Id : id [:],
0 commit comments