root/hydranode/utils/srcstat.pl

Revision 2778, 16.8 kB (checked in by chemical, 3 years ago)

Detect NNP clients and do not count them as a failed downloadsession anymore

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/perl
2 # Copyright (C) 2004-2006 Alo Sarv <madcat_@users.sourceforge.net>
3 #
4 #  This program is free software; you can redistribute it and/or modify
5 #  it under the terms of the GNU General Public License as published by
6 #  the Free Software Foundation; either version 2 of the License, or
7 #  (at your option) any later version.
8 #
9 #  This program is distributed in the hope that it will be useful,
10 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #  GNU General Public License for more details.
13 #
14 #  You should have received a copy of the GNU General Public License
15 #  along with this program; if not, write to the Free Software
16 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18 #
19 #
20 #
21
22 # =============================================================================
23 # For best results, you need to start hydranode with the commandline parameters
24 # "-t ed2k.client,ed2k.clientlist,ed2k.deadsource,chunks,ed2k.secident"
25 #
26 # If you start hydranode within gdb, use:
27 # > run -t ed2k.client,ed2k.clientlist,ed2k.deadsource,chunks,ed2k.secident,ed2k.sourceexchange,ed2k.globsrc
28 #
29 #
30 #
31 #
32 #
33 #
34
35 use Time::Local;
36 $|++;
37
38 my $logfile = $ENV{HOME}."/.hydranode/hydranode.log";
39 open(LOGFILE,'<',$logfile) || die "can't open ".$logfile.": $!";
40 #open(LOGFILE, '<', "./config/hydranode.log"); # for win32
41
42 my %Client;
43 my %ClientUnknown;
44 my $aa = 0; #temporary
45 my $ab = 0; #temporary
46 my $starttime = "";
47 my $endtime = "";
48 my $runtime = "";
49 my $lastline = "";
50
51 my $fromserver      = 0; # Sources received from servers
52 my $fromudp         = 0; # Sources received via UDP
53 my $fromsrcex       = 0; # Sources received via SourceExchange
54 my $passive         = 0; # Sources received passively
55 my $statreq         = 0; # Number of servers pinged
56 my $statres         = 0; # Number of servers that answered
57 my $getsrc          = 0; # Number of UDP GetSources sent
58 my $gotsrc          = 0; # Number of UDP GotSources received
59 my $deadsrv         = 0; # Number of dead servers deleted
60 my $deadsrc         = 0; # Number of dead sources dropped
61 my $deadque         = 0; # Number of dead queued clients dropped
62 my $sec_id_ok       = 0; # Number of successful secure identifications
63 my $sec_id_fail     = 0; # Number of failed secure identifications
64 my $sec_id_ok_low   = 0; # Number of successful secure identifications (to LowID Clients)
65 my $sec_id_fail_low = 0; # Number of failed secure identifications (to LowID Clients)
66 my $low_calltot     = 0; # Number of LowID callback attempts
67 my $low_callok      = 0; # Number of successful LowID callbacks
68 my $low_callfail    = 0; # Number of failed LowID callbacks
69 my $cltotal         = 0; # Total number of clients interacted with
70 my $udpreasks       = 0; # Number of UDP reask attempts done
71 my $udptimeout      = 0; # Number of timed out UDP reasks
72 my $udpack          = 0; # Number of UDP ReaskAcks received
73 my $udpackPosZero   = 0; # Number of UDP ReaskAcks received with remote position 0
74 my $udpnotfound     = 0; # Number of UDP NotFound received
75 my $udpquefull      = 0; # Number of UDP QueueFull received
76 my $reqchunks       = 0; # Number of requested chunks
77 my $complchunks     = 0; # Number of completed chunks downloadings
78 my $complpackedc    = 0; # Number of completed packed chunks
79 my $downloadsess    = 0; # Number of download sessions
80 my $downloaddata    = 0; # Amount of download data received in sessions
81 my $downloadlongest = 0; # Longest download session
82 my $uploadsess      = 0; # Number of upload sessions
83 my $uploaddata      = 0; # Amount of upload data sent in sessions
84 my $uploadlongest   = 0; # Longest upload session
85 my $faileddownnnp   = 0; # Failed download sessions because of a NNP source
86 my $faileddownsess  = 0; # Failed download sessions (0 bytes transfered)
87 my $failedupsess    = 0; # Failed upload sessions (0 bytes transfered) (Total, Low and High ID Clients)
88 my $failedupsessh   = 0; # Failed upload sessions on HighID Clients
89 my $corrupt         = 0; # Amount of corrupted data dropped
90 my $serverconnL     = 0; # Connected to a server and got LowID (firewalled)
91 my $serverconnH     = 0; # Connected to a server and got HighID (tcp port accessible)
92
93 my $dropclrecoverQ  = 0; # The number of clients that reconnect to us within the next hour since we dropped them
94 my $dropclrecoverL  = 0; # The number of clients that reconnect to us after an hour since we dropped them
95
96 my %client_nnp;
97 my %timestamp;
98
99 my $linecnt1 =  0; # Counts logfile lines up to 25'000 and prints dot
100 my $linecnt2 =  0; # Counts logfile lines up to 1'000'000 and resets dots
101
102 $_ = <LOGFILE>;
103 m/^\[(\d+)-(\w+)-(\d+) (\d+):(\d+):(\d+)\]/ && ( $starttime = timelocal($6,$5,$4,$3,$2,$1)  );
104
105 printf "Please wait, parsing logfile";
106 while (<LOGFILE>) {
107         $linecnt1++;
108         if ($linecnt1 % 25000 == 0) {
109                 if ($linecnt1 % 1000000 == 0) {
110                         printf "\r                                                                    \r";
111                         printf "Please wait, parsing logfile";
112                 } else {
113                         printf ".";
114                 }
115         }
116         if (m/ed2k.secident/) {
117                 if (m/Ident succeeded/) {
118                         if (m/\[\d+:\d+\] /) {
119                                 # LowID Secure Ident
120                                 $sec_id_ok_low++;
121                         } else {
122                                 $sec_id_ok++;
123                         }
124                 } elsif (m/Ident failed!/) {
125                         if (m/\[\d+:\d+\] /) {
126                                 # LowID Secure Ident
127                                 $sec_id_fail_low++;
128                         } else {
129                                 $sec_id_fail++;
130                         }
131                 }
132         } elsif (m/LowID/) {
133                 if (m/Performing/) {
134                         $low_calltot++;
135                 } elsif (m/succeeded/) {
136                         $low_callok++;
137                 } elsif (m/timed out/) {
138                         $low_callfail++;
139                 } elsif (m/Cannot do LowID<->LowID reask/) {
140                         $deadsrc++;
141                 }
142         } elsif (m/\(Hello\)/) {
143                 if (m/ClientSoftware is Unknown (\S+)/) {
144                         $ClientUnknown{$1}++;
145                         $cltotal++;
146                 } elsif (m/ClientSoftware is (\w+)/) {
147                         $Client{$1}++;
148                         $cltotal++;
149                 }
150
151
152                 if (m/ClientSoftware is /) {
153                         # Ah, we spotted a new client. But perhaps it isn't really new? Lets check if we dropped him before.
154
155                         m/\[(\d+)-(\w+)-(\d+) (\d+):(\d+):(\d+)\] .+ \[(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d+)\]/;    # get date and ip:port
156                         # year=$1, month=$2, day=$3, hour=$4, minute=$5, second=$6, ipport=$7
157
158                         # if we "use warnings;" we need to check if $7 is defined first. I don't check for lowid clients here (no ip then)
159                         if (defined $timestamp{$7}) {           # see, we dropped it!
160                                 if (timelocal($6,$5,$4,$3,$2,$1) - $timestamp{$7} <= 3600) {
161                                         # we dropped it within the last hour!
162                                                 $dropclrecoverQ++;
163                                         # forget about the dropped source, it recovered.
164                                                 delete $timestamp{$7};
165                                 } elsif (timelocal($6,$5,$4,$3,$2,$1) - $timestamp{$7} > 3600) {
166                                         $dropclrecoverL++;
167                                         delete $timestamp{$7};
168                                 }
169                         }
170                 }
171
172         } elsif (m/chunk /) {
173                 if (m/Requesting chunk/) {
174                         $reqchunks++;
175                 } elsif (m/Completed chunk/) {
176                         $complchunks++;
177                 } elsif (m/Completed packed chunk/) {
178                         $complchunks++;
179                         $complpackedc++;
180                 } elsif (m/ \[(.+)\] Exception while sending chunk reqests: No more needed parts/) {
181                         # Remember that this client is NNP before we count a failed DownloadSession
182                         $client_nnp{$1}++;
183                 }
184         } elsif (m/ New ID: (\d+)/) {
185                 # 0x00ffffff is the highest LowID possible
186                 if ($1 > 16777215) {
187                         $serverconnH++;
188                 } else {
189                         $serverconnL++;
190                 }
191         } elsif (m/Passivly adding source/) {
192                 $passive++;
193         } elsif (m/GlobGetSources/) {
194                 if (m/Received (\d+) sources/) {
195                         $fromudp += $1;
196                         $gotsrc++;
197                 } elsif (m/Sending GlobGetSources/) {
198                         $getsrc++;
199                 }
200         } elsif (m/GlobStat/) {
201                 if (m/Sending GlobStatReq/) {
202                         $statreq++;
203                 } elsif (m/Received GlobStatRes/) {
204                         $statres++;
205                 } elsif (m/Removing dead server/) {
206                         $deadsrv++;
207                 }
208         } elsif (m/Source, but never connected/) {
209                 $deadsrc++;
210         } elsif (m/Dropping client \(unable to connect\)/) {
211                 $deadsrc++;
212         } elsif (m/Client is on different server/) {
213                 $deadsrc++;
214         } elsif (m/Error performing LowID callback/) {
215                 $deadsrc++;
216         } elsif (m/Unable to connect to client/) {
217                 $deadsrc++;
218         } elsif (m/Queue update/) {
219                 if (m/(\d+) dropped/) {
220                         $deadque += $1;
221                 }
222         } elsif (m/UDP Reask/) {
223                 if (m/in progress/) {
224                         $udpreasks++;
225                 } elsif (m/timed out/) {
226                         $udptimeout++;
227                 } elsif (m/Received ReaskAck/) {
228                         $udpack++;
229                         m/We are queued on position 0 for file/ && $udpackPosZero++;
230                 } elsif (m/Received FileNotFound/) {
231                         $udpnotfound++;
232                 } elsif (m/Received QueueFull/) {
233                         $udpquefull++;
234                 } elsif (m/and TCP Reask also failed/) {
235                         $deadsrc++;
236                         $dropcltcpfail++;               # This is ONLY for this match.
237
238                         m/\[(\d+)-(\w+)-(\d+) (\d+):(\d+):(\d+)\] .+ \[(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d+)\]/;    # get date and ip:port
239                         # year=$1, month=$2, day=$3, hour=$4, minute=$5, second=$6, ipport=$7
240
241                         # format for timelocal: $sec,$min,$hour,$mday,$mon,$year
242                         # Remember when we dropped that ip:port
243                         $timestamp{$7} = timelocal($6,$5,$4,$3,$2,$1);
244                 }
245         } elsif (m/Received (\d+) new sources from server/) {
246                 $fromserver += $1;
247         } elsif (m/ \[(.+)\] DownloadSessionEnd: Total received: 0 bytes/) {
248                 if (defined($client_nnp{$1})) {
249                         # OK, this client was marked as a NNP, so this is not a failed downloadsession
250                         delete $client_nnp{$1};
251                         $faileddownnnp++;
252                 } else {
253                         $faileddownsess++;
254                 }
255         } elsif (m/DownloadSessionEnd: Total received: (\d+) bytes/) {
256                 $downloadsess++;
257                 $downloaddata+=$1;
258                 if ($1 > $downloadlongest) {
259                         $downloadlongest=$1;
260                 }
261         } elsif (m/UploadSessionEnd: Total sent: 0 bytes/) {
262                 $failedupsess++;
263                 if (m/ \[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+\] /) {
264                         # If we match a complete IP in that line, we failed to upload to a high id client
265                         $failedupsessh++;
266                 }
267         } elsif (m/UploadSessionEnd: Total sent: (\d+) bytes/) {
268                 $uploadsess++;
269                 $uploaddata+=$1;
270                 if ($1 > $uploadlongest) {
271                         $uploadlongest=$1;
272                 }
273         } elsif (m/Corruption/) {
274                 if (m/Corruption found at (\d+)..(\d+)/) {
275                         $corrupt += $2-$1;
276                 }
277         } elsif (m/SourceExchange: Received (\d+) sources for/) {
278                 $fromsrcex += $1;
279         }
280         $lastline = $_;
281 }
282 close(LOGFILE);
283 printf "\r                                                                    \r";
284
285 if ($lastline =~ m/^\[(\d+)-(\w+)-(\d+) (\d+):(\d+):(\d+)\]/) { $endtime = timelocal($6,$5,$4,$3,$2,$1); }
286 $runtime = ($endtime - $starttime) / 60;
287
288 printf "---> Overall runtime for statistics below: ".sec2time($endtime - $starttime)."\n";
289
290 my $total = $fromserver+$passive+$fromudp+$fromsrcex;
291 if ($total and ($fromserver or $fromudp or $passive or $fromsrcex)) {
292         printf "-> Sources acquisition statistics:\n";
293         if ($fromserver) {
294                 printf "-----> From local server: %5d (%5.2f%%, %6.2f per minute)\n",
295                         $fromserver,
296                         $fromserver*100/$total,
297                         $fromserver/$runtime;
298         }
299         if ($fromudp) {
300                 printf "-----> From UDP server:   %5d (%5.2f%%, %6.2f per minute)\n",
301                         $fromudp,
302                         $fromudp*100/$total,
303                         $fromudp/$runtime;
304         }
305         if ($passive) {
306                 printf "-----> Passively:         %5d (%5.2f%%, %6.2f per minute)\n",
307                         $passive,
308                         $passive*100/$total,
309                         $passive/$runtime;
310         }
311         if ($fromsrcex) {
312                 printf "-----> SourceExchange:    %5d (%5.2f%%, %6.2f per minute)\n",
313                         $fromsrcex,
314                         $fromsrcex*100/$total,
315                         $fromsrcex/$runtime;
316         }
317         printf "-----> Total:             %5d (        %6.2f per minute)\n",
318                         $total,
319                         $total/$runtime;
320 }
321
322 if ($deadsrc or $deadque) {
323         printf "-> Clients dropping statistics:\n";
324         if ($deadsrc && $total) {
325                 printf "-----> Dropped %d dead sources  (%5.2f%%,  %5.2f per minute)\n",
326                         $deadsrc,
327                         $deadsrc*100/($total+$deadsrc),
328                         $deadsrc/$runtime;
329         }
330         if ($deadque) {
331                 printf "-----> Dropped %d dead clients from queue.\n",
332                         $deadque;
333         }
334         if ($dropcltcpfail) {
335                 printf "-------> Dropped %d clients because of failed TCP reasks (%4.2f per minute).\n",
336                         $dropcltcpfail,
337                         $dropcltcpfail/$runtime;
338                 printf "-------> %4d recovered within the next hour (%5.2f%% 'false positive' drops)\n",
339                         $dropclrecoverQ,
340                         $dropclrecoverQ*100/$dropcltcpfail;
341                 printf "-------> %4d recovered later\n",
342                         $dropclrecoverL;
343         }
344 }
345 if ($sec_id_ok or $sec_id_fail or $low_calltot) {
346         printf "-> Feature statistics:\n";
347         if ($sec_id_ok or $sec_id_fail) {
348                 printf "-----> HighId: Succeeded %5d out of %5d SecIdents (%5.2f%%, %5.2f per minute)\n",
349                         $sec_id_ok,
350                         $sec_id_ok+$sec_id_fail,
351                         $sec_id_ok*100/($sec_id_fail+$sec_id_ok),
352                         ($sec_id_ok+$sec_id_fail)/$runtime;
353         }
354         if ($sec_id_ok_low or $sec_id_fail_low) {
355                 printf "-----> LowId : Succeeded %5d out of %5d SecIdents (%5.2f%%, %5.2f per minute)\n",
356                         $sec_id_ok_low,
357                         $sec_id_ok_low+$sec_id_fail_low,
358                         $sec_id_ok_low*100/($sec_id_fail_low+$sec_id_ok_low),
359                         ($sec_id_ok_low+$sec_id_fail_low)/$runtime;
360         }
361         if ($low_calltot) {
362                 printf "-----> Succeeded %5d out of %5d LowID callbacks   (%5.2f%%, %5.2f per minute)\n",
363                         $low_callok,
364                         $low_calltot,
365                         $low_callok*100/$low_calltot,
366                         $low_calltot/$runtime;
367         }
368         if ($udpreasks) {
369                 printf "-----> Succeeded %5d out of %5d UDP reasks        (%5.2f%%, %5.2f per minute)\n",
370                         $udpreasks-$udptimeout,
371                         $udpreasks,
372                         ($udpreasks-$udptimeout)*100/$udpreasks,
373                         $udpreasks/$runtime;
374                 if ($udpack) {
375                         printf "----------> ReaskAck:  %5d (%5.2f%%)",
376                                 $udpack,
377                                 $udpack*100/$udpreasks;
378                         if ($udpackPosZero) {
379                                 printf ", %5d (%5.2f%%) indicating Position 0!",
380                                         $udpackPosZero,
381                                         $udpackPosZero*100/$udpack;
382                         }
383                         printf "\n";
384                 }
385                 if ($udpquefull) {
386                         printf "----------> QueueFull: %5d (%5.2f%%)\n",
387                                 $udpquefull,
388                                 $udpquefull*100/$udpreasks;
389                 }
390                 if ($udpnotfound) {
391                         printf "----------> NoFile:    %5d (%5.2f%%)\n",
392                                 $udpnotfound,
393                                 $udpnotfound*100/$udpreasks;
394                 }
395                 if ($udptimeout) {
396                         printf "----------> Timeout:   %5d (%5.2f%%)\n",
397                                 $udptimeout,
398                                 $udptimeout*100/$udpreasks;
399                 }
400         }
401 }
402 if ($statreq or $getsrc or $deadsrv or $serverconnH or $serverconnL) {
403         printf "-> Server communication statistics:\n";
404         if ($serverconnH or $serverconnL) {
405                 printf "-----> Connected to server %d times, and received High ID %d times.\n",
406                         $serverconnH+$serverconnL,
407                         $serverconnH;
408         }
409         if ($statreq) {
410                 printf "-----> Sent %d pings, got %d answers (%.2f%% lost)\n",
411                         $statreq,
412                         $statres,
413                         100-$statres*100/$statreq;
414         }
415         if ($getsrc) {
416                 printf "-----> Sent %d GetSources, got %d answers (%.2f%% effectiveness)\n",
417                         $getsrc,
418                         $gotsrc,
419                         $gotsrc*100/$getsrc;
420         }
421         if ($deadsrv) {
422                 printf "-----> Dropped %d dead servers.\n",
423                         $deadsrv;
424         }
425 }
426
427 printf "-> ClientSoftware statistics:\n";
428 foreach (sort { $Client{$b}<=>$Client{$a} } keys %Client) {
429         printf "-----> %15s: %6d (%5.2f%%)\n",
430                 $_,
431                 $Client{$_},
432                 $Client{$_}*100/$cltotal;
433 }
434 foreach (sort { $ClientUnknown{$b}<=>$ClientUnknown{$a} } keys %ClientUnknown) {
435         printf "-----> Unknown %7s: %6d (%5.2f%%)\n",
436                 $_,
437                 $ClientUnknown{$_},
438                 $ClientUnknown{$_}*100/$cltotal;
439 }
440 printf "-> Transfer statistics:\n";
441 if ($downloadsess) {
442         printf("-----> Downloaded %7.2f MB during %4d sessions (%5.2f MB avg per session)\n",
443                 $downloaddata/1024/1024, $downloadsess, $downloaddata/$downloadsess/1024/1024);
444 }
445 if ($uploadsess) {
446         printf("-----> Uploaded   %7.2f MB during %4d sessions (%5.2f MB avg per session)\n",
447                 $uploaddata/1024/1024, $uploadsess, $uploaddata/$uploadsess/1024/1024);
448 }
449 if ($downloadsess or $faileddownsess or $faileddownnnp) {
450         printf("-----> Longest download session: %7.2f MB",     $downloadlongest/1024/1024);
451         if ($faileddownsess or $faileddownnnp) {
452                 printf(", failed %d sessions (%5.2f%%) and %d were NNP clients (%5.2f%%)\n",
453                         $faileddownsess,
454                         $faileddownsess*100/($downloadsess+$faileddownsess+$faileddownnnp),
455                         $faileddownnnp,
456                         $faileddownnnp*100/($downloadsess+$faileddownsess+$faileddownnnp));
457         } else {
458                 printf("\n");
459         }
460 }
461 if ($uploadsess) {
462         printf("-----> Longest upload session:   %7.2f MB", $uploadlongest/1024/1024);
463         if ($failedupsess) {
464                 printf(", failed %d sessions (%5.2f%%)\n",
465                         $failedupsess, $failedupsess*100/($uploadsess+$failedupsess));
466         } else {
467                 printf("\n");
468         }
469 }
470 if ($failedupsessh) {
471         printf("-----> Failed %d upload sessions to High ID clients (%5.2f%%)\n",
472                 $failedupsess, $failedupsess*100/($uploadsess+$failedupsess));
473 }
474 if ($complchunks) {
475         printf "-----> Completed %d out of %d chunks (%5.2f%%, %4.2f per minute )\n",
476                 $complchunks,
477                 $reqchunks,
478                 $complchunks*100/$reqchunks,
479                 ($complchunks*100/$reqchunks)/$runtime;
480 }
481 if ($complchunks and $complpackedc) {
482         printf "-------> ... out of which %4d were zlib compressed (%5.2f%%, %4.2f per minute )\n",
483                 $complpackedc,
484                 $complpackedc*100/$complchunks,
485                 $complpackedc/$runtime;
486 }
487 if ($corrupt) {
488         printf "-----> Lost due to curruption:   %7.2f MB\n",
489                 $corrupt/1024/1024;
490 }
491
492 sub sec2time {
493  my $s = shift;
494   if ($s < 60) {
495     $s = int $s;
496     return "1 second" if ($s == 1);
497     return sprintf("%.1f seconds", $s);
498   } elsif ($s < 86400) {
499     my $hours = int $s / 3600;
500     $s %= 3600;
501     my $mins = int $s / 60;
502     $s %= 60;
503     return sprintf("%2.2uh %2.2um", $hours, $mins);
504   }
505   my $days = int $s / 86400;
506   $s %= 86400;
507   my $hours = int $s / 3600;
508   $s %= 3600;
509   my $mins = int $s / 60;
510   $s %= 60;
511   my $S = ($days == 1) ? "" : "s";
512   return sprintf("%u day$S %2.2uh %2.2um", $days, $hours, $mins);
513 }
Note: See TracBrowser for help on using the browser.