public Task TrackAsync(DateTime date, string key, string?category, Counters counters, CancellationToken ct = default) { Guard.NotNull(key, nameof(key)); return(inner.TrackAsync(date, key, category, counters, ct)); }
public async Task Should_forward_track_call() { await sut.TrackAsync(key, "MyCategory", 123, 456); A.CallTo(() => inner.TrackAsync(key, "MyCategory", 123, 456)) .MustHaveHappened(); }
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var appFeature = context.HttpContext.Features.Get <IAppFeature>(); if (appFeature?.App != null && FilterDefinition.Weight > 0) { var stopWatch = Stopwatch.StartNew(); try { var plan = appPlanProvider.GetPlanForApp(appFeature.App); var usage = await usageTracker.GetMonthlyCalls(appFeature.App.Id.ToString(), DateTime.Today); if (plan.MaxApiCalls >= 0 && (usage * 1.1) > plan.MaxApiCalls) { context.Result = new StatusCodeResult(429); return; } await next(); } finally { stopWatch.Stop(); await usageTracker.TrackAsync(appFeature.App.Id.ToString(), FilterDefinition.Weight, stopWatch.ElapsedMilliseconds); } } else { await next(); } }
public async Task Should_return_429_status_code_if_max_calls_over_limit() { sut.FilterDefinition = new ApiCostsAttribute(1); SetupApp(); apiCallsCurrent = 1000; apiCallsMax = 600; await sut.OnActionExecutionAsync(actionContext, next); Assert.Equal(429, (actionContext.Result as StatusCodeResult)?.StatusCode); Assert.False(isNextCalled); A.CallTo(() => usageTracker.TrackAsync(A <string> .Ignored, A <string> .Ignored, A <double> .Ignored, A <double> .Ignored)) .MustNotHaveHappened(); }
public async Task Should_forward_track_call() { var counters = new Counters(); await sut.TrackAsync(date, key, "my-category", counters); A.CallTo(() => inner.TrackAsync(date, key, "my-category", counters)) .MustHaveHappened(); }
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { context.HttpContext.Features.Set <IApiCostsFeature>(FilterDefinition); var app = context.HttpContext.Context().App; if (app != null) { var appId = app.Id.ToString(); if (FilterDefinition.Weight > 0) { using (Profiler.Trace("CheckUsage")) { var plan = appPlansProvider.GetPlanForApp(app); var usage = await usageTracker.GetMonthlyCallsAsync(appId, DateTime.Today); if (plan?.MaxApiCalls >= 0 && usage > plan.MaxApiCalls * 1.1) { context.Result = new StatusCodeResult(429); return; } } } var watch = ValueStopwatch.StartNew(); try { await next(); } finally { var elapsedMs = watch.Stop(); await appLogStore.LogAsync(app.Id, clock.GetCurrentInstant(), context.HttpContext.Request.Method, context.HttpContext.Request.Path, context.HttpContext.User.OpenIdSubject(), context.HttpContext.User.OpenIdClientId(), elapsedMs, FilterDefinition.Weight); if (FilterDefinition.Weight > 0) { await usageTracker.TrackAsync(appId, context.HttpContext.User.OpenIdClientId(), FilterDefinition.Weight, elapsedMs); } } } else { await next(); } }
public Task TrackAsync(DateTime date, string key, string?category, double weight, long elapsedMs, long bytes) { var apiKey = GetKey(key); var counters = new Counters { [CounterTotalCalls] = weight, [CounterTotalElapsedMs] = elapsedMs, [CounterTotalBytes] = bytes }; return(usageTracker.TrackAsync(date, apiKey, category, counters)); }
public async Task Invoke(HttpContext context) { var stopWatch = Stopwatch.StartNew(); await next(context); var appFeature = context.Features.Get <IAppFeature>(); if (appFeature?.App != null) { stopWatch.Stop(); var weight = context.Features.Get <IAppTrackingWeightFeature>()?.Weight ?? 1; await usageTracker.TrackAsync(appFeature.App.Id.ToString(), weight, stopWatch.ElapsedMilliseconds); } }
public async Task Should_track_usage() { Counters?measuredCounters = null; A.CallTo(() => usageTracker.TrackAsync(date, $"{key}_API", null, A <Counters> .Ignored, ct)) .Invokes(args => { measuredCounters = args.GetArgument <Counters>(3) !; }); await sut.TrackAsync(date, key, null, 4, 120, 1024, ct); measuredCounters.Should().BeEquivalentTo(new Counters { [ApiUsageTracker.CounterTotalBytes] = 1024, [ApiUsageTracker.CounterTotalCalls] = 4, [ApiUsageTracker.CounterTotalElapsedMs] = 120 }); }
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var appFeature = context.HttpContext.Features.Get <IAppFeature>(); if (appFeature?.App != null && FilterDefinition.Weight > 0) { using (Profiler.Trace("CheckUsage")) { var plan = appPlanProvider.GetPlanForApp(appFeature.App); var usage = await usageTracker.GetMonthlyCallsAsync(appFeature.App.Id.ToString(), DateTime.Today); if (plan.MaxApiCalls >= 0 && usage > plan.MaxApiCalls * 1.1) { context.Result = new StatusCodeResult(429); return; } } var watch = ValueStopwatch.StartNew(); try { await next(); } finally { var elapsedMs = watch.Stop(); await usageTracker.TrackAsync(appFeature.App.Id.ToString(), context.HttpContext.User.OpenIdClientId(), FilterDefinition.Weight, elapsedMs); } } else { await next(); } }
public Task TrackAsync(string key, string category, double weight, double elapsedMs) { return(inner.TrackAsync(key, category, weight, elapsedMs)); }
public Task TrackAsync(DateTime date, string key, string?category, Counters counters) { Guard.NotNull(key, nameof(key)); return(inner.TrackAsync(date, key, category, counters)); }
public Task TrackAsync(string key, string?category, double weight, double elapsedMs) { Guard.NotNull(key); return(inner.TrackAsync(key, category, weight, elapsedMs)); }