mirror of https://github.com/Squidex/squidex.git
26 changed files with 512 additions and 235 deletions
@ -1,92 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// AppUsageController.cs
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex Group
|
|
||||
// All rights reserved.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System; |
|
||||
using System.Linq; |
|
||||
using System.Threading.Tasks; |
|
||||
using Microsoft.AspNetCore.Authorization; |
|
||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using NSwag.Annotations; |
|
||||
using Squidex.Controllers.Api.Apps.Models; |
|
||||
using Squidex.Core.Identity; |
|
||||
using Squidex.Infrastructure.CQRS.Commands; |
|
||||
using Squidex.Infrastructure.UsageTracking; |
|
||||
using Squidex.Pipeline; |
|
||||
|
|
||||
namespace Squidex.Controllers.Api.Apps |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Retrieves usage information for apps.
|
|
||||
/// </summary>
|
|
||||
[ApiExceptionFilter] |
|
||||
[ServiceFilter(typeof(AppFilterAttribute))] |
|
||||
[SwaggerTag("Apps")] |
|
||||
public class AppUsageController : ControllerBase |
|
||||
{ |
|
||||
private readonly IUsageTracker usageTracker; |
|
||||
|
|
||||
public AppUsageController(ICommandBus commandBus, IUsageTracker usageTracker) |
|
||||
: base(commandBus) |
|
||||
{ |
|
||||
this.usageTracker = usageTracker; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Get api calls for this month.
|
|
||||
/// </summary>
|
|
||||
/// <param name="app">The name of the app.</param>
|
|
||||
/// <returns>
|
|
||||
/// 200 => Usage tracking results returned.
|
|
||||
/// 404 => App not found.
|
|
||||
/// </returns>
|
|
||||
[Authorize(Roles = SquidexRoles.AppEditor)] |
|
||||
[HttpGet] |
|
||||
[Route("apps/{app}/usages/monthly")] |
|
||||
[ProducesResponseType(typeof(MonthlyCallsDto), 200)] |
|
||||
public async Task<IActionResult> GetMonthlyCalls(string app) |
|
||||
{ |
|
||||
var count = await usageTracker.GetMonthlyCalls(App.Id.ToString(), DateTime.Today); |
|
||||
|
|
||||
return Ok(new MonthlyCallsDto { Count = count }); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Get api calls in date range.
|
|
||||
/// </summary>
|
|
||||
/// <param name="app">The name of the app.</param>
|
|
||||
/// <param name="fromDate">The from date.</param>
|
|
||||
/// <param name="toDate">The to date.</param>
|
|
||||
/// <returns>
|
|
||||
/// 200 => Usage tracking results returned.
|
|
||||
/// 404 => App not found.
|
|
||||
/// 400 => Range between from date and to date is not valid or has more than 100 days.
|
|
||||
/// </returns>
|
|
||||
[Authorize(Roles = SquidexRoles.AppEditor)] |
|
||||
[HttpGet] |
|
||||
[Route("apps/{app}/usages/{fromDate}/{toDate}")] |
|
||||
[ProducesResponseType(typeof(UsageDto[]), 200)] |
|
||||
public async Task<IActionResult> GetUsages(string app, DateTime fromDate, DateTime toDate) |
|
||||
{ |
|
||||
if (fromDate > toDate && (toDate - fromDate).TotalDays > 100) |
|
||||
{ |
|
||||
return BadRequest(); |
|
||||
} |
|
||||
|
|
||||
var entities = await usageTracker.FindAsync(App.Id.ToString(), fromDate.Date, toDate.Date); |
|
||||
|
|
||||
var models = entities.Select(x => |
|
||||
{ |
|
||||
var averageMs = x.TotalCount == 0 ? 0 : x.TotalElapsedMs / x.TotalCount; |
|
||||
|
|
||||
return new UsageDto { Date = x.Date, Count = x.TotalCount, AverageMs = averageMs }; |
|
||||
}).ToList(); |
|
||||
|
|
||||
return Ok(models); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,14 +1,14 @@ |
|||||
// ==========================================================================
|
// ==========================================================================
|
||||
// MonthlyCallsDto.cs
|
// CurrentCallsDto.cs
|
||||
// Squidex Headless CMS
|
// Squidex Headless CMS
|
||||
// ==========================================================================
|
// ==========================================================================
|
||||
// Copyright (c) Squidex Group
|
// Copyright (c) Squidex Group
|
||||
// All rights reserved.
|
// All rights reserved.
|
||||
// ==========================================================================
|
// ==========================================================================
|
||||
|
|
||||
namespace Squidex.Controllers.Api.Apps.Models |
namespace Squidex.Controllers.Api.Statistics.Models |
||||
{ |
{ |
||||
public class MonthlyCallsDto |
public class CurrentCallsDto |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// The number of calls.
|
/// The number of calls.
|
||||
@ -0,0 +1,18 @@ |
|||||
|
// ==========================================================================
|
||||
|
// CurrentStorageDto.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
namespace Squidex.Controllers.Api.Statistics.Models |
||||
|
{ |
||||
|
public class CurrentStorageDto |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The size in bytes.
|
||||
|
/// </summary>
|
||||
|
public long Size { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
// ==========================================================================
|
||||
|
// StorageUsageDto.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
|
||||
|
namespace Squidex.Controllers.Api.Statistics.Models |
||||
|
{ |
||||
|
public class StorageUsageDto |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The date when the usage was tracked.
|
||||
|
/// </summary>
|
||||
|
public DateTime Date { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The number of assets.
|
||||
|
/// </summary>
|
||||
|
public long Count { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The size in bytes.
|
||||
|
/// </summary>
|
||||
|
public long Size { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,144 @@ |
|||||
|
// ==========================================================================
|
||||
|
// UsagesController.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using NSwag.Annotations; |
||||
|
using Squidex.Controllers.Api.Statistics.Models; |
||||
|
using Squidex.Core.Identity; |
||||
|
using Squidex.Infrastructure.CQRS.Commands; |
||||
|
using Squidex.Infrastructure.UsageTracking; |
||||
|
using Squidex.Pipeline; |
||||
|
using Squidex.Read.Assets.Repositories; |
||||
|
|
||||
|
namespace Squidex.Controllers.Api.Statistics |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Retrieves usage information for apps.
|
||||
|
/// </summary>
|
||||
|
[ApiExceptionFilter] |
||||
|
[ServiceFilter(typeof(AppFilterAttribute))] |
||||
|
[SwaggerTag("Statistics")] |
||||
|
public class UsagesController : ControllerBase |
||||
|
{ |
||||
|
private readonly IUsageTracker usageTracker; |
||||
|
private readonly IAssetStatsRepository assetStatsRepository; |
||||
|
|
||||
|
public UsagesController(ICommandBus commandBus, IUsageTracker usageTracker, IAssetStatsRepository assetStatsRepository) |
||||
|
: base(commandBus) |
||||
|
{ |
||||
|
this.usageTracker = usageTracker; |
||||
|
|
||||
|
this.assetStatsRepository = assetStatsRepository; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Get api calls for this month.
|
||||
|
/// </summary>
|
||||
|
/// <param name="app">The name of the app.</param>
|
||||
|
/// <returns>
|
||||
|
/// 200 => Usage tracking results returned.
|
||||
|
/// 404 => App not found.
|
||||
|
/// </returns>
|
||||
|
[Authorize(Roles = SquidexRoles.AppEditor)] |
||||
|
[HttpGet] |
||||
|
[Route("apps/{app}/usages/calls/month")] |
||||
|
[ProducesResponseType(typeof(CurrentCallsDto), 200)] |
||||
|
public async Task<IActionResult> GetMonthlyCalls(string app) |
||||
|
{ |
||||
|
var count = await usageTracker.GetMonthlyCalls(App.Id.ToString(), DateTime.Today); |
||||
|
|
||||
|
return Ok(new CurrentCallsDto { Count = count }); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Get api calls in date range.
|
||||
|
/// </summary>
|
||||
|
/// <param name="app">The name of the app.</param>
|
||||
|
/// <param name="fromDate">The from date.</param>
|
||||
|
/// <param name="toDate">The to date.</param>
|
||||
|
/// <returns>
|
||||
|
/// 200 => API call returned.
|
||||
|
/// 404 => App not found.
|
||||
|
/// 400 => Range between from date and to date is not valid or has more than 100 days.
|
||||
|
/// </returns>
|
||||
|
[Authorize(Roles = SquidexRoles.AppEditor)] |
||||
|
[HttpGet] |
||||
|
[Route("apps/{app}/usages/calls/{fromDate}/{toDate}")] |
||||
|
[ProducesResponseType(typeof(CallsUsageDto[]), 200)] |
||||
|
public async Task<IActionResult> GetUsages(string app, DateTime fromDate, DateTime toDate) |
||||
|
{ |
||||
|
if (fromDate > toDate && (toDate - fromDate).TotalDays > 100) |
||||
|
{ |
||||
|
return BadRequest(); |
||||
|
} |
||||
|
|
||||
|
var entities = await usageTracker.QueryAsync(App.Id.ToString(), fromDate.Date, toDate.Date); |
||||
|
|
||||
|
var models = entities.Select(x => |
||||
|
{ |
||||
|
var averageMs = x.TotalCount == 0 ? 0 : x.TotalElapsedMs / x.TotalCount; |
||||
|
|
||||
|
return new CallsUsageDto { Date = x.Date, Count = x.TotalCount, AverageMs = averageMs }; |
||||
|
}).ToList(); |
||||
|
|
||||
|
return Ok(models); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Get current size of all assets for today.
|
||||
|
/// </summary>
|
||||
|
/// <param name="app">The name of the app.</param>
|
||||
|
/// <returns>
|
||||
|
/// 200 => Storage usage returned.
|
||||
|
/// 404 => App not found.
|
||||
|
/// </returns>
|
||||
|
[Authorize(Roles = SquidexRoles.AppEditor)] |
||||
|
[HttpGet] |
||||
|
[Route("apps/{app}/usages/storage/today")] |
||||
|
[ProducesResponseType(typeof(CurrentStorageDto), 200)] |
||||
|
public async Task<IActionResult> GetCurrentStorageSize(string app) |
||||
|
{ |
||||
|
var size = await assetStatsRepository.GetTotalSizeAsync(App.Id); |
||||
|
|
||||
|
return Ok(new CurrentStorageDto { Size = size }); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Get storage usage in date range.
|
||||
|
/// </summary>
|
||||
|
/// <param name="app">The name of the app.</param>
|
||||
|
/// <param name="fromDate">The from date.</param>
|
||||
|
/// <param name="toDate">The to date.</param>
|
||||
|
/// <returns>
|
||||
|
/// 200 => Storage usage returned.
|
||||
|
/// 404 => App not found.
|
||||
|
/// 400 => Range between from date and to date is not valid or has more than 100 days.
|
||||
|
/// </returns>
|
||||
|
[Authorize(Roles = SquidexRoles.AppEditor)] |
||||
|
[HttpGet] |
||||
|
[Route("apps/{app}/usages/storage/{fromDate}/{toDate}")] |
||||
|
[ProducesResponseType(typeof(StorageUsageDto[]), 200)] |
||||
|
public async Task<IActionResult> GetStorageSizes(string app, DateTime fromDate, DateTime toDate) |
||||
|
{ |
||||
|
if (fromDate > toDate && (toDate - fromDate).TotalDays > 100) |
||||
|
{ |
||||
|
return BadRequest(); |
||||
|
} |
||||
|
|
||||
|
var entities = await assetStatsRepository.QueryAsync(App.Id, fromDate.Date, toDate.Date); |
||||
|
|
||||
|
var models = entities.Select(x => new StorageUsageDto { Date = x.Date, Count = x.TotalCount, Size = x.TotalSize }).ToList(); |
||||
|
|
||||
|
return Ok(models); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue