atlet99/dtorrent_tracker_v2
[FEATURE] - Add tracker statistics and metrics;
Aperta
#9 aperta il 3 nov 2025
enhancementhelp wanted
Metriche repository
- Star
- (0 stelle)
- Metriche merge PR
- (Nessuna PR mergiata in 30 g)
Descrizione
Description
There is currently no way to track statistics about tracker operations, such as:
- Number of successful/unsuccessful requests
- Response times
- Error rates
- Request counts per tracker
This would be valuable for monitoring, debugging, and optimizing tracker usage.
Location
File: lib/src/tracker/tracker.dart (new functionality)
Expected Behavior
Add optional statistics tracking to the Tracker class that includes:
-
Request Statistics:
- Total requests sent
- Successful responses
- Failed responses
- Timeout errors
- Network errors
-
Performance Metrics:
- Average response time
- Min/Max response times
- Last response time
-
Error Tracking:
- Error counts by type
- Last error message/time
-
Availability:
- Track success rate
- Track consecutive failures
- Last successful request time
Proposed Implementation
/// Statistics for tracker operations
class TrackerStatistics {
int totalRequests = 0;
int successfulRequests = 0;
int failedRequests = 0;
int timeoutErrors = 0;
int networkErrors = 0;
final List<Duration> responseTimes = [];
DateTime? lastRequestTime;
DateTime? lastSuccessTime;
DateTime? lastFailureTime;
String? lastErrorMessage;
dynamic lastError;
/// Average response time in milliseconds
double get averageResponseTime {
if (responseTimes.isEmpty) return 0.0;
var total = responseTimes.fold<int>(
0,
(sum, duration) => sum + duration.inMilliseconds,
);
return total / responseTimes.length;
}
/// Minimum response time
Duration? get minResponseTime {
if (responseTimes.isEmpty) return null;
return responseTimes.reduce((a, b) => a < b ? a : b);
}
/// Maximum response time
Duration? get maxResponseTime {
if (responseTimes.isEmpty) return null;
return responseTimes.reduce((a, b) => a > b ? a : b);
}
/// Success rate (0.0 to 1.0)
double get successRate {
if (totalRequests == 0) return 0.0;
return successfulRequests / totalRequests;
}
/// Reset all statistics
void reset() {
totalRequests = 0;
successfulRequests = 0;
failedRequests = 0;
timeoutErrors = 0;
networkErrors = 0;
responseTimes.clear();
lastRequestTime = null;
lastSuccessTime = null;
lastFailureTime = null;
lastErrorMessage = null;
lastError = null;
}
}
Add to Tracker class:
abstract class Tracker with EventsEmittable<TrackerEvent> {
// ... existing code ...
/// Statistics tracking (optional, disabled by default)
bool enableStatistics = false;
TrackerStatistics? _statistics;
TrackerStatistics? get statistics =>
enableStatistics ? _statistics : null;
Tracker(this.id, this.announceUrl, this.infoHashBuffer, {this.provider}) {
_statistics = TrackerStatistics();
}
Future<bool> _intervalAnnounce(String event) async {
var startTime = DateTime.now();
if (enableStatistics) {
_statistics?.totalRequests++;
_statistics?.lastRequestTime = startTime;
}
// ... existing announce code ...
try {
result = await announce(event, await _announceOptions);
if (enableStatistics && result != null) {
var duration = DateTime.now().difference(startTime);
_statistics?.successfulRequests++;
_statistics?.responseTimes.add(duration);
_statistics?.lastSuccessTime = DateTime.now();
}
// ... rest of processing ...
} catch (e) {
if (enableStatistics) {
_statistics?.failedRequests++;
_statistics?.lastFailureTime = DateTime.now();
_statistics?.lastError = e;
_statistics?.lastErrorMessage = e.toString();
if (e.toString().contains('timeout')) {
_statistics?.timeoutErrors++;
} else {
_statistics?.networkErrors++;
}
}
events.emit(TrackerAnnounceErrorEvent(this, e));
return false;
}
}
}
Usage Example
var tracker = HttpTracker(uri, infoHash);
tracker.enableStatistics = true;
await tracker.start();
// Later, access statistics
var stats = tracker.statistics;
if (stats != null) {
print('Total requests: ${stats.totalRequests}');
print('Success rate: ${(stats.successRate * 100).toStringAsFixed(1)}%');
print('Average response time: ${stats.averageResponseTime.toStringAsFixed(0)}ms');
print('Last error: ${stats.lastErrorMessage}');
}
Impact
- Severity: Low (Feature Enhancement)
- Affected: All tracker instances (optional feature)
- Benefits:
- Monitoring and observability
- Debugging performance issues
- Optimizing tracker selection
- Production diagnostics
- User metrics and analytics
Additional Context
Statistics should be:
- Optional (disabled by default for performance)
- Low overhead when enabled
- Thread-safe if used in multi-threaded environments
- Resettable for testing/debugging
- Accessible without breaking existing API
Related Standards
- General best practices for metrics collection
- Observability patterns