Skip to content

Add stats endpoint used for dashboards#453

Merged
Flaminel merged 2 commits intomainfrom
add_stats_endpoint
Feb 21, 2026
Merged

Add stats endpoint used for dashboards#453
Flaminel merged 2 commits intomainfrom
add_stats_endpoint

Conversation

@Flaminel
Copy link
Contributor

@Flaminel Flaminel commented Feb 20, 2026

Relates to #250

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new authenticated /api/stats endpoint intended for dashboard integrations by aggregating event/strike/job-run statistics and exposing cached health status for download clients and arr instances.

Changes:

  • Introduces StatsService + response DTOs and wires them into DI.
  • Adds StatsController (GET /api/stats?hours=...) and removes the old /api/events/stats endpoint.
  • Extends health checking to include arr instances and updates docs for the new stats API.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
docs/docs/configuration/stats/index.mdx New documentation page describing auth, query params, and response fields for /api/stats.
code/backend/Cleanuparr.Infrastructure/Stats/StatsService.cs Aggregates stats from Events DB + job scheduler + cached health service.
code/backend/Cleanuparr.Infrastructure/Stats/StatsResponse.cs Adds the stats response contract/DTOs returned by the API.
code/backend/Cleanuparr.Infrastructure/Stats/IStatsService.cs Defines the stats aggregation interface.
code/backend/Cleanuparr.Infrastructure/Health/IHealthCheckService.cs Extends health service contract to support arr instance health checks.
code/backend/Cleanuparr.Infrastructure/Health/HealthCheckService.cs Implements arr instance health checks and caching.
code/backend/Cleanuparr.Infrastructure/Health/HealthCheckBackgroundService.cs Periodically checks both download clients and arr instances.
code/backend/Cleanuparr.Infrastructure/Health/ArrHealthStatus.cs Adds arr instance health status model.
code/backend/Cleanuparr.Api/DependencyInjection/ServicesDI.cs Registers IStatsService in API DI.
code/backend/Cleanuparr.Api/Controllers/StatsController.cs New /api/stats controller endpoint with clamped hours.
code/backend/Cleanuparr.Api/Controllers/EventsController.cs Removes the legacy /api/events/stats endpoint.
Comments suppressed due to low confidence (5)

code/backend/Cleanuparr.Api/Controllers/EventsController.cs:156

  • The /api/events/stats endpoint was removed here, but the Angular frontend still calls it (code/frontend/src/app/core/api/events.api.ts#getEventStats). This will break the UI at runtime unless the frontend is updated in the same PR, or this endpoint is kept for backward compatibility (e.g., reintroduce it and have it delegate to the new stats service / return the previously expected shape).
    /// <summary>
    /// Manually triggers cleanup of old events
    /// </summary>
    [HttpPost("cleanup")]
    public async Task<ActionResult<object>> CleanupOldEvents([FromQuery] int retentionDays = 30)

code/backend/Cleanuparr.Infrastructure/Health/HealthCheckService.cs:216

  • In CheckArrInstanceHealthAsync, the exception path returns an ArrHealthStatus with only InstanceId populated; InstanceName and InstanceType will be empty/default. That makes downstream consumers (like /api/stats which serializes Type via InstanceType.ToString()) misleading when a check fails. Consider capturing the instance/config info before the health check call and populating InstanceName/InstanceType even on error.
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error performing health check for arr instance {instanceId}", instanceId);

            var status = new ArrHealthStatus
            {
                InstanceId = instanceId,
                IsHealthy = false,
                LastChecked = DateTime.UtcNow,
                ErrorMessage = $"Error: {ex.Message}"
            };

            UpdateArrHealthStatus(status);
            return status;

docs/docs/configuration/stats/index.mdx:99

  • The API response includes a top-level generatedAt field (see StatsResponse.GeneratedAt), but the documentation only describes the events/strikes/jobs/health sections. Please document generatedAt (and ideally show an example of the full top-level response shape) or remove the field if it isn’t intended to be part of the contract.
<SectionTitle icon="📋">Response Reference</SectionTitle>

<ConfigSection
  title="events"
  icon="📝"
>

docs/docs/configuration/stats/index.mdx:70

  • The controller clamps hours to 1–720 (Math.Clamp(hours, 1, 720)), so out-of-range values won’t error but will be silently adjusted. The docs currently state a range, but don’t mention the clamping behavior; consider clarifying this to avoid confusing dashboard integrations that accidentally send e.g. hours=0 or hours=999.
**Query Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `hours` | integer | `24` | Timeframe in hours (range: 1–720) |

code/backend/Cleanuparr.Api/Controllers/StatsController.cs:36

  • There are no automated tests added for the new stats aggregation behavior (e.g., timeframe filtering, job NextRunAt enrichment, and health serialization). Given the endpoint is intended for external dashboard polling, please add coverage (unit tests for StatsService and/or an API test for GET /api/stats).
    /// <summary>
    /// Gets aggregated application statistics for the specified timeframe
    /// </summary>
    /// <param name="hours">Timeframe in hours (default 24, range 1-720)</param>
    [HttpGet]
    public async Task<IActionResult> GetStats([FromQuery] int hours = 24)
    {
        try
        {
            hours = Math.Clamp(hours, 1, 720);

            var stats = await _statsService.GetStatsAsync(hours);
            return Ok(stats);

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Flaminel Flaminel merged commit 70f9995 into main Feb 21, 2026
7 checks passed
@Flaminel Flaminel deleted the add_stats_endpoint branch February 21, 2026 00:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants