line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mojolicious::Plugin::Status; |
2
|
1
|
|
|
1
|
|
1571
|
use Mojo::Base 'Mojolicious::Plugin'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
8
|
|
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
968
|
use BSD::Resource qw(getrusage); |
|
1
|
|
|
|
|
2407
|
|
|
1
|
|
|
|
|
5
|
|
5
|
1
|
|
|
1
|
|
136
|
use Time::HiRes qw(time); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
11
|
|
6
|
1
|
|
|
1
|
|
140
|
use Mojo::File qw(path); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
47
|
|
7
|
1
|
|
|
1
|
|
7
|
use Mojo::IOLoop; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
16
|
|
8
|
1
|
|
|
1
|
|
588
|
use Mojo::MemoryMap; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
12
|
|
9
|
1
|
|
|
1
|
|
44
|
use Mojo::Util qw(humanize_bytes); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
68
|
|
10
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
6
|
use constant MACOS => $^O eq 'darwin'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3528
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
our $VERSION = '1.16'; |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub register { |
16
|
1
|
|
|
1
|
1
|
88
|
my ($self, $app, $config) = @_; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Config |
19
|
1
|
|
33
|
|
|
7
|
my $prefix = $config->{route} // $app->routes->any('/mojo-status'); |
20
|
1
|
|
50
|
|
|
13
|
$prefix->to(return_to => $config->{return_to} // '/'); |
21
|
1
|
|
50
|
|
|
66
|
$self->{slowest} = $config->{slowest} // 10; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# Initialize cache |
24
|
1
|
|
|
|
|
9
|
my $map = $self->{map} = Mojo::MemoryMap->new($config->{size}); |
25
|
1
|
|
|
|
|
6
|
$map->writer->store({processed => 0, started => time, stats => _stats(), slowest => []}); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# Only the two built-in servers are supported for now |
28
|
1
|
|
|
2
|
|
6
|
$app->hook(before_server_start => sub { $self->_start(@_) }); |
|
2
|
|
|
|
|
6366
|
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# Static files |
31
|
1
|
|
|
|
|
37
|
my $resources = path(__FILE__)->sibling('resources'); |
32
|
1
|
|
|
|
|
122
|
push @{$app->static->paths}, $resources->child('public')->to_string; |
|
1
|
|
|
|
|
25
|
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Templates |
35
|
1
|
|
|
|
|
46
|
push @{$app->renderer->paths}, $resources->child('templates')->to_string; |
|
1
|
|
|
|
|
8
|
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# Routes |
38
|
1
|
|
|
|
|
46
|
$prefix->get('/' => {mojo_status => $self} => \&_dashboard)->name('mojo_status'); |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub _activity { |
42
|
2
|
|
|
2
|
|
44
|
my $all = shift; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# Workers |
45
|
2
|
|
|
|
|
5
|
my @table; |
46
|
2
|
|
|
|
|
6
|
for my $pid (sort keys %{$all->{workers}}) { |
|
2
|
|
|
|
|
11
|
|
47
|
2
|
|
|
|
|
5
|
my $worker = $all->{workers}{$pid}; |
48
|
2
|
|
|
|
|
27
|
my $cpu = sprintf '%.2f', $worker->{utime} + $worker->{stime}; |
49
|
2
|
|
|
|
|
9
|
my @worker = ($pid, $cpu, humanize_bytes($worker->{maxrss})); |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# Connections |
52
|
2
|
|
|
|
|
29
|
my $connections = $worker->{connections}; |
53
|
2
|
50
|
|
|
|
10
|
if (keys %$connections) { |
54
|
2
|
|
|
|
|
7
|
my $repeat; |
55
|
2
|
|
|
|
|
9
|
for my $cid (sort keys %$connections) { |
56
|
2
|
|
|
|
|
4
|
my $conn = $connections->{$cid}; |
57
|
2
|
50
|
|
|
|
9
|
@worker = ('', '', '') if $repeat++; |
58
|
2
|
|
|
|
|
7
|
my $bytes_read = humanize_bytes $conn->{bytes_read}; |
59
|
2
|
|
|
|
|
43
|
my $bytes_written = humanize_bytes $conn->{bytes_written}; |
60
|
2
|
|
|
|
|
30
|
my $rw = "$bytes_read/$bytes_written"; |
61
|
2
|
|
|
|
|
6
|
my @conn = ($conn->{client}, $rw, $conn->{processed}); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# Request |
64
|
2
|
50
|
|
|
|
9
|
if (my $req = $conn->{request}) { |
65
|
2
|
50
|
|
|
|
7
|
my $active = $req->{finished} ? 0 : 1; |
66
|
2
|
|
|
|
|
4
|
my ($rid, $proto) = @{$req}{qw(request_id protocol)}; |
|
2
|
|
|
|
|
7
|
|
67
|
|
|
|
|
|
|
|
68
|
2
|
|
|
|
|
8
|
my $str = "$req->{method} $req->{path}"; |
69
|
2
|
100
|
|
|
|
8
|
$str .= "?$req->{query}" if $req->{query}; |
70
|
2
|
50
|
|
|
|
10
|
$str .= " → $req->{status}" if $req->{status}; |
71
|
|
|
|
|
|
|
|
72
|
2
|
50
|
|
|
|
17
|
my $finished = $active ? time : $req->{finished}; |
73
|
2
|
|
|
|
|
15
|
my $time = sprintf '%.2f', $finished - $req->{started}; |
74
|
2
|
|
|
|
|
16
|
push @table, [@worker, @conn, $rid, $active, $time, $proto, $str]; |
75
|
|
|
|
|
|
|
} |
76
|
0
|
|
|
|
|
0
|
else { push @table, [@worker, @conn] } |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
} |
79
|
0
|
|
|
|
|
0
|
else { push @table, \@worker } |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
2
|
|
|
|
|
11
|
return \@table; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub _dashboard { |
86
|
9
|
|
|
9
|
|
14506
|
my $c = shift; |
87
|
|
|
|
|
|
|
|
88
|
9
|
|
|
|
|
31
|
my $map = $c->stash('mojo_status')->{map}; |
89
|
9
|
100
|
|
|
|
176
|
if ($c->param('reset')) { |
90
|
1
|
|
|
1
|
|
273
|
$map->writer->change(sub { @{$_}{qw(slowest stats)} = ([], _stats()) }); |
|
1
|
|
|
|
|
9
|
|
|
1
|
|
|
|
|
11
|
|
91
|
1
|
|
|
|
|
9
|
return $c->redirect_to('mojo_status'); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
8
|
|
|
|
|
1935
|
my $all = $map->writer->fetch; |
95
|
|
|
|
|
|
|
$c->respond_to( |
96
|
|
|
|
|
|
|
html => sub { |
97
|
2
|
|
|
2
|
|
978
|
$c->render( |
98
|
|
|
|
|
|
|
'mojo-status/dashboard', |
99
|
|
|
|
|
|
|
now => time, |
100
|
|
|
|
|
|
|
usage => humanize_bytes($map->usage), |
101
|
|
|
|
|
|
|
size => humanize_bytes($map->size), |
102
|
|
|
|
|
|
|
activity => _activity($all), |
103
|
|
|
|
|
|
|
slowest => _slowest($all), |
104
|
|
|
|
|
|
|
all => $all |
105
|
|
|
|
|
|
|
); |
106
|
|
|
|
|
|
|
}, |
107
|
8
|
|
|
|
|
44
|
json => {json => $all} |
108
|
|
|
|
|
|
|
); |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub _read_write { |
112
|
64
|
|
|
64
|
|
168
|
my ($all, $id) = @_; |
113
|
64
|
50
|
|
|
|
289
|
return unless my $stream = Mojo::IOLoop->stream($id); |
114
|
64
|
|
|
|
|
1108
|
@{$all->{workers}{$$}{connections}{$id}}{qw(bytes_read bytes_written)} |
|
64
|
|
|
|
|
528
|
|
115
|
|
|
|
|
|
|
= ($stream->bytes_read, $stream->bytes_written); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub _request { |
119
|
64
|
|
|
64
|
|
140
|
my ($self, $c) = @_; |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# Request start |
122
|
64
|
|
|
|
|
183
|
my $tx = $c->tx; |
123
|
64
|
|
|
|
|
368
|
my $id = $tx->connection; |
124
|
64
|
|
|
|
|
467
|
my $req = $tx->req; |
125
|
64
|
|
|
|
|
378
|
my $url = $req->url->to_abs; |
126
|
64
|
50
|
|
|
|
11352
|
my $proto = $tx->is_websocket ? 'ws' : 'http'; |
127
|
64
|
50
|
|
|
|
359
|
$proto .= 's' if $req->is_secure; |
128
|
|
|
|
|
|
|
$self->{map}->writer->change(sub { |
129
|
|
|
|
|
|
|
$_->{workers}{$$}{connections}{$id}{request} = { |
130
|
64
|
|
|
64
|
|
273
|
request_id => $req->request_id, |
131
|
|
|
|
|
|
|
method => $req->method, |
132
|
|
|
|
|
|
|
protocol => $proto, |
133
|
|
|
|
|
|
|
path => $url->path->to_abs_string, |
134
|
|
|
|
|
|
|
query => $url->query->to_string, |
135
|
|
|
|
|
|
|
started => time |
136
|
|
|
|
|
|
|
}; |
137
|
64
|
|
|
|
|
14372
|
_read_write($_, $id); |
138
|
64
|
|
|
|
|
236
|
$_->{workers}{$$}{connections}{$id}{client} = $tx->remote_address; |
139
|
64
|
|
|
|
|
1611
|
}); |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# Request end |
142
|
|
|
|
|
|
|
$tx->on( |
143
|
|
|
|
|
|
|
finish => sub { |
144
|
64
|
|
|
64
|
|
81453
|
my $tx = shift; |
145
|
|
|
|
|
|
|
$self->{map}->writer->change(sub { |
146
|
64
|
50
|
|
|
|
256
|
return unless my $worker = $_->{workers}{$$}; |
147
|
|
|
|
|
|
|
|
148
|
64
|
|
50
|
|
|
211
|
my $code = $tx->res->code || 0; |
149
|
64
|
50
|
|
|
|
726
|
if ($code > 499) { $_->{stats}{server_error}++ } |
|
0
|
50
|
|
|
|
0
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
150
|
0
|
|
|
|
|
0
|
elsif ($code > 399) { $_->{stats}{client_error}++ } |
151
|
2
|
|
|
|
|
4
|
elsif ($code > 299) { $_->{stats}{redirect}++ } |
152
|
62
|
|
|
|
|
113
|
elsif ($code > 199) { $_->{stats}{success}++ } |
153
|
0
|
|
|
|
|
0
|
elsif ($code) { $_->{stats}{info}++ } |
154
|
|
|
|
|
|
|
|
155
|
64
|
|
|
|
|
197
|
@{$worker->{connections}{$id}{request}}{qw(finished status)} = (time, $code); |
|
64
|
|
|
|
|
229
|
|
156
|
64
|
|
|
|
|
126
|
$worker->{connections}{$id}{processed}++; |
157
|
64
|
|
|
|
|
94
|
$worker->{processed}++; |
158
|
64
|
|
|
|
|
209
|
$_->{processed}++; |
159
|
64
|
|
|
|
|
251
|
}); |
160
|
|
|
|
|
|
|
} |
161
|
64
|
|
|
|
|
443
|
); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub _rendered { |
165
|
64
|
|
|
64
|
|
162
|
my ($self, $c) = @_; |
166
|
|
|
|
|
|
|
|
167
|
64
|
|
|
|
|
176
|
my $id = $c->tx->connection; |
168
|
|
|
|
|
|
|
$self->{map}->writer->change(sub { |
169
|
64
|
50
|
|
64
|
|
281
|
return unless my $conn = $_->{workers}{$$}{connections}{$id}; |
170
|
64
|
50
|
|
|
|
154
|
return unless my $req = $conn->{request}; |
171
|
64
|
|
|
|
|
225
|
$req->{time} = time - $req->{started}; |
172
|
64
|
|
|
|
|
237
|
@{$req}{qw(client status worker)} = ($conn->{client}, $c->res->code, $$); |
|
64
|
|
|
|
|
1048
|
|
173
|
|
|
|
|
|
|
|
174
|
64
|
|
|
|
|
133
|
my $slowest = $_->{slowest}; |
175
|
64
|
|
|
|
|
297
|
@$slowest = sort { $b->{time} <=> $a->{time} } @$slowest, $req; |
|
465
|
|
|
|
|
961
|
|
176
|
64
|
|
|
|
|
97
|
my %seen; |
177
|
64
|
|
|
|
|
143
|
@$slowest = grep { !$seen{"$_->{method} $_->{path}"}++ } @$slowest; |
|
324
|
|
|
|
|
1474
|
|
178
|
64
|
|
|
|
|
416
|
pop @$slowest while @$slowest > $self->{slowest}; |
179
|
64
|
|
|
|
|
846
|
}); |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
sub _resources { |
183
|
2
|
|
|
2
|
|
5
|
my $self = shift; |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
$self->{map}->writer->change(sub { |
186
|
2
|
|
|
2
|
|
42
|
@{$_->{workers}{$$}}{qw(utime stime maxrss)} = (getrusage)[0, 1, 2]; |
|
2
|
|
|
|
|
874
|
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# macOS actually returns bytes instead of kilobytes |
189
|
2
|
|
|
|
|
11
|
$_->{workers}{$$}{maxrss} = $_->{workers}{$$}{maxrss} * 1000 unless MACOS; |
190
|
|
|
|
|
|
|
|
191
|
2
|
|
|
|
|
5
|
for my $id (keys %{$_->{workers}{$$}{connections}}) { _read_write($_, $id) } |
|
2
|
|
|
|
|
12
|
|
|
0
|
|
|
|
|
0
|
|
192
|
2
|
|
|
|
|
7
|
}); |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
sub _slowest { |
196
|
2
|
|
|
2
|
|
5
|
my $all = shift; |
197
|
|
|
|
|
|
|
|
198
|
2
|
|
|
|
|
10
|
my @table; |
199
|
2
|
|
|
|
|
6
|
for my $req (@{$all->{slowest}}) { |
|
2
|
|
|
|
|
12
|
|
200
|
8
|
|
|
|
|
26
|
my $str = "$req->{method} $req->{path}"; |
201
|
8
|
100
|
|
|
|
26
|
$str .= "?$req->{query}" if $req->{query}; |
202
|
8
|
50
|
|
|
|
30
|
$str .= " → $req->{status}" if $req->{status}; |
203
|
8
|
|
|
|
|
33
|
my $time = sprintf '%.2f', $req->{time}; |
204
|
8
|
|
|
|
|
18
|
push @table, [$time, $str, @{$req}{qw(request_id worker client started)}]; |
|
8
|
|
|
|
|
27
|
|
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
2
|
|
|
|
|
15
|
return \@table; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
sub _start { |
211
|
2
|
|
|
2
|
|
18
|
my ($self, $server, $app) = @_; |
212
|
|
|
|
|
|
|
|
213
|
2
|
50
|
|
|
|
22
|
return $app->log->warn('Server not suported by Mojolicious::Plugin::Status') |
214
|
|
|
|
|
|
|
unless $server->isa('Mojo::Server::Daemon'); |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
# Register started workers |
217
|
|
|
|
|
|
|
Mojo::IOLoop->next_tick(sub { |
218
|
2
|
|
|
2
|
|
2146
|
$self->{map}->writer->change(sub { $_->{workers}{$$} = {started => time, processed => 0} }); |
|
2
|
|
|
|
|
21
|
|
219
|
2
|
|
|
|
|
22
|
}); |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# Remove stopped workers |
222
|
|
|
|
|
|
|
$server->on( |
223
|
|
|
|
|
|
|
reap => sub { |
224
|
0
|
|
|
0
|
|
0
|
my ($server, $pid) = @_; |
225
|
0
|
|
|
|
|
0
|
$self->{map}->writer->change(sub { delete $_->{workers}{$pid} }); |
|
0
|
|
|
|
|
0
|
|
226
|
|
|
|
|
|
|
} |
227
|
2
|
50
|
|
|
|
173
|
) if $server->isa('Mojo::Server::Prefork'); |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# Collect stats |
230
|
2
|
|
|
64
|
|
19
|
$app->hook(after_build_tx => sub { $self->_tx(@_) }); |
|
64
|
|
|
|
|
247005
|
|
231
|
2
|
|
|
64
|
|
47
|
$app->hook(before_dispatch => sub { $self->_request(@_) }); |
|
64
|
|
|
|
|
36532
|
|
232
|
2
|
|
|
64
|
|
30
|
$app->hook(after_dispatch => sub { $self->_rendered(@_) }); |
|
64
|
|
|
|
|
100381
|
|
233
|
2
|
|
|
2
|
|
28
|
Mojo::IOLoop->next_tick(sub { $self->_resources }); |
|
2
|
|
|
|
|
28
|
|
234
|
2
|
|
|
0
|
|
50
|
Mojo::IOLoop->recurring(5 => sub { $self->_resources }); |
|
0
|
|
|
|
|
0
|
|
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
2
|
|
|
2
|
|
23
|
sub _stats { {started => time, info => 0, success => 0, redirect => 0, client_error => 0, server_error => 0} } |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub _stream { |
240
|
1
|
|
|
1
|
|
5
|
my ($self, $id) = @_; |
241
|
|
|
|
|
|
|
|
242
|
1
|
|
|
|
|
9
|
my $stream = Mojo::IOLoop->stream($id); |
243
|
|
|
|
|
|
|
$stream->on( |
244
|
|
|
|
|
|
|
close => sub { |
245
|
1
|
50
|
|
1
|
|
32158
|
$self->{map}->writer->change(sub { delete $_->{workers}{$$}{connections}{$id} if $_->{workers}{$$} }); |
|
1
|
|
|
|
|
20
|
|
246
|
|
|
|
|
|
|
} |
247
|
1
|
|
|
|
|
26
|
); |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
sub _tx { |
251
|
64
|
|
|
64
|
|
160
|
my ($self, $tx, $app) = @_; |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
$tx->on( |
254
|
|
|
|
|
|
|
connection => sub { |
255
|
64
|
|
|
64
|
|
2030
|
my ($tx, $id) = @_; |
256
|
|
|
|
|
|
|
|
257
|
64
|
|
|
|
|
169
|
my $map = $self->{map}; |
258
|
64
|
100
|
|
|
|
206
|
return if $map->writer->fetch->{workers}{$$}{connections}{$id}; |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
$map->writer->change(sub { |
261
|
1
|
|
|
|
|
13
|
$_->{workers}{$$}{connections}{$id} = {started => time, processed => 0, bytes_read => 0, bytes_written => 0}; |
262
|
1
|
|
|
|
|
9
|
}); |
263
|
1
|
|
|
|
|
6
|
$self->_stream($id); |
264
|
|
|
|
|
|
|
} |
265
|
64
|
|
|
|
|
357
|
); |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
1; |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=encoding utf8 |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=head1 NAME |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
Mojolicious::Plugin::Status - Mojolicious server status |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=head1 SYNOPSIS |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
# Mojolicious |
279
|
|
|
|
|
|
|
$self->plugin('Status'); |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
# Mojolicious::Lite |
282
|
|
|
|
|
|
|
plugin 'Status'; |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
# Secure access to the server status ui with Basic authentication |
285
|
|
|
|
|
|
|
my $under = $self->routes->under('/status' => sub ($c) { |
286
|
|
|
|
|
|
|
return 1 if $c->req->url->to_abs->userinfo eq 'Bender:rocks'; |
287
|
|
|
|
|
|
|
$c->res->headers->www_authenticate('Basic'); |
288
|
|
|
|
|
|
|
$c->render(text => 'Authentication required!', status => 401); |
289
|
|
|
|
|
|
|
return undef; |
290
|
|
|
|
|
|
|
}); |
291
|
|
|
|
|
|
|
$self->plugin('Status' => {route => $under}); |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head1 DESCRIPTION |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=begin html |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
width="600px"> |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=end html |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
L is a L plugin providing a server status ui for L and |
305
|
|
|
|
|
|
|
L. Note that this module is B and should therefore only be used for debugging |
306
|
|
|
|
|
|
|
purposes. |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head1 OPTIONS |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
L supports the following options. |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=head2 return_to |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# Mojolicious::Lite |
315
|
|
|
|
|
|
|
plugin Status => {return_to => 'some_route'}; |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Name of route or path to return to when leaving the server status ui, defaults to C>. |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=head2 route |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# Mojolicious::Lite |
322
|
|
|
|
|
|
|
plugin Status => {route => app->routes->any('/status')}; |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
L object to attach the server status ui to, defaults to generating a new one with the |
325
|
|
|
|
|
|
|
prefix C. |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=head2 size |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
# Mojolicious::Lite |
330
|
|
|
|
|
|
|
plugin Status => {size => 1234}; |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
Size of anonymous mapped memory to use for storing statistics, defaults to C<52428800> (50 MiB). |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
=head2 slowest |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
# Mojolicious::Lite |
337
|
|
|
|
|
|
|
plugin Status => {slowest => 5}; |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
Number of slowest requests to track, defaults to C<10>. |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=head1 METHODS |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
L inherits all methods from L and implements the following new ones. |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=head2 register |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
my $route = $plugin->register(Mojolicious->new); |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
Register renderer and helper in L application. |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head1 BUNDLED FILES |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
The L distribution includes a few files with different licenses that have been bundled for |
354
|
|
|
|
|
|
|
internal use. |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=head2 Artwork |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
Copyright (C) 2018, Sebastian Riedel. |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
Licensed under the CC-SA License, Version 4.0 L. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=head2 Bootstrap |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
Copyright (C) 2011-2018 The Bootstrap Authors. |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
Licensed under the MIT License, L. |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
=head2 Font Awesome |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
Copyright (C) Dave Gandy. |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
Licensed under the MIT License, L, and the SIL OFL 1.1, |
373
|
|
|
|
|
|
|
L. |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=head1 AUTHOR |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
Sebastian Riedel, C. |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
Copyright (C) 2018-2021, Sebastian Riedel and others. |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version |
384
|
|
|
|
|
|
|
2.0. |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
=head1 SEE ALSO |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
L, L, L. |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=cut |