Skip to content

Commit

Permalink
添加更多追踪数据
Browse files Browse the repository at this point in the history
  • Loading branch information
Ghost-chu committed Oct 8, 2024
1 parent f3d77c5 commit 7fc3159
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.ghostchu.btn.sparkle.util.BencodeUtil;
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressString;
import io.micrometer.core.instrument.MeterRegistry;
import jakarta.persistence.LockModeType;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
Expand Down Expand Up @@ -45,6 +46,8 @@ public class TrackerController extends SparkleController {
@Autowired
private AuditService auditService;

private MeterRegistry meterRegistry;

public static String compactPeers(List<TrackerService.Peer> peers, boolean isV6) throws IllegalStateException {
ByteBuffer buffer = ByteBuffer.allocate((isV6 ? 18 : 6) * peers.size());
for (TrackerService.Peer peer : peers) {
Expand Down Expand Up @@ -90,7 +93,9 @@ public static List<byte[]> extractInfoHashes(String queryString) {
@Transactional
@Lock(LockModeType.WRITE)
public byte[] announce() {
tickMetrics("announce_req", 1);
if (req.getQueryString() == null) {
tickMetrics("announce_req_fails", 1);
return "Sorry, This is a BitTorrent Tracker, and access announce endpoint via Browser is disallowed and useless.".getBytes(StandardCharsets.UTF_8);
}
if (ua(req) != null) {
Expand All @@ -100,6 +105,7 @@ public byte[] announce() {
|| ua(req).contains("Safari")
|| ua(req).contains("Edge")
|| ua(req).contains("Opera")) {
tickMetrics("announce_req_fails", 1);
return "Sorry, This is a BitTorrent Tracker, and access announce endpoint via Browser is disallowed and useless.".getBytes(StandardCharsets.UTF_8);
}
}
Expand Down Expand Up @@ -153,7 +159,9 @@ public byte[] announce() {
}
}
var peers = trackerService.fetchPeersFromTorrent(infoHash, peerId, null, numWant);

tickMetrics("announce_provided_peers", peers.v4().size() + peers.v6().size());
tickMetrics("announce_provided_peers_ipv4", peers.v4().size());
tickMetrics("announce_provided_peers_ipv6", peers.v6().size());
// 合成响应
var map = new HashMap<>() {{
put("interval", announceInterval / 1000);
Expand All @@ -178,6 +186,7 @@ public byte[] announce() {
}});
}
}};
tickMetrics("announce_req_success", 1);
auditService.log(req, "TRACKER_ANNOUNCE", true, Map.of("hash", infoHash, "user-agent", ua(req)));
return BencodeUtil.INSTANCE.encode(map);
}
Expand All @@ -191,9 +200,9 @@ public ResponseEntity<byte[]> scrape() {
for (byte[] infoHash : infoHashes) {
files.put(new String(infoHash, StandardCharsets.ISO_8859_1), new TreeMap<>() {{
var peers = trackerService.scrape(infoHash);
put("complete", peers.seeders() + 15);
put("incomplete", peers.leechers() + 15);
put("downloaded", peers.downloaded() + 15);
put("complete", peers.seeders());
put("incomplete", peers.leechers());
put("downloaded", peers.downloaded());
}});
}
map.put("files", files);
Expand All @@ -217,6 +226,11 @@ public List<String> getPossiblePeerIps(HttpServletRequest req) {
return found;
}


private void tickMetrics(String service, double increment) {
meterRegistry.counter("sparkle_tracker_" + service).increment(increment);
}

private record SparkleTrackerMetricsMessage(
long seeders,
long leechers,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.ghostchu.btn.sparkle.util.ByteUtil;
import com.ghostchu.btn.sparkle.util.TimeUtil;
import com.ghostchu.btn.sparkle.util.ipdb.GeoIPManager;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
Expand All @@ -30,17 +32,36 @@ public class TrackerService {
private final long inactiveInterval;
private final int maxPeersReturn;
private final GeoIPManager geoIPManager;

private final Counter announceCounter;
private final Counter peersFetchCounter;
private final Counter scrapeCounter;
private final MeterRegistry meterRegistry;

public TrackerService(TrackedPeerRepository trackedPeerRepository,
TrackedTaskRepository trackedTaskRepository,
@Value("${service.tracker.inactive-interval}") long inactiveInterval,
@Value("${service.tracker.max-peers-return}") int maxPeersReturn, GeoIPManager geoIPManager) {
@Value("${service.tracker.max-peers-return}") int maxPeersReturn, GeoIPManager geoIPManager,
MeterRegistry meterRegistry) {
this.trackedPeerRepository = trackedPeerRepository;
this.trackedTaskRepository = trackedTaskRepository;
this.inactiveInterval = inactiveInterval;
this.maxPeersReturn = maxPeersReturn;
this.geoIPManager = geoIPManager;
this.meterRegistry = meterRegistry;
this.announceCounter = meterRegistry.counter("sparkle_tracker_announce");
this.peersFetchCounter = meterRegistry.counter("sparkle_tracker_peers_fetch");
this.scrapeCounter = meterRegistry.counter("sparkle_tracker_scrape");
}

@Scheduled(fixedDelayString = "${service.tracker.metrics-interval}")
@Transactional
public void updateTrackerMetrics() {
var totalPeers = meterRegistry.gauge("sparkle_tracker_tracking_total_peers", trackedPeerRepository.count());
var uniquePeers = meterRegistry.gauge("sparkle_tracker_tracking_unique_peers", trackedPeerRepository.countDistinctByPeerId());
var uniqueIps = meterRegistry.gauge("sparkle_tracker_tracking_unique_ips", trackedPeerRepository.countDistinctByPeerIp());
var activeTasks = meterRegistry.gauge("sparkle_tracker_tracking_tasks", trackedPeerRepository.countDistinctByTorrentInfoHash());
var totalTasks = meterRegistry.gauge("sparkle_tracker_tracking_tasks", trackedTaskRepository.count());
log.info("[Tracker 实时] 总Peer: {}, 唯一Peer: {}, 唯一IP: {}, 活动种子: {}, 种子总数: {}", totalPeers, uniquePeers, uniqueIps, activeTasks, totalTasks);
}

@Scheduled(fixedDelayString = "${service.tracker.cleanup-interval}")
Expand All @@ -52,6 +73,7 @@ public void cleanup() {

@Async
public void executeAnnounce(PeerAnnounce announce) {
announceCounter.increment();
var trackedPeer = trackedPeerRepository.findByPeerIpAndPeerIdAndTorrentInfoHash(
announce.peerIp(),
ByteUtil.filterUTF8(ByteUtil.bytesToHex(announce.peerId())),
Expand Down Expand Up @@ -121,6 +143,7 @@ public void executeAnnounce(PeerAnnounce announce) {

@Cacheable(value = {"peers#3000"}, key = "#torrentInfoHash")
public TrackedPeerList fetchPeersFromTorrent(byte[] torrentInfoHash, byte[] peerId, InetAddress peerIp, int numWant) {
peersFetchCounter.increment();
List<Peer> v4 = new ArrayList<>();
List<Peer> v6 = new ArrayList<>();
int seeders = 0;
Expand Down Expand Up @@ -149,6 +172,7 @@ public TrackedPeerList fetchPeersFromTorrent(byte[] torrentInfoHash, byte[] peer

@Cacheable(value = {"scrape#60000"}, key = "#torrentInfoHash")
public ScrapeResponse scrape(byte[] torrentInfoHash) {
scrapeCounter.increment();
var seeders = trackedPeerRepository.countByTorrentInfoHashAndLeft(ByteUtil.bytesToHex(torrentInfoHash), 0L);
var leechers = trackedPeerRepository.countByTorrentInfoHashAndLeftNot(ByteUtil.bytesToHex(torrentInfoHash), 0L);
var downloaded = 0L;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ order by RANDOM() limit ?3

long countByLeftNot(Long left);

long countDistinctByPeerId();

long countDistinctByPeerIp();

long countDistinctByTorrentInfoHash();

@Query("select count(*) from TrackedPeer t where t.uploaded = 0")
long countUsersWhoDidntUploadAnyData();
@Query("select count(*) from TrackedPeer t where t.uploaded != 0")
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ service.tracker.cleanup-interval=600000
service.tracker.announce-interval=3600000
service.tracker.inactive-interval=3800000
service.tracker.max-peers-return=300
service.tracker.metrics-interval=600000

util.ipmerger.merge-threshold.ipv4=2
util.ipmerger.merge-threshold.ipv6=3
Expand Down

0 comments on commit 7fc3159

Please sign in to comment.