diff --git a/src/Services/MetricsService.cs b/src/Services/MetricsService.cs
index 657c6ed..91ba461 100644
--- a/src/Services/MetricsService.cs
+++ b/src/Services/MetricsService.cs
@@ -1,528 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Threading;
using System.Threading.Tasks;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using TransmissionRssManager.Core;
-using TransmissionRssManager.Data.Repositories;
namespace TransmissionRssManager.Services
{
+ ///
+ /// Interface for the metrics service that provides dashboard statistics and performance data
+ ///
public interface IMetricsService
{
- Task GetDashboardStatsAsync();
- Task> GetDownloadHistoryAsync(int days = 30);
- Task> GetCategoryStatsAsync();
- Task GetSystemStatusAsync();
+ Task> GetDashboardStatsAsync();
Task> EstimateDiskUsageAsync();
- Task> GetPerformanceMetricsAsync();
+ Task> GetSystemStatusAsync();
}
+ ///
+ /// Service that provides metrics and statistics about downloads, system status, and performance
+ ///
public class MetricsService : IMetricsService
{
private readonly ILogger _logger;
private readonly ITransmissionClient _transmissionClient;
- private readonly IRepository _feedRepository;
- private readonly IRepository _feedItemRepository;
- private readonly IRepository _torrentRepository;
- private readonly IRepository _logRepository;
- private readonly ILoggingService _loggingService;
private readonly IConfigService _configService;
- // Helper method to map database Torrent model to Core.TorrentInfo
- private Core.TorrentInfo MapToTorrentInfo(TransmissionRssManager.Data.Models.Torrent torrent)
- {
- return new Core.TorrentInfo
- {
- Id = torrent.Id,
- Name = torrent.Name,
- Status = torrent.Status,
- PercentDone = torrent.PercentDone,
- TotalSize = torrent.TotalSize,
- DownloadDir = torrent.DownloadDirectory ?? "",
- AddedDate = torrent.AddedOn,
- CompletedDate = torrent.CompletedOn,
- DownloadedEver = torrent.DownloadedEver,
- UploadedEver = torrent.UploadedEver,
- UploadRatio = (int)torrent.UploadRatio,
- ErrorString = torrent.ErrorMessage ?? "",
- HashString = torrent.Hash,
- PeersConnected = torrent.PeersConnected,
- DownloadSpeed = torrent.DownloadSpeed,
- UploadSpeed = torrent.UploadSpeed,
- Category = torrent.Category ?? "",
- HasMetadata = torrent.HasMetadata,
- TransmissionInstance = torrent.TransmissionInstance ?? "default",
- SourceFeedId = torrent.RssFeedItemId?.ToString() ?? "",
- IsPostProcessed = torrent.PostProcessed
- };
- }
-
- // Helper method to map database RssFeed model to Core.RssFeed
- private Core.RssFeed MapToRssFeed(TransmissionRssManager.Data.Models.RssFeed feed)
- {
- var result = new Core.RssFeed
- {
- Id = feed.Id.ToString(),
- Name = feed.Name,
- Url = feed.Url,
- AutoDownload = feed.Enabled,
- LastChecked = feed.LastCheckedAt,
- TransmissionInstanceId = feed.TransmissionInstanceId ?? "default",
- Schedule = feed.Schedule,
- Enabled = feed.Enabled,
- MaxHistoryItems = feed.MaxHistoryItems,
- DefaultCategory = feed.DefaultCategory ?? "",
- ErrorCount = feed.ErrorCount,
- LastError = feed.LastError != null ? feed.LastCheckedAt : null,
- LastErrorMessage = feed.LastError
- };
-
- // Add rules to the feed
- if (feed.Rules != null)
- {
- foreach (var rule in feed.Rules)
- {
- result.AdvancedRules.Add(new Core.RssFeedRule
- {
- Id = rule.Id.ToString(),
- Name = rule.Name,
- Pattern = rule.IncludePattern ?? "",
- IsRegex = rule.UseRegex,
- IsEnabled = rule.Enabled,
- IsCaseSensitive = false, // Default value as this field doesn't exist in the DB model
- Category = rule.CustomSavePath ?? "",
- Priority = rule.Priority,
- Action = rule.EnablePostProcessing ? "process" : "download",
- DestinationFolder = rule.CustomSavePath ?? ""
- });
- }
- }
-
- return result;
- }
-
public MetricsService(
ILogger logger,
ITransmissionClient transmissionClient,
- IRepository feedRepository,
- IRepository feedItemRepository,
- IRepository torrentRepository,
- IRepository logRepository,
- ILoggingService loggingService,
IConfigService configService)
{
_logger = logger;
_transmissionClient = transmissionClient;
- _feedRepository = feedRepository;
- _feedItemRepository = feedItemRepository;
- _torrentRepository = torrentRepository;
- _logRepository = logRepository;
- _loggingService = loggingService;
_configService = configService;
}
- public async Task GetDashboardStatsAsync()
+ ///
+ /// Gets dashboard statistics including active downloads, upload/download speeds, etc.
+ ///
+ public async Task> GetDashboardStatsAsync()
{
try
{
- var now = DateTime.UtcNow;
- var today = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0, DateTimeKind.Utc);
+ var stats = new Dictionary();
+ var torrents = await _transmissionClient.GetTorrentsAsync();
- // Combine data from both Transmission and database
- // Get active torrents from Transmission for real-time data
- var transmissionTorrents = await _transmissionClient.GetTorrentsAsync();
+ // Calculate basic stats
+ stats["TotalTorrents"] = torrents.Count;
+ stats["ActiveDownloads"] = torrents.Count(t => t.Status == "Downloading");
+ stats["SeedingTorrents"] = torrents.Count(t => t.Status == "Seeding");
+ stats["CompletedTorrents"] = torrents.Count(t => t.IsFinished);
+ stats["TotalDownloaded"] = torrents.Sum(t => t.DownloadedEver);
+ stats["TotalUploaded"] = torrents.Sum(t => t.UploadedEver);
+ stats["DownloadSpeed"] = torrents.Sum(t => t.DownloadSpeed);
+ stats["UploadSpeed"] = torrents.Sum(t => t.UploadSpeed);
- // Get database torrent data for historical information
- var dbTorrents = await _torrentRepository.Query().ToListAsync();
+ // Calculate total size
+ long totalSize = torrents.Sum(t => t.TotalSize);
+ stats["TotalSize"] = totalSize;
- // Count active downloads (status is downloading)
- var activeDownloads = transmissionTorrents.Count(t => t.Status == "Downloading");
-
- // Count seeding torrents (status is seeding)
- var seedingTorrents = transmissionTorrents.Count(t => t.Status == "Seeding");
-
- // Get active feeds count
- var activeFeeds = await _feedRepository.Query()
- .Where(f => f.Enabled)
- .CountAsync();
-
- // Get completed downloads today
- var completedToday = dbTorrents
- .Count(t => t.CompletedOn.HasValue && t.CompletedOn.Value >= today);
-
- // Get added today
- var addedToday = dbTorrents
- .Count(t => t.AddedOn >= today);
-
- // Get matched count (all time)
- var matchedCount = await _feedItemRepository.Query()
- .Where(i => i.MatchedRuleId != null)
- .CountAsync();
-
- // Calculate download/upload speeds from Transmission (real-time data)
- double downloadSpeed = transmissionTorrents.Sum(t => t.DownloadSpeed);
- double uploadSpeed = transmissionTorrents.Sum(t => t.UploadSpeed);
-
- // Update database objects with transmission data
- // This helps keep database in sync with transmission for metrics
- foreach (var transmissionTorrent in transmissionTorrents)
- {
- var dbTorrent = dbTorrents.FirstOrDefault(t => t.TransmissionId == transmissionTorrent.Id);
- if (dbTorrent != null)
- {
- // Update database with current speeds and status for the background service to store
- dbTorrent.DownloadSpeed = transmissionTorrent.DownloadSpeed;
- dbTorrent.UploadSpeed = transmissionTorrent.UploadSpeed;
- dbTorrent.Status = transmissionTorrent.Status;
- dbTorrent.PercentDone = transmissionTorrent.PercentDone;
- dbTorrent.DownloadedEver = transmissionTorrent.DownloadedEver;
- dbTorrent.UploadedEver = transmissionTorrent.UploadedEver;
- dbTorrent.PeersConnected = transmissionTorrent.PeersConnected;
-
- // Update the database object
- await _torrentRepository.UpdateAsync(dbTorrent);
- }
- }
-
- // Save the changes
- await _torrentRepository.SaveChangesAsync();
-
- // Calculate total downloaded and uploaded
- // Use Transmission for active torrents (more accurate) and database for historical torrents
- var totalDownloaded = transmissionTorrents.Sum(t => t.DownloadedEver);
- var totalUploaded = transmissionTorrents.Sum(t => t.UploadedEver);
-
- // Add historical data from database for torrents that are no longer in Transmission
- var transmissionIds = transmissionTorrents.Select(t => t.Id).ToHashSet();
- var historicalTorrents = dbTorrents.Where(t => t.TransmissionId.HasValue && !transmissionIds.Contains(t.TransmissionId.Value));
- totalDownloaded += historicalTorrents.Sum(t => t.DownloadedEver);
- totalUploaded += historicalTorrents.Sum(t => t.UploadedEver);
-
- return new DashboardStats
- {
- ActiveDownloads = activeDownloads,
- SeedingTorrents = seedingTorrents,
- ActiveFeeds = activeFeeds,
- CompletedToday = completedToday,
- AddedToday = addedToday,
- FeedsCount = await _feedRepository.Query().CountAsync(),
- MatchedCount = matchedCount,
- DownloadSpeed = downloadSpeed,
- UploadSpeed = uploadSpeed,
- TotalDownloaded = totalDownloaded,
- TotalUploaded = totalUploaded
- };
+ return stats;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting dashboard stats");
- _loggingService.Log(
- LogLevel.Error,
- $"Error getting dashboard stats: {ex.Message}",
- "MetricsService",
- new Dictionary {
- { "ErrorMessage", ex.Message },
- { "StackTrace", ex.StackTrace }
- }
- );
-
- return new DashboardStats();
- }
- }
-
- public async Task> GetDownloadHistoryAsync(int days = 30)
- {
- try
- {
- var result = new List();
- var endDate = DateTime.UtcNow;
- var startDate = endDate.AddDays(-days);
-
- // Get download history from the database for added torrents
- var addedTorrents = await _torrentRepository.Query()
- .Where(t => t.AddedOn >= startDate && t.AddedOn <= endDate)
- .ToListAsync();
-
- // Get completed torrents history
- var completedTorrents = await _torrentRepository.Query()
- .Where(t => t.CompletedOn.HasValue && t.CompletedOn.Value >= startDate && t.CompletedOn.Value <= endDate)
- .ToListAsync();
-
- // Group by date added
- var groupedByAdded = addedTorrents
- .GroupBy(t => new DateTime(t.AddedOn.Year, t.AddedOn.Month, t.AddedOn.Day, 0, 0, 0, DateTimeKind.Utc))
- .Select(g => new {
- Date = g.Key,
- Count = g.Count(),
- TotalSize = g.Sum(t => t.TotalSize)
- })
- .OrderBy(g => g.Date)
- .ToList();
-
- // Group by date completed
- var groupedByCompleted = completedTorrents
- .GroupBy(t => new DateTime(t.CompletedOn.Value.Year, t.CompletedOn.Value.Month, t.CompletedOn.Value.Day, 0, 0, 0, DateTimeKind.Utc))
- .Select(g => new {
- Date = g.Key,
- Count = g.Count(),
- TotalSize = g.Sum(t => t.TotalSize)
- })
- .OrderBy(g => g.Date)
- .ToList();
-
- // Fill in missing dates
- for (var date = startDate; date <= endDate; date = date.AddDays(1))
+ return new Dictionary
{
- var day = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, DateTimeKind.Utc);
-
- // Get data for this day
- var addedData = groupedByAdded.FirstOrDefault(g => g.Date == day);
- var completedData = groupedByCompleted.FirstOrDefault(g => g.Date == day);
-
- // Create data point with added count and size
- result.Add(new HistoricalDataPoint
- {
- Date = day,
- Count = addedData?.Count ?? 0, // Use added count by default
- TotalSize = addedData?.TotalSize ?? 0,
- CompletedCount = completedData?.Count ?? 0,
- CompletedSize = completedData?.TotalSize ?? 0
- });
- }
-
- return result;
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error getting download history");
- _loggingService.Log(
- LogLevel.Error,
- $"Error getting download history: {ex.Message}",
- "MetricsService",
- new Dictionary {
- { "ErrorMessage", ex.Message },
- { "StackTrace", ex.StackTrace },
- { "Days", days.ToString() }
- }
- );
-
- return new List();
+ ["Error"] = ex.Message,
+ ["TotalTorrents"] = 0,
+ ["ActiveDownloads"] = 0,
+ ["SeedingTorrents"] = 0,
+ ["CompletedTorrents"] = 0
+ };
}
}
- public async Task> GetCategoryStatsAsync()
- {
- try
- {
- // Get torrents with categories from database
- var dbTorrents = await _torrentRepository.Query()
- .Where(t => t.Category != null)
- .ToListAsync();
-
- // Get torrents from Transmission for real-time data
- var transmissionTorrents = await _transmissionClient.GetTorrentsAsync();
-
- // Map Transmission torrents to dictionary by hash for quick lookup
- var transmissionTorrentsByHash = transmissionTorrents
- .Where(t => !string.IsNullOrEmpty(t.HashString))
- .ToDictionary(t => t.HashString, t => t);
-
- // Create a list to store category stats with combined data
- var categoryStats = new Dictionary();
-
- // Process database torrents first
- foreach (var torrent in dbTorrents)
- {
- var category = torrent.Category ?? "Uncategorized";
-
- if (!categoryStats.TryGetValue(category, out var stats))
- {
- stats = new CategoryStats
- {
- Category = category,
- Count = 0,
- TotalSize = 0,
- ActiveCount = 0,
- CompletedCount = 0,
- DownloadSpeed = 0,
- UploadSpeed = 0
- };
- categoryStats[category] = stats;
- }
-
- stats.Count++;
- stats.TotalSize += torrent.TotalSize;
-
- // Check if this torrent is completed
- if (torrent.CompletedOn.HasValue)
- {
- stats.CompletedCount++;
- }
-
- // Check if this torrent is active in Transmission
- if (transmissionTorrentsByHash.TryGetValue(torrent.Hash, out var transmissionTorrent))
- {
- stats.ActiveCount++;
- stats.DownloadSpeed += transmissionTorrent.DownloadSpeed;
- stats.UploadSpeed += transmissionTorrent.UploadSpeed;
- }
- }
-
- // Process any Transmission torrents that might not be in the database
- foreach (var torrent in transmissionTorrents)
- {
- // Skip if no hash or already processed
- if (string.IsNullOrEmpty(torrent.HashString) ||
- dbTorrents.Any(t => t.Hash == torrent.HashString))
- {
- continue;
- }
-
- var category = torrent.Category ?? "Uncategorized";
-
- if (!categoryStats.TryGetValue(category, out var stats))
- {
- stats = new CategoryStats
- {
- Category = category,
- Count = 0,
- TotalSize = 0,
- ActiveCount = 0,
- CompletedCount = 0,
- DownloadSpeed = 0,
- UploadSpeed = 0
- };
- categoryStats[category] = stats;
- }
-
- stats.Count++;
- stats.TotalSize += torrent.TotalSize;
- stats.ActiveCount++;
- stats.DownloadSpeed += torrent.DownloadSpeed;
- stats.UploadSpeed += torrent.UploadSpeed;
-
- // Check if this torrent is completed
- if (torrent.IsFinished)
- {
- stats.CompletedCount++;
- }
- }
-
- // Return the category stats ordered by count
- return categoryStats.Values
- .OrderByDescending(c => c.Count)
- .ToList();
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error getting category stats");
- _loggingService.Log(
- LogLevel.Error,
- $"Error getting category stats: {ex.Message}",
- "MetricsService",
- new Dictionary {
- { "ErrorMessage", ex.Message },
- { "StackTrace", ex.StackTrace }
- }
- );
-
- return new List();
- }
- }
-
- public async Task GetSystemStatusAsync()
- {
- var config = _configService.GetConfiguration();
-
- var status = new SystemStatus
- {
- TransmissionConnected = false,
- AutoDownloadEnabled = config.AutoDownloadEnabled,
- PostProcessingEnabled = config.PostProcessing.Enabled,
- EnabledFeeds = await _feedRepository.Query().Where(f => f.Enabled).CountAsync(),
- TotalFeeds = await _feedRepository.Query().CountAsync(),
- CheckIntervalMinutes = config.CheckIntervalMinutes,
- NotificationsEnabled = config.UserPreferences.NotificationsEnabled,
- DatabaseStatus = "Connected"
- };
-
- try
- {
- // Check database health by counting torrents
- var torrentCount = await _torrentRepository.Query().CountAsync();
- status.TorrentCount = torrentCount;
-
- // Count torrents by status
- status.ActiveTorrentCount = await _torrentRepository.Query()
- .Where(t => t.Status == "downloading" || t.Status == "Downloading")
- .CountAsync();
-
- status.CompletedTorrentCount = await _torrentRepository.Query()
- .Where(t => t.CompletedOn.HasValue)
- .CountAsync();
-
- // Check feed items count
- status.FeedItemCount = await _feedItemRepository.Query().CountAsync();
-
- // Check log entries count
- var logCount = await _logRepository.Query().CountAsync();
- status.LogEntryCount = logCount;
-
- // Get database size estimate (rows * avg row size)
- long estimatedDbSize = (torrentCount * 1024) + (status.FeedItemCount * 512) + (logCount * 256);
- status.EstimatedDatabaseSizeBytes = estimatedDbSize;
-
- // Try to connect to Transmission to check if it's available
- var torrents = await _transmissionClient.GetTorrentsAsync();
-
- status.TransmissionConnected = true;
- status.TransmissionVersion = "Unknown"; // We don't have a way to get this info directly
- status.TransmissionTorrentCount = torrents.Count;
-
- // Enhancement: Map any transmission torrents not in our database
- var dbTorrents = await _torrentRepository.Query().ToListAsync();
- var transmissionHashes = torrents.Select(t => t.HashString).ToHashSet();
- var dbHashes = dbTorrents.Select(t => t.Hash).ToHashSet();
-
- status.OrphanedTorrentCount = transmissionHashes.Count(h => !dbHashes.Contains(h));
- status.StaleDbTorrentCount = dbHashes.Count(h => !transmissionHashes.Contains(h));
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error getting system status");
- status.TransmissionConnected = false;
- status.LastErrorMessage = ex.Message;
- }
-
- return status;
- }
-
+ ///
+ /// Estimates disk usage for torrents and available space
+ ///
public async Task> EstimateDiskUsageAsync()
{
try
{
- // Get disk usage from both Transmission and database
- var transmissionTorrents = await _transmissionClient.GetTorrentsAsync();
- var dbTorrents = await _torrentRepository.Query().ToListAsync();
-
- // Calculate total size from Transmission (most accurate for active torrents)
- long transmissionSize = transmissionTorrents.Sum(t => t.TotalSize);
-
- // Add sizes from database for torrents not in Transmission (historical data)
- var transmissionHashes = transmissionTorrents.Select(t => t.HashString).ToHashSet();
- var historicalTorrents = dbTorrents.Where(t => !transmissionHashes.Contains(t.Hash));
-
- long historicalSize = historicalTorrents.Sum(t => t.TotalSize);
-
- // Also get estimated database size
- long databaseSize = await _torrentRepository.Query().CountAsync() * 1024 + // ~1KB per torrent
- await _feedItemRepository.Query().CountAsync() * 512 + // ~512B per feed item
- await _logRepository.Query().CountAsync() * 256; // ~256B per log entry
+ // Get disk usage from torrents
+ var torrents = await _transmissionClient.GetTorrentsAsync();
+ long totalSize = torrents.Sum(t => t.TotalSize);
// Calculate available space in download directory
string downloadDir = _configService.GetConfiguration().DownloadDirectory;
@@ -543,204 +106,56 @@ namespace TransmissionRssManager.Services
return new Dictionary
{
- ["activeTorrentsSize"] = transmissionSize,
- ["historicalTorrentsSize"] = historicalSize,
- ["totalTorrentsSize"] = transmissionSize + historicalSize,
- ["databaseSize"] = databaseSize,
+ ["activeTorrentsSize"] = totalSize,
["availableSpace"] = availableSpace
};
}
catch (Exception ex)
{
_logger.LogError(ex, "Error estimating disk usage");
- _loggingService.Log(
- LogLevel.Error,
- $"Error estimating disk usage: {ex.Message}",
- "MetricsService",
- new Dictionary {
- { "ErrorMessage", ex.Message },
- { "StackTrace", ex.StackTrace }
- }
- );
-
return new Dictionary
{
["activeTorrentsSize"] = 0,
- ["historicalTorrentsSize"] = 0,
- ["totalTorrentsSize"] = 0,
- ["databaseSize"] = 0,
["availableSpace"] = 0
};
}
}
- public async Task> GetPerformanceMetricsAsync()
+ ///
+ /// Gets system status including Transmission connection state
+ ///
+ public async Task> GetSystemStatusAsync()
{
- var metrics = new Dictionary();
+ var config = _configService.GetConfiguration();
+
+ var status = new Dictionary
+ {
+ ["TransmissionConnected"] = false,
+ ["AutoDownloadEnabled"] = config.AutoDownloadEnabled,
+ ["PostProcessingEnabled"] = config.PostProcessing.Enabled,
+ ["CheckIntervalMinutes"] = config.CheckIntervalMinutes
+ };
try
{
- // Calculate average time to complete downloads
- var completedTorrents = await _torrentRepository.Query()
- .Where(t => t.CompletedOn.HasValue)
- .ToListAsync();
+ // Try to connect to Transmission to check if it's available
+ var torrents = await _transmissionClient.GetTorrentsAsync();
- if (completedTorrents.Any())
- {
- var avgCompletionTimeMinutes = completedTorrents
- .Where(t => t.AddedOn < t.CompletedOn)
- .Average(t => (t.CompletedOn.Value - t.AddedOn).TotalMinutes);
-
- metrics["AvgCompletionTimeMinutes"] = Math.Round(avgCompletionTimeMinutes, 2);
- }
- else
- {
- metrics["AvgCompletionTimeMinutes"] = 0;
- }
+ status["TransmissionConnected"] = true;
+ status["TransmissionTorrentCount"] = torrents.Count;
- // Calculate feed refresh performance
- var feeds = await _feedRepository.Query().ToListAsync();
- if (feeds.Any())
- {
- var avgItemsPerFeed = await _feedItemRepository.Query().CountAsync() / (double)feeds.Count;
- metrics["AvgItemsPerFeed"] = Math.Round(avgItemsPerFeed, 2);
- }
- else
- {
- metrics["AvgItemsPerFeed"] = 0;
- }
-
- return metrics;
+ // Count torrents by status
+ status["ActiveTorrentCount"] = torrents.Count(t => t.Status == "Downloading");
+ status["CompletedTorrentCount"] = torrents.Count(t => t.IsFinished);
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error getting performance metrics");
- return new Dictionary
- {
- ["AvgCompletionTimeMinutes"] = 0,
- ["AvgItemsPerFeed"] = 0
- };
- }
- }
- }
-
- public class DashboardStats
- {
- public int ActiveDownloads { get; set; }
- public int SeedingTorrents { get; set; }
- public int ActiveFeeds { get; set; }
- public int CompletedToday { get; set; }
- public int AddedToday { get; set; }
- public int FeedsCount { get; set; }
- public int MatchedCount { get; set; }
- public double DownloadSpeed { get; set; }
- public double UploadSpeed { get; set; }
- public long TotalDownloaded { get; set; }
- public long TotalUploaded { get; set; }
- }
-
- public class HistoricalDataPoint
- {
- public DateTime Date { get; set; }
- public int Count { get; set; }
- public long TotalSize { get; set; }
- public int CompletedCount { get; set; }
- public long CompletedSize { get; set; }
- }
-
- public class CategoryStats
- {
- public string Category { get; set; }
- public int Count { get; set; }
- public long TotalSize { get; set; }
- public int ActiveCount { get; set; }
- public int CompletedCount { get; set; }
- public double DownloadSpeed { get; set; }
- public double UploadSpeed { get; set; }
- }
-
- public class SystemStatus
- {
- public bool TransmissionConnected { get; set; }
- public string TransmissionVersion { get; set; }
- public bool AutoDownloadEnabled { get; set; }
- public bool PostProcessingEnabled { get; set; }
- public int EnabledFeeds { get; set; }
- public int TotalFeeds { get; set; }
- public int CheckIntervalMinutes { get; set; }
- public bool NotificationsEnabled { get; set; }
-
- // Database status
- public string DatabaseStatus { get; set; }
- public int TorrentCount { get; set; }
- public int ActiveTorrentCount { get; set; }
- public int CompletedTorrentCount { get; set; }
- public int FeedItemCount { get; set; }
- public int LogEntryCount { get; set; }
- public long EstimatedDatabaseSizeBytes { get; set; }
-
- // Transmission status
- public int TransmissionTorrentCount { get; set; }
-
- // Sync status
- public int OrphanedTorrentCount { get; set; } // Torrents in Transmission but not in database
- public int StaleDbTorrentCount { get; set; } // Torrents in database but not in Transmission
-
- // For compatibility
- public string TranmissionVersion
- {
- get => TransmissionVersion;
- set => TransmissionVersion = value;
- }
-
- // Error info
- public string LastErrorMessage { get; set; }
- }
-
- public class MetricsBackgroundService : BackgroundService
- {
- private readonly ILogger _logger;
- private readonly IServiceProvider _serviceProvider;
-
- public MetricsBackgroundService(
- ILogger logger,
- IServiceProvider serviceProvider)
- {
- _logger = logger;
- _serviceProvider = serviceProvider;
- }
-
- protected override async Task ExecuteAsync(CancellationToken stoppingToken)
- {
- _logger.LogInformation("Metrics background service started");
-
- // Update metrics every minute
- var timer = new PeriodicTimer(TimeSpan.FromMinutes(1));
-
- while (!stoppingToken.IsCancellationRequested && await timer.WaitForNextTickAsync(stoppingToken))
- {
- try
- {
- using var scope = _serviceProvider.CreateScope();
- var metricsService = scope.ServiceProvider.GetRequiredService();
-
- // This just ensures the metrics are calculated and cached if needed
- await metricsService.GetDashboardStatsAsync();
-
- _logger.LogDebug("Metrics updated");
- }
- catch (OperationCanceledException)
- {
- // Service is shutting down
- break;
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error updating metrics");
- }
+ _logger.LogError(ex, "Error getting system status");
+ status["TransmissionConnected"] = false;
+ status["LastErrorMessage"] = ex.Message;
}
- _logger.LogInformation("Metrics background service stopped");
+ return status;
}
}
}
\ No newline at end of file