← Index
NYTProf Performance Profile   « line view »
For starman worker -M FindBin --max-requests 50 --workers 2 --user=kohadev-koha --group kohadev-koha --pid /var/run/koha/kohadev/plack.pid --daemonize --access-log /var/log/koha/kohadev/plack.log --error-log /var/log/koha/kohadev/plack-error.log -E deployment --socket /var/run/koha/kohadev/plack.sock /etc/koha/sites/kohadev/plack.psgi
  Run on Fri Jan 8 14:31:06 2016
Reported on Fri Jan 8 14:33:30 2016

Filename/usr/share/perl5/Plack/Middleware/Debug.pm
StatementsExecuted 0 statements in 0s
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Plack::Middleware::Debug;
2use 5.008_001;
3use strict;
4use warnings;
5use parent qw(Plack::Middleware);
6our $VERSION = '0.16';
7
8use Encode;
9use File::ShareDir;
10use Plack::App::File;
11use Plack::Builder;
12use Plack::Util::Accessor qw(panels renderer files);
13use Plack::Util;
14use Plack::Middleware::Debug::Panel;
15use Text::MicroTemplate;
16use Try::Tiny;
17
18sub TEMPLATE {
19 <<'EOTMPL' }
20% my $stash = $_[0];
21<script type="text/javascript" charset="utf-8">
22 // When jQuery is sourced, it's going to overwrite whatever might be in the
23 // '$' variable, so store a reference of it in a temporary variable...
24 var _$ = window.$;
25 if (typeof jQuery == 'undefined') {
26 var jquery_url = '<%= $stash->{BASE_URL} %>/debug_toolbar/jquery.js';
27 document.write(unescape('%3Cscript src="' + jquery_url + '" type="text/javascript"%3E%3C/script%3E'));
28 }
29</script>
30<script type="text/javascript" src="<%= $stash->{BASE_URL} %>/debug_toolbar/toolbar.min.js"></script>
31<script type="text/javascript" charset="utf-8">
32 // Now that jQuery is done loading, put the '$' variable back to what it was...
33 var $ = _$;
34</script>
35<style type="text/css">
36 @import url(<%= $stash->{BASE_URL} %>/debug_toolbar/toolbar.min.css);
37</style>
38<div id="plDebug">
39 <div style="display:none;" id="plDebugToolbar">
40 <ul id="plDebugPanelList">
41% if ($stash->{panels}) {
42 <li><a id="plHideToolBarButton" href="#" title="Hide Toolbar">Hide &raquo;</a></li>
43% } else {
44 <li id="plDebugButton">DEBUG</li>
45% }
46% for my $panel (reverse @{$stash->{panels}}) {
47 <li>
48% if ($panel->content) {
49 <a href="<%= $panel->url %>" title="<%= $panel->title %>" class="<%= $panel->dom_id %>">
50% } else {
51 <div class="contentless">
52% }
53 <%= $panel->nav_title %>
54% if ($panel->nav_subtitle) {
55 <br><small><%= $panel->nav_subtitle %></small>
56% }
57% if ($panel->content) {
58 </a>
59% } else {
60 </div>
61% }
62 </li>
63% } # end for
64 </ul>
65 </div>
66 <div style="display:none;" id="plDebugToolbarHandle">
67 <a title="Show Toolbar" id="plShowToolBarButton" href="#">&laquo;</a>
68 </div>
69% for my $panel (reverse @{$stash->{panels}}) {
70% if ($panel->content) {
71 <div id="<%= $panel->dom_id %>" class="panelContent">
72 <div class="plDebugPanelTitle">
73 <a href="" class="plDebugClose">Close</a>
74 <h3><%= $panel->title %></h3>
75 </div>
76 <div class="plDebugPanelContent">
77 <div class="scroll">
78% my $content = ref $panel->content eq 'CODE' ? $panel->content->() : $panel->content;
79% $content = Encode::encode('latin1', $content, Encode::FB_XMLCREF);
80 <%= Text::MicroTemplate::encoded_string($content) %>
81 </div>
82 </div>
83 </div>
84% }
85% } # end for
86 <div id="plDebugWindow" class="panelContent"></div>
87</div>
88EOTMPL
89
90sub default_panels {
91 [qw(Environment Response Timer Memory Session DBITrace)];
92}
93
94sub prepare_app {
95 my $self = shift;
96 my $root = try { File::ShareDir::dist_dir('Plack-Middleware-Debug') } || 'share';
97
98 my $builder = Plack::Builder->new;
99
100 for my $spec (@{ $self->panels || $self->default_panels }) {
101 my ($package, %args);
102 if (ref $spec eq 'ARRAY') {
103 # For the backward compatiblity
104 # [ 'PanelName', key1 => $value1, ... ]
105 $package = shift @$spec;
106 $builder->add_middleware("Debug::$package", @$spec);
107 } else {
108 # $spec could be a code ref (middleware) or a string
109 # copy so that we do not change default_panels
110 my $spec_copy = $spec;
111 $spec_copy = "Debug::$spec_copy" unless ref $spec_copy;
112 $builder->add_middleware($spec_copy);
113 }
114 }
115
116 $self->app( $builder->to_app($self->app) );
117
118 $self->renderer(
119 Text::MicroTemplate->new(
120 template => $self->TEMPLATE,
121 tag_start => '<%',
122 tag_end => '%>',
123 line_start => '%',
124 )->build
125 );
126
127 $self->files(Plack::App::File->new(root => $root));
128}
129
130sub call {
131 my ($self, $env) = @_;
132 if ($env->{PATH_INFO} =~ m!^/debug_toolbar!) {
133 return $self->files->call($env);
134 }
135
136 $env->{'plack.debug.panels'} = [];
137
138 my $res = $self->app->($env);
139 $self->response_cb($res, sub {
140 my $res = shift;
141 my $headers = Plack::Util::headers($res->[1]);
142 my $panels = delete $env->{'plack.debug.panels'};
143 if ( ! Plack::Util::status_with_no_entity_body($res->[0])
144 && ($headers->get('Content-Type') || '') =~ m!^(?:text/html|application/xhtml\+xml)!) {
145
146 my $vars = {
147 panels => [ grep !$_->disabled, @$panels ],
148 BASE_URL => $env->{SCRIPT_NAME},
149 };
150
151 my $content = $self->renderer->($vars);
152 return sub {
153 my $chunk = shift;
154 return unless defined $chunk;
155311µs $chunk =~ s!(?=</body>)!$content!i;
# spent 11µs making 3 calls to Text::MicroTemplate::EncodedString::__ANON__, avg 4µs/call
156 return $chunk;
157 };
158 }
159 });
160}
161
1621;
163__END__
164
165=head1 NAME
166
167Plack::Middleware::Debug - display information about the current request/response
168
169=head1 SYNOPSIS
170
171 enable "Debug";
172
173=head1 DESCRIPTION
174
175The debug middleware offers a configurable set of panels that displays
176information about the current request and response. The information is
177generated only for responses with a status of 200 (C<OK>) and a
178C<Content-Type> that contains C<text/html> or C<application/xhtml+xml>
179and is embedded in the HTML that is sent back to the browser. Also the
180code is injected directly before the C<< </body> >> tag so if there is
181no such tag, the information will not be injected.
182
183To enable the middleware, just use L<Plack::Builder> as usual in your C<.psgi>
184file:
185
186 use Plack::Builder;
187
188 builder {
189 enable 'Debug', panels => [ qw(DBITrace Memory Timer) ];
190 $app;
191 };
192
193The C<Debug> middleware takes an optional C<panels> argument whose value is
194expected to be a reference to an array of panel specifications. If given,
195only those panels will be enabled. If you don't pass a C<panels>
196argument, the default list of panels - C<Environment>, C<Response>,
197C<Timer>, C<Memory>, C<Session> and C<DBITrace> - will be enabled, each with
198their default settings, and automatically disabled if their targer modules or
199middleware components are not loaded.
200
201Each panel specification can take one of three forms:
202
203=over 4
204
205=item A string
206
207This is interpreted as the base name of a panel in the
208C<Plack::Middeware::Debug::> namespace. The panel class is loaded and a panel
209object is created with its default settings.
210
211=item An array reference
212
213If you need to pass arguments to the panel object as it is created,
214you may use this form (But see below).
215
216The first element of the array reference has to be the panel base
217name. The remaining elements are key/value pairs to be passed to the
218panel.
219
220For example:
221
222 builder {
223 enable 'Debug', panels =>
224 [ qw(Environment Response Timer Memory),
225 [ 'DBITrace', level => 2 ]
226 ];
227 $app;
228 };
229
230Because each panel is a middleware component, you can write this way
231as well:
232
233 builder {
234 enable 'Debug'; # load defaults
235 enable 'Debug::DBITrace', level => 2;
236 $app;
237 };
238
239Note that the C<<enable 'Debug'>> line should come before other Debug
240panels because of the order middleware components are executed.
241
242=item Custom middleware
243
244You can also pass a Panel middleware component. This might be useful
245if you have custom debug panels in your framework or web application.
246
247=back
248
249=head1 HOW TO WRITE YOUR OWN DEBUG PANEL
250
251The C<Debug> middleware is designed to be easily extensible. You might
252want to write a custom debug panel for your framework or for your web
253application. Each debug panel is also a Plack middleware copmonent and
254is easy to write one.
255
256Let's look at the anatomy of the C<Timer> debug panel. Here is the code from
257that panel:
258
259 package Plack::Middleware::Debug::Timer;
260 use Time::HiRes;
261
262 use parent qw(Plack::Middleware::Debug::Base);
263
264 sub run {
265 my($self, $env, $panel) = @_;
266
267 my $start = [ Time::HiRes::gettimeofday ];
268
269 return sub {
270 my $res = shift;
271
272 my $end = [ Time::HiRes::gettimeofday ];
273 my $elapsed = sprintf '%.6f s', Time::HiRes::tv_interval $start, $end;
274
275 $panel->nav_subtitle($elapsed);
276 $panel->content(
277 $self->render_list_pairs(
278 [ Start => $self->format_time($start),
279 End => $self->format_time($end),
280 Elapsed => $elapsed ],
281 ),
282 );
283 };
284 }
285
286 sub format_time { ... }
287
288To write a new debug panel, place it in the C<Plack::Middleware::Debug::>
289namespace. In our example, the C<Timer> panel lives in the
290C<Plack::Middleware::Debug::Timer> package.
291
292The only thing your panel should do is to subclass
293L<Plack::Middleware::Debug::Base>. This does most of the things a
294middleware component should do as a Plack middleware, so you only need
295to override C<run> method to profile and create the panel content.
296
297 sub run {
298 my($self, $env, $panel) = @_;
299
300 # Do something before the application runs
301
302 return sub {
303 my $res = shift;
304
305 # Do something after the application returns
306
307 };
308 }
309
310You can create as many lexical variables as you need and reference
311that in the returned callback as a closure, and update the content of
312of the C<$panel> which is Plack::Middleware::Debug::Panel object.
313
314In our C<Timer> example we want to list three key/value pairs: the
315start time, the end time and the elapsed time. We use the
316C<render_list_pairs()> method to place the pairs in the order we
317want. There is also a C<render_hash()> and C<render_lines()> method,
318to render a hash keys and values, as well as just text lines (e.g. log
319messages).
320
321=head1 BUGS AND LIMITATIONS
322
323Please report any bugs or feature requests through the web interface at
324L<http://rt.cpan.org>.
325
326=head1 INSTALLATION
327
328See perlmodinstall for information and options on installing Perl modules.
329
330=head1 AVAILABILITY
331
332The latest version of this module is available from the Comprehensive Perl
333Archive Network (CPAN). Visit L<http://www.perl.com/CPAN/> to find a CPAN site
334near you. Or see L<http://search.cpan.org/dist/Plack-Middleware-Debug/>.
335
336The development version lives at
337L<http://github.com/miyagawa/plack-middleware-debug/>. Instead of sending
338patches, please fork this project using the standard git and github
339infrastructure.
340
341=head1 AUTHORS
342
343Marcel Grunauer, C<< <marcel@cpan.org> >>
344
345Tatsuhiko Miyagawa, C<< <miyagawa@bulknews.net> >>
346
347=head1 COPYRIGHT AND LICENSE
348
349Copyright 2009 by Marcel GrE<uuml>nauer
350
351This library is free software; you can redistribute it and/or modify
352it under the same terms as Perl itself.
353
354=head1 SEE ALSO
355
356The debug middleware is heavily influenced (that is, adapted from) the Django
357Debug Toolbar - see L<http://github.com/robhudson/django-debug-toolbar>.
358
359=cut