sync SVN r18206

This commit is contained in:
2026-09-25 12:35:54 +03:00
parent 63134daf6a
commit 7c8da7bf66
8 changed files with 1225 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
#!/usr/bin/perl
use strict; use warnings;
use JSON::PP;
my $file = shift @ARGV or die "usage: analyze_pi.pl <file.jsonl> [startline] [endline]\n";
my $startline = shift @ARGV || 1;
my $endline = shift @ARGV || 1e9;
my $json = JSON::PP->new;
my %calls; # id -> {name, args, reqts}
my @results; # {id, name, rests, iserror, errsnippet}
open my $fh, '<:encoding(UTF-8)', $file or die $!;
my $ln = 0;
while (my $line = <$fh>) {
$ln++;
next if $ln < $startline || $ln > $endline;
chomp $line;
next unless length $line;
my $obj = eval { $json->decode($line) };
next unless $obj;
my $msg = $obj->{message} or next;
if (($msg->{role} // '') eq 'assistant') {
my $ts = $msg->{timestamp};
for my $c (@{$msg->{content} || []}) {
next unless ($c->{type} // '') eq 'toolCall';
my $argstr = '';
if ($c->{arguments}) {
$argstr = $c->{arguments}{command} // $c->{arguments}{path} // $c->{arguments}{pattern} // encode_json_short($c->{arguments});
}
$calls{$c->{id}} = { name => $c->{name}, args => $argstr, reqts => $ts };
}
} elsif (($msg->{role} // '') eq 'toolResult') {
my $ts = $msg->{timestamp};
my $iserror = $msg->{isError} ? 1 : 0;
my $snippet = '';
if ($iserror) {
for my $c (@{$msg->{content} || []}) {
if (($c->{type}//'') eq 'text') { $snippet = substr($c->{text}//'',0,300); last; }
}
}
push @results, { id => $msg->{toolCallId}, name => $msg->{toolName}, rests => $ts, iserror => $iserror, snippet => $snippet };
}
}
close $fh;
sub encode_json_short { my $h = shift; my $s = eval { $json->encode($h) } // ''; return substr($s,0,200); }
# join
my @rows;
for my $r (@results) {
my $c = $calls{$r->{id}};
next unless $c;
my $dur = ($r->{rests} && $c->{reqts}) ? ($r->{rests} - $c->{reqts}) : undef;
push @rows, { name => $c->{name}, args => $c->{args}, dur => $dur, iserror => $r->{iserror}, snippet => $r->{snippet}, reqts=>$c->{reqts}, rests=>$r->{rests} };
}
# counts by tool name
my %cnt;
$cnt{$_->{name}}++ for @rows;
print "=== tool counts ===\n";
for my $k (sort { $cnt{$b} <=> $cnt{$a} } keys %cnt) { print "$k: $cnt{$k}\n"; }
print "\n=== top 10 longest ===\n";
my @sorted = sort { ($b->{dur}//0) <=> ($a->{dur}//0) } @rows;
for my $i (0..9) {
last unless $sorted[$i];
my $row = $sorted[$i];
my $a = $row->{args}; $a =~ s/\s+/ /g; $a = substr($a,0,100);
printf "%8dms %-6s %s\n", ($row->{dur}//-1), $row->{name}, $a;
}
print "\n=== errors ===\n";
for my $row (@rows) {
next unless $row->{iserror};
my $a = $row->{args}; $a =~ s/\s+/ /g; $a = substr($a,0,150);
my $s = $row->{snippet}; $s =~ s/\s+/ /g; $s = substr($s,0,200);
print "reqts=$row->{reqts} rests=$row->{rests} dur=".($row->{dur}//'?')."ms\n CMD: $a\n ERR: $s\n";
}
my $totaldur = 0;
$totaldur += ($_->{dur}//0) for @rows;
print "\n=== total tool time (sum durations, ms) === $totaldur\n";
print "=== total tool calls with duration === " . scalar(@rows) . "\n";