diff --git a/src/BirdsiteLive.Twitter/Models/ApiStatistics.cs b/src/BirdsiteLive.Twitter/Models/ApiStatistics.cs index 55325ad..4d5b194 100644 --- a/src/BirdsiteLive.Twitter/Models/ApiStatistics.cs +++ b/src/BirdsiteLive.Twitter/Models/ApiStatistics.cs @@ -2,11 +2,17 @@ { public class ApiStatistics { - public int UserCallsCount { get; set; } + public int UserCallsCountMin { get; set; } + public int UserCallsCountAvg { get; set; } + public int UserCallsCountMax { get; set; } public int UserCallsMax { get; set; } - public int TweetCallsCount { get; set; } + public int TweetCallsCountMin { get; set; } + public int TweetCallsCountAvg { get; set; } + public int TweetCallsCountMax { get; set; } public int TweetCallsMax { get; set; } - public int TimelineCallsCount { get; set; } + public int TimelineCallsCountMin { get; set; } + public int TimelineCallsCountAvg { get; set; } + public int TimelineCallsCountMax { get; set; } public int TimelineCallsMax { get; set; } } } \ No newline at end of file diff --git a/src/BirdsiteLive.Twitter/Statistics/TwitterStatisticsHandler.cs b/src/BirdsiteLive.Twitter/Statistics/TwitterStatisticsHandler.cs index ef64fd1..afea0d0 100644 --- a/src/BirdsiteLive.Twitter/Statistics/TwitterStatisticsHandler.cs +++ b/src/BirdsiteLive.Twitter/Statistics/TwitterStatisticsHandler.cs @@ -1,4 +1,7 @@ -using System.Threading; +using System; +using System.Collections.Concurrent; +using System.Linq; +using System.Threading; using System.Timers; using BirdsiteLive.Twitter.Models; @@ -15,14 +18,12 @@ namespace BirdsiteLive.Statistics.Domain //Rate limits: https://developer.twitter.com/en/docs/twitter-api/v1/rate-limits public class TwitterStatisticsHandler : ITwitterStatisticsHandler { - private static int _previousUserCalls; - private static int _previousTweetCalls; - private static int _previousTimelineCalls; - private static int _userCalls; private static int _tweetCalls; private static int _timelineCalls; + private static ConcurrentDictionary _snapshots = new ConcurrentDictionary(); + private static System.Timers.Timer _resetTimer; #region Ctor @@ -40,13 +41,23 @@ namespace BirdsiteLive.Statistics.Domain private void OnTimeResetEvent(object sender, ElapsedEventArgs e) { - _previousUserCalls = _userCalls; - _previousTweetCalls = _tweetCalls; - _previousTimelineCalls = _timelineCalls; - + // Add snapshot + var snapshot = new ApiStatisticsSnapshot(_userCalls, _tweetCalls, _timelineCalls); + bool success; + do + { + success = _snapshots.TryAdd(snapshot.SnapshotDate, snapshot); + } while (!success); + + // Reset Interlocked.Exchange(ref _userCalls, 0); Interlocked.Exchange(ref _tweetCalls, 0); Interlocked.Exchange(ref _timelineCalls, 0); + + // Clean up + var now = DateTime.UtcNow; + var oldSnapshots = _snapshots.Keys.Where(x => (now - x).TotalHours > 24).ToList(); + foreach (var old in oldSnapshots) _snapshots.TryRemove(old, out var data); } public void CalledUserApi() //GET users/show - 900/15mins @@ -66,15 +77,44 @@ namespace BirdsiteLive.Statistics.Domain public ApiStatistics GetStatistics() { + var snapshots = _snapshots.Values.ToList(); + var userCalls = snapshots.Select(x => x.UserCalls).ToList(); + var tweetCalls = snapshots.Select(x => x.TweetCalls).ToList(); + var timelineCalls = snapshots.Select(x => x.TimelineCalls).ToList(); + return new ApiStatistics { - UserCallsCount = _previousUserCalls, + UserCallsCountMin = userCalls.Any() ? userCalls.Min() : 0, + UserCallsCountAvg = userCalls.Any() ? (int)userCalls.Average() : 0, + UserCallsCountMax = userCalls.Any() ? userCalls.Max() : 0, UserCallsMax = 900, - TweetCallsCount = _previousTweetCalls, + TweetCallsCountMin = tweetCalls.Any() ? tweetCalls.Min() : 0, + TweetCallsCountAvg = tweetCalls.Any() ? (int)tweetCalls.Average() : 0, + TweetCallsCountMax = tweetCalls.Any() ? tweetCalls.Max() : 0, TweetCallsMax = 300, - TimelineCallsCount = _previousTimelineCalls, + TimelineCallsCountMin = timelineCalls.Any() ? timelineCalls.Min() : 0, + TimelineCallsCountAvg = timelineCalls.Any() ? (int)timelineCalls.Average() : 0, + TimelineCallsCountMax = timelineCalls.Any() ? timelineCalls.Max() : 0, TimelineCallsMax = 1500 }; } } + + internal class ApiStatisticsSnapshot + { + #region Ctor + public ApiStatisticsSnapshot(int userCalls, int tweetCalls, int timelineCalls) + { + UserCalls = userCalls; + TweetCalls = tweetCalls; + TimelineCalls = timelineCalls; + SnapshotDate = DateTime.UtcNow; + } + #endregion + + public DateTime SnapshotDate { get; } + public int UserCalls { get; set; } + public int TweetCalls { get; set; } + public int TimelineCalls { get; set; } + } } \ No newline at end of file diff --git a/src/BirdsiteLive/Views/Statistics/Index.cshtml b/src/BirdsiteLive/Views/Statistics/Index.cshtml index 90a5e02..8b4f57a 100644 --- a/src/BirdsiteLive/Views/Statistics/Index.cshtml +++ b/src/BirdsiteLive/Views/Statistics/Index.cshtml @@ -12,9 +12,9 @@
  • Followers: @Model.FollowersCount
  • -

    Twitter API

    +

    Twitter API (Min, Avg, Max for the last 24h)

    \ No newline at end of file