@@ -7,11 +7,14 @@ namespace SpacetimeDB
77{
88 public class NetworkRequestTracker
99 {
10- private readonly ConcurrentQueue < ( DateTime End , TimeSpan Duration , string Metadata ) > _requestDurations = new ( ) ;
10+ private readonly ConcurrentQueue < ( DateTime End , ( TimeSpan Duration , string Metadata ) Request ) > _requestDurations = new ( ) ;
1111
1212 private uint _nextRequestId ;
1313 private readonly Dictionary < uint , ( DateTime Start , string Metadata ) > _requests = new ( ) ;
1414
15+ // Limit the number of request durations we store to prevent memory leaks.
16+ public int KeepLastSeconds = 5 * 60 ;
17+
1518 internal uint StartTrackingRequest ( string metadata = "" )
1619 {
1720 // Record the start time of the request
@@ -40,9 +43,25 @@ internal bool FinishTrackingRequest(uint requestId)
4043 return true ;
4144 }
4245
46+ private IEnumerable < ( TimeSpan Duration , string Metadata ) > GetRequestDurations ( int lastSeconds )
47+ {
48+ var cutoff = DateTime . UtcNow . AddSeconds ( - lastSeconds ) ;
49+ return _requestDurations . SkipWhile ( x => x . End < cutoff ) . Select ( x => x . Request ) ;
50+ }
51+
4352 internal void InsertRequest ( TimeSpan duration , string metadata )
4453 {
45- _requestDurations . Enqueue ( ( DateTime . UtcNow , duration , metadata ) ) ;
54+ lock ( _requestDurations )
55+ {
56+ // Remove expired entries, we need to do this atomically.
57+ var cutoff = DateTime . UtcNow . AddSeconds ( - KeepLastSeconds ) ;
58+ var removeCount = _requestDurations . TakeWhile ( x => x . End < cutoff ) . Count ( ) ;
59+ for ( var i = 0 ; i < removeCount ; i ++ )
60+ {
61+ _requestDurations . TryDequeue ( out _ ) ;
62+ }
63+ _requestDurations . Enqueue ( ( DateTime . UtcNow , ( duration , metadata ) ) ) ;
64+ }
4665 }
4766
4867 internal void InsertRequest ( DateTime start , string metadata )
@@ -52,8 +71,13 @@ internal void InsertRequest(DateTime start, string metadata)
5271
5372 public ( ( TimeSpan Duration , string Metadata ) Min , ( TimeSpan Duration , string Metadata ) Max ) ? GetMinMaxTimes ( int lastSeconds )
5473 {
74+ if ( lastSeconds > KeepLastSeconds )
75+ {
76+ throw new ArgumentException ( $ "lastSeconds must be less than or equal to KeepLastSeconds = { KeepLastSeconds } ", nameof ( lastSeconds ) ) ;
77+ }
78+
5579 var cutoff = DateTime . UtcNow . AddSeconds ( - lastSeconds ) ;
56- var requestDurations = _requestDurations . Where ( x => x . End >= cutoff ) . Select ( x => ( x . Duration , x . Metadata ) ) ;
80+ var requestDurations = _requestDurations . SkipWhile ( x => x . End < cutoff ) . Select ( x => x . Request ) ;
5781
5882 if ( ! requestDurations . Any ( ) )
5983 {
@@ -74,5 +98,14 @@ public class Stats
7498 public readonly NetworkRequestTracker SubscriptionRequestTracker = new ( ) ;
7599 public readonly NetworkRequestTracker AllReducersTracker = new ( ) ;
76100 public readonly NetworkRequestTracker ParseMessageTracker = new ( ) ;
101+
102+ public void KeepLastSeconds ( int seconds )
103+ {
104+ ReducerRequestTracker . KeepLastSeconds = seconds ;
105+ OneOffRequestTracker . KeepLastSeconds = seconds ;
106+ SubscriptionRequestTracker . KeepLastSeconds = seconds ;
107+ AllReducersTracker . KeepLastSeconds = seconds ;
108+ ParseMessageTracker . KeepLastSeconds = seconds ;
109+ }
77110 }
78111}
0 commit comments