.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Plack::Middleware::Debug 3pm" .TH Plack::Middleware::Debug 3pm "2020-05-08" "perl v5.30.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Plack::Middleware::Debug \- display information about the current request/response .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& enable "Debug"; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The debug middleware offers a configurable set of panels that displays information about the current request and response. The information is generated only for responses with a status of 200 (\f(CW\*(C`OK\*(C'\fR) and a \&\f(CW\*(C`Content\-Type\*(C'\fR that contains \f(CW\*(C`text/html\*(C'\fR or \f(CW\*(C`application/xhtml+xml\*(C'\fR and is embedded in the \s-1HTML\s0 that is sent back to the browser. .PP Note that the code is injected \fBdirectly before the closing tag\fR (\f(CW\*(C`\*(C'\fR) so if there is no such tag, the debug panel will not be injected at all. .PP To enable the middleware, just use Plack::Builder as usual in your \f(CW\*(C`.psgi\*(C'\fR file: .PP .Vb 1 \& use Plack::Builder; \& \& builder { \& enable \*(AqDebug\*(Aq, panels => [ qw(DBITrace Memory Timer) ]; \& $app; \& }; .Ve .PP The \f(CW\*(C`Debug\*(C'\fR middleware takes an optional \f(CW\*(C`panels\*(C'\fR argument whose value is expected to be a reference to an array of panel specifications. If given, only those panels will be enabled. If you don't pass a \f(CW\*(C`panels\*(C'\fR argument, the default list of panels \- \f(CW\*(C`Environment\*(C'\fR, \f(CW\*(C`Response\*(C'\fR, \&\f(CW\*(C`Timer\*(C'\fR, \f(CW\*(C`Memory\*(C'\fR, \f(CW\*(C`Session\*(C'\fR and \f(CW\*(C`DBITrace\*(C'\fR \- will be enabled, each with their default settings, and automatically disabled if their target modules or middleware components are not loaded. .PP Each panel specification can take one of three forms: .IP "A string" 4 .IX Item "A string" This is interpreted as the base name of a panel in the \&\f(CW\*(C`Plack::Middeware::Debug::\*(C'\fR namespace, unless preceded by \f(CW\*(C`+\*(C'\fR, in which case it's interpreted as an absolute name similar to how Plack::Builder handles such names, e.g. \f(CW\*(C`+My::Plack::Middleware::Debug::Something\*(C'\fR. .Sp The panel class is loaded and a panel object is created with its default settings. .IP "An array reference" 4 .IX Item "An array reference" If you need to pass arguments to the panel object as it is created, you may use this form (But see below). .Sp The first element of the array reference has to be the panel base name. The remaining elements are key/value pairs to be passed to the panel. .Sp For example: .Sp .Vb 7 \& builder { \& enable \*(AqDebug\*(Aq, panels => \& [ qw(Environment Response Timer Memory), \& [ \*(AqDBITrace\*(Aq, level => 2 ] \& ]; \& $app; \& }; .Ve .Sp Because each panel is a middleware component, you can write this way as well: .Sp .Vb 5 \& builder { \& enable \*(AqDebug\*(Aq; # load defaults \& enable \*(AqDebug::DBITrace\*(Aq, level => 2; \& $app; \& }; .Ve .Sp Note that the \f(CW\*(C` line should come before other Debug panels because of the order middleware components are executed. .IP "Custom middleware" 4 .IX Item "Custom middleware" You can also pass a Panel middleware component. This might be useful if you have custom debug panels in your framework or web application. .SH "HOW TO WRITE YOUR OWN DEBUG PANEL" .IX Header "HOW TO WRITE YOUR OWN DEBUG PANEL" The \f(CW\*(C`Debug\*(C'\fR middleware is designed to be easily extensible. You might want to write a custom debug panel for your framework or for your web application. Each debug panel is also a Plack middleware component and is easy to write one. .PP Let's look at the anatomy of the \f(CW\*(C`Timer\*(C'\fR debug panel. Here is the code from that panel: .PP .Vb 2 \& package Plack::Middleware::Debug::Timer; \& use Time::HiRes; \& \& use parent qw(Plack::Middleware::Debug::Base); \& \& sub run { \& my($self, $env, $panel) = @_; \& \& my $start = [ Time::HiRes::gettimeofday ]; \& \& return sub { \& my $res = shift; \& \& my $end = [ Time::HiRes::gettimeofday ]; \& my $elapsed = sprintf \*(Aq%.6f s\*(Aq, Time::HiRes::tv_interval $start, $end; \& \& $panel\->nav_subtitle($elapsed); \& $panel\->content( \& $self\->render_list_pairs( \& [ Start => $self\->format_time($start), \& End => $self\->format_time($end), \& Elapsed => $elapsed ], \& ), \& ); \& }; \& } \& \& sub format_time { ... } .Ve .PP To write a new debug panel, place it in the \f(CW\*(C`Plack::Middleware::Debug::\*(C'\fR namespace. In our example, the \f(CW\*(C`Timer\*(C'\fR panel lives in the \&\f(CW\*(C`Plack::Middleware::Debug::Timer\*(C'\fR package. .PP The only thing your panel should do is to subclass Plack::Middleware::Debug::Base. This does most of the things a middleware component should do as a Plack middleware, so you only need to override \f(CW\*(C`run\*(C'\fR method to profile and create the panel content. .PP .Vb 2 \& sub run { \& my($self, $env, $panel) = @_; \& \& # Do something before the application runs \& \& return sub { \& my $res = shift; \& \& # Do something after the application returns \& \& }; \& } .Ve .PP You can create as many lexical variables as you need and reference that in the returned callback as a closure, and update the content of of the \f(CW$panel\fR which is Plack::Middleware::Debug::Panel object. .PP In our \f(CW\*(C`Timer\*(C'\fR example we want to list three key/value pairs: the start time, the end time and the elapsed time. We use the \&\f(CW\*(C`render_list_pairs()\*(C'\fR method to place the pairs in the order we want. There is also a \f(CW\*(C`render_hash()\*(C'\fR and \f(CW\*(C`render_lines()\*(C'\fR method, to render a hash keys and values, as well as just text lines (e.g. log messages). .SH "BUGS AND LIMITATIONS" .IX Header "BUGS AND LIMITATIONS" Please report any bugs or feature requests through the web interface at . .SH "INSTALLATION" .IX Header "INSTALLATION" See perlmodinstall for information and options on installing Perl modules. .SH "AVAILABILITY" .IX Header "AVAILABILITY" The latest version of this module is available from the Comprehensive Perl Archive Network (\s-1CPAN\s0). Visit to find a \s-1CPAN\s0 site near you. Or see . .PP The development version lives at . Instead of sending patches, please fork this project using the standard git and github infrastructure. .SH "AUTHORS" .IX Header "AUTHORS" Marcel Grunauer, \f(CW\*(C`\*(C'\fR .PP Tatsuhiko Miyagawa, \f(CW\*(C`\*(C'\fR .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright 2009 by Marcel Gru\*:nauer .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" The debug middleware is heavily influenced (that is, adapted from) the Django Debug Toolbar \- see .