Skip to content

Instantly share code, notes, and snippets.

@dallaylaen
Last active February 5, 2023 11:13
Show Gist options
  • Save dallaylaen/7efbb6617c86d1026eba54d98f690283 to your computer and use it in GitHub Desktop.
Save dallaylaen/7efbb6617c86d1026eba54d98f690283 to your computer and use it in GitHub Desktop.
Nytprof for PSGI code
package nyt;
use strict;
use warnings;
=head1 NAME
nyt - Decorate existing code with Devel::NYTProf (for PSGI)
=head1 SYNOPSIS
perl -Mnyt `which plackup` -e 'nyt::prof( "app.psgi" )'
<some requests>
Ctrl-C
nytprofhtml
=head1 DESCRIPTION
L<Devel::NYTProf> sometimes results in garbled files when profiling
a web server.
This package preloads NYTProf, turns off profiling, and
wraps profiling on/off around any incoming code,
whether CODEREF or source file.
It also captures exit and signal interruption
to avoid incomplete profiler output.
=cut
BEGIN {
$ENV{NYTPROF} .= ":start=no:sigexit=1:posix_exit=1";
};
use Carp;
use Devel::NYTProf;
=head2 prof( $CODE || $filename )
Take a subroutine either directly or by loading a file
and return another subroutine.
=cut
sub prof($) {
my $app = shift;
my $code;
if (ref $app) {
$code = $app;
} else {
$app = "./$app" unless $app =~ m#^/#;
DB::enable_profile();
$code = do $app;
die "Failed to load $app: ".($@ || $!|| "unknown error")
unless ref $code;
DB::disable_profile();
};
croak "nyt::prof: this is NOT a coderef, won't run"
unless UNIVERSAL::isa( $code, 'CODE' );
return sub {
my (@arg) = @_;
DB::enable_profile();
my $ret;
my $ok = eval { $ret = $code->(@arg); 1 };
my $err = $ok ? ($@ || "Something happened") : '';
DB::disable_profile();
die $err unless $ok;
return ref $ret eq 'CODE' ? prof($ret) : $ret;
};
};
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment