| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Plack::Middleware::Statsd; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# ABSTRACT: send statistics to statsd |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# RECOMMEND PREREQ: Net::Statsd::Tiny v0.3.0 |
|
6
|
|
|
|
|
|
|
# RECOMMEND PREREQ: HTTP::Status 6.16 |
|
7
|
|
|
|
|
|
|
# RECOMMEND PREREQ: List::Util::XS |
|
8
|
|
|
|
|
|
|
# RECOMMEND PREREQ: Ref::Util::XS |
|
9
|
|
|
|
|
|
|
|
|
10
|
5
|
|
|
5
|
|
1217326
|
use v5.20; |
|
|
5
|
|
|
|
|
19
|
|
|
11
|
5
|
|
|
5
|
|
24
|
use warnings; |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
301
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
5
|
|
|
5
|
|
23
|
use parent qw/ Plack::Middleware /; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
33
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
5
|
|
|
5
|
|
29723
|
use Digest::SHA 5.96 qw/ hmac_sha256_base64 /; |
|
|
5
|
|
|
|
|
12240
|
|
|
|
5
|
|
|
|
|
539
|
|
|
16
|
5
|
|
|
5
|
|
35
|
use List::Util qw/ first /; |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
310
|
|
|
17
|
5
|
|
|
5
|
|
24
|
use Plack::Util; |
|
|
5
|
|
|
|
|
7
|
|
|
|
5
|
|
|
|
|
169
|
|
|
18
|
|
|
|
|
|
|
use Plack::Util::Accessor |
|
19
|
5
|
|
|
5
|
|
19
|
qw/ client sample_rate histogram increment set_add secure_set_add secure_set_key catch_errors /; |
|
|
5
|
|
|
|
|
7
|
|
|
|
5
|
|
|
|
|
30
|
|
|
20
|
5
|
|
|
5
|
|
2898
|
use Ref::Util qw/ is_coderef /; |
|
|
5
|
|
|
|
|
10374
|
|
|
|
5
|
|
|
|
|
364
|
|
|
21
|
5
|
|
|
5
|
|
30
|
use Scalar::Util qw/ weaken /; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
216
|
|
|
22
|
5
|
|
|
5
|
|
20
|
use Time::HiRes; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
38
|
|
|
23
|
5
|
|
|
5
|
|
2521
|
use Try::Tiny; |
|
|
5
|
|
|
|
|
7405
|
|
|
|
5
|
|
|
|
|
297
|
|
|
24
|
|
|
|
|
|
|
|
|
25
|
5
|
|
|
5
|
|
1831
|
use experimental qw/ postderef signatures /; |
|
|
5
|
|
|
|
|
9469
|
|
|
|
5
|
|
|
|
|
23
|
|
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
our $VERSION = 'v0.9.3'; |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# Note: You may be able to omit the client if there is a client |
|
30
|
|
|
|
|
|
|
# defined in the environment hash at C, and the |
|
31
|
|
|
|
|
|
|
# L, L and L are set. But that |
|
32
|
|
|
|
|
|
|
# is a strange case and unsupported. |
|
33
|
|
|
|
|
|
|
|
|
34
|
5
|
|
|
5
|
1
|
323656
|
sub prepare_app($self) { |
|
|
5
|
|
|
|
|
23
|
|
|
|
5
|
|
|
|
|
7
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
5
|
50
|
|
|
|
28
|
if ( my $client = $self->client ) { |
|
37
|
5
|
|
|
|
|
214
|
foreach my $init ( |
|
38
|
|
|
|
|
|
|
[qw/ histogram timing_ms timing /], |
|
39
|
|
|
|
|
|
|
[qw/ increment increment /], |
|
40
|
|
|
|
|
|
|
[qw/ set_add set_add /], |
|
41
|
|
|
|
|
|
|
[qw/ secure_set_add secure_set_add /], |
|
42
|
|
|
|
|
|
|
) |
|
43
|
|
|
|
|
|
|
{ |
|
44
|
20
|
|
|
|
|
87
|
my ( $attr, @methods ) = $init->@*; |
|
45
|
20
|
100
|
|
|
|
49
|
next if defined $self->$attr; |
|
46
|
19
|
|
|
21
|
|
126
|
my $method = first { $client->can($_) } @methods; |
|
|
21
|
|
|
|
|
113
|
|
|
47
|
19
|
100
|
100
|
|
|
141
|
warn "No $attr method found for client " . ref($client) |
|
48
|
|
|
|
|
|
|
unless defined $method || $attr eq "secure_set_add"; |
|
49
|
58
|
|
|
|
|
60
|
$self->$attr( |
|
50
|
58
|
|
|
58
|
|
80
|
sub($env, @args) { |
|
|
58
|
|
|
|
|
107
|
|
|
|
58
|
|
|
|
|
57
|
|
|
51
|
58
|
100
|
|
|
|
81
|
return unless defined $method; |
|
52
|
|
|
|
|
|
|
try { |
|
53
|
56
|
|
|
|
|
2407
|
$client->$method( grep { defined $_ } @args ); |
|
|
133
|
|
|
|
|
307
|
|
|
54
|
|
|
|
|
|
|
} |
|
55
|
|
|
|
|
|
|
catch { |
|
56
|
2
|
|
|
|
|
37
|
my ($e) = $_; |
|
57
|
2
|
50
|
|
|
|
6
|
if (my $logger = $env->{'psgix.logger'}) { |
|
58
|
2
|
|
|
|
|
7
|
$logger->( { message => $e, level => 'error' } ); |
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
else { |
|
61
|
0
|
|
|
|
|
0
|
$env->{'psgi.errors'}->print($e); |
|
62
|
|
|
|
|
|
|
} |
|
63
|
56
|
|
|
|
|
295
|
}; |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
} |
|
66
|
19
|
|
|
|
|
62
|
); |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
|
|
69
|
5
|
50
|
|
|
|
54
|
unless ( $client->can("secure_set_add") ) { |
|
70
|
5
|
100
|
|
|
|
34
|
if ( my $key = $self->secure_set_key ) { |
|
71
|
6
|
|
|
|
|
9
|
$self->secure_set_add( |
|
72
|
6
|
|
|
6
|
|
10
|
sub( $env, $metric, $string ) { |
|
|
6
|
|
|
|
|
7
|
|
|
|
6
|
|
|
|
|
9
|
|
|
|
6
|
|
|
|
|
7
|
|
|
73
|
6
|
|
|
|
|
74
|
my $obscure = hmac_sha256_base64( $string, $key ); |
|
74
|
6
|
|
|
|
|
17
|
$self->set_add->( $env, $metric, $obscure ); |
|
75
|
|
|
|
|
|
|
} |
|
76
|
1
|
|
|
|
|
6
|
); |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
} |
|
81
|
|
|
|
|
|
|
|
|
82
|
5
|
100
|
|
14
|
|
32
|
if (my $attr = first { !is_coderef($self->$_) } qw/ histogram increment set_add /) { |
|
|
14
|
|
|
|
|
43
|
|
|
83
|
1
|
|
|
|
|
14
|
die "$attr is not a coderef"; |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
4
|
100
|
|
|
|
39
|
if ( my $catch = $self->catch_errors ) { |
|
87
|
|
|
|
|
|
|
|
|
88
|
1
|
50
|
|
|
|
6
|
unless ( is_coderef($catch) ) { |
|
89
|
|
|
|
|
|
|
|
|
90
|
1
|
|
|
|
|
1
|
$self->catch_errors( |
|
91
|
1
|
|
|
1
|
|
2
|
sub( $env, $error ) { |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1
|
|
|
92
|
1
|
50
|
|
|
|
4
|
if ( my $logger = $env->{'psgix.logger'} ) { |
|
93
|
1
|
|
|
|
|
4
|
$logger->( { level => 'error', message => $error } ); |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
else { |
|
96
|
0
|
|
|
|
|
0
|
$env->{'psgi.errors'}->print($error); |
|
97
|
|
|
|
|
|
|
} |
|
98
|
1
|
|
|
|
|
3
|
my $message = 'Internal Error'; |
|
99
|
1
|
|
|
|
|
6
|
return [ 500, [ 'Content-Type' => 'text/plain', 'Content-Length' => length($message) ], [$message] ]; |
|
100
|
|
|
|
|
|
|
} |
|
101
|
1
|
|
|
|
|
4
|
); |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
7
|
|
|
7
|
1
|
220792
|
sub call ( $self, $env ) { |
|
|
7
|
|
|
|
|
16
|
|
|
|
7
|
|
|
|
|
13
|
|
|
|
7
|
|
|
|
|
10
|
|
|
109
|
|
|
|
|
|
|
|
|
110
|
7
|
|
33
|
|
|
117
|
my $client = ( $env->{'psgix.monitor.statsd'} //= $self->client ); |
|
111
|
7
|
|
|
|
|
67
|
my $secure = $self->secure_set_add; |
|
112
|
|
|
|
|
|
|
|
|
113
|
7
|
50
|
|
|
|
51
|
if ( defined $secure ) { |
|
114
|
7
|
|
|
|
|
18
|
weaken( my $ref = $env ); |
|
115
|
7
|
|
|
1
|
|
35
|
$env->{'psgix.monitor.statsd_secure_set_add'} = sub { $secure->( $ref, @_ ) }; |
|
|
1
|
|
|
|
|
70
|
|
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
|
|
119
|
7
|
|
|
|
|
41
|
my $start = [Time::HiRes::gettimeofday]; |
|
120
|
7
|
|
|
|
|
15
|
my $res; |
|
121
|
|
|
|
|
|
|
|
|
122
|
7
|
100
|
|
|
|
24
|
if (my $catch = $self->catch_errors) { |
|
123
|
|
|
|
|
|
|
try { |
|
124
|
1
|
|
|
1
|
|
73
|
$res = $self->app->($env); |
|
125
|
|
|
|
|
|
|
} |
|
126
|
|
|
|
|
|
|
catch { |
|
127
|
1
|
|
|
1
|
|
90
|
$res = $catch->( $env, $_ ); |
|
128
|
|
|
|
|
|
|
} |
|
129
|
1
|
|
|
|
|
9
|
} |
|
130
|
|
|
|
|
|
|
else { |
|
131
|
6
|
|
|
|
|
60
|
$res = $self->app->($env); |
|
132
|
|
|
|
|
|
|
} |
|
133
|
|
|
|
|
|
|
|
|
134
|
7
|
|
|
|
|
10
|
return Plack::Util::response_cb( |
|
135
|
|
|
|
|
|
|
$res, |
|
136
|
7
|
|
|
7
|
|
83
|
sub($res) { |
|
|
7
|
|
|
|
|
19
|
|
|
137
|
7
|
50
|
|
|
|
29
|
return unless $client; |
|
138
|
|
|
|
|
|
|
|
|
139
|
7
|
|
|
|
|
19
|
my $rate = $self->sample_rate; |
|
140
|
|
|
|
|
|
|
|
|
141
|
7
|
50
|
33
|
|
|
75
|
$rate = undef if ( defined $rate ) && ( $rate >= 1 ); |
|
142
|
|
|
|
|
|
|
|
|
143
|
7
|
|
|
|
|
20
|
my $histogram = $self->histogram; |
|
144
|
7
|
|
|
|
|
32
|
my $increment = $self->increment; |
|
145
|
7
|
|
|
|
|
28
|
my $set_add = $self->set_add; |
|
146
|
|
|
|
|
|
|
|
|
147
|
7
|
|
|
|
|
37
|
my $elapsed = Time::HiRes::tv_interval($start); |
|
148
|
|
|
|
|
|
|
|
|
149
|
7
|
|
|
|
|
132
|
$histogram->( $env, 'psgi.response.time', $elapsed * 1000, $rate ); |
|
150
|
|
|
|
|
|
|
|
|
151
|
7
|
50
|
|
|
|
172
|
if ( defined $env->{CONTENT_LENGTH} ) { |
|
152
|
|
|
|
|
|
|
$histogram->( $env, |
|
153
|
|
|
|
|
|
|
'psgi.request.content-length', |
|
154
|
7
|
|
|
|
|
18
|
$env->{CONTENT_LENGTH}, $rate |
|
155
|
|
|
|
|
|
|
); |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
7
|
50
|
|
|
|
128
|
if ( my $method = $env->{REQUEST_METHOD} ) { |
|
159
|
7
|
100
|
|
|
|
41
|
$method = "other" unless $method =~ /^\w+$/a; |
|
160
|
7
|
|
|
|
|
19
|
$increment->( $env, 'psgi.request.method.' . $method, $rate ); |
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
|
|
163
|
7
|
100
|
|
|
|
113
|
if ( my $type = _mime_type_to_metric( $env->{CONTENT_TYPE} ) ) { |
|
164
|
1
|
|
|
|
|
3
|
$increment->( $env, 'psgi.request.content-type.' . $type, $rate ); |
|
165
|
|
|
|
|
|
|
} |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
$secure->( $env, 'psgi.request.remote_addr', $env->{REMOTE_ADDR} ) |
|
168
|
7
|
50
|
33
|
|
|
70
|
if defined($secure) && $env->{REMOTE_ADDR}; |
|
169
|
|
|
|
|
|
|
|
|
170
|
7
|
|
|
|
|
76
|
$set_add->( $env, 'psgi.worker.pid', $$ ); |
|
171
|
|
|
|
|
|
|
|
|
172
|
7
|
|
|
|
|
96
|
my $h = Plack::Util::headers( $res->[1] ); |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
my $xsendfile = |
|
175
|
|
|
|
|
|
|
$env->{'plack.xsendfile.type'} |
|
176
|
|
|
|
|
|
|
|| $ENV{HTTP_X_SENDFILE_TYPE} |
|
177
|
7
|
|
50
|
|
|
175
|
|| 'X-Sendfile'; |
|
178
|
|
|
|
|
|
|
|
|
179
|
7
|
50
|
|
|
|
32
|
if ( $h->exists($xsendfile) ) { |
|
180
|
0
|
|
|
|
|
0
|
$increment->( $env, 'psgi.response.x-sendfile', $rate ); |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
|
|
183
|
7
|
50
|
|
|
|
170
|
if ( $h->exists('Content-Length') ) { |
|
184
|
7
|
|
100
|
|
|
124
|
my $length = $h->get('Content-Length') || 0; |
|
185
|
7
|
|
|
|
|
161
|
$histogram->( $env, 'psgi.response.content-length', $length, $rate ); |
|
186
|
|
|
|
|
|
|
} |
|
187
|
|
|
|
|
|
|
|
|
188
|
7
|
50
|
|
|
|
120
|
if ( my $type = _mime_type_to_metric( $h->get('Content-Type') ) ) { |
|
189
|
7
|
|
|
|
|
16
|
$increment->( $env, 'psgi.response.content-type.' . $type, $rate ); |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
|
|
192
|
7
|
|
|
|
|
107
|
$increment->( $env, 'psgi.response.status.' . $res->[0], $rate ); |
|
193
|
|
|
|
|
|
|
|
|
194
|
7
|
50
|
|
|
|
110
|
if ( |
|
|
|
50
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
$env->{'psgix.harakiri.supported'} |
|
196
|
|
|
|
|
|
|
? $env->{'psgix.harakiri'} |
|
197
|
|
|
|
|
|
|
: $env->{'psgix.harakiri.commit'} |
|
198
|
|
|
|
|
|
|
) |
|
199
|
|
|
|
|
|
|
{ |
|
200
|
0
|
|
|
|
|
0
|
$increment->( $env, 'psgix.harakiri' ); # rate == 1 |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
|
|
203
|
7
|
50
|
|
|
|
31
|
$client->flush if $client->can('flush'); |
|
204
|
|
|
|
|
|
|
|
|
205
|
7
|
|
|
|
|
59
|
return; |
|
206
|
|
|
|
|
|
|
} |
|
207
|
7
|
|
|
|
|
1617
|
); |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
|
|
211
|
14
|
|
|
14
|
|
168
|
sub _mime_type_to_metric( $type = undef ) { |
|
|
14
|
|
|
|
|
27
|
|
|
|
14
|
|
|
|
|
14
|
|
|
212
|
14
|
100
|
|
|
|
37
|
return unless $type; |
|
213
|
8
|
50
|
|
|
|
56
|
return unless $type =~ m#^\w+/(?:\w+[\-\+])*\w+(?: *;\w+=\w+)?#a; |
|
214
|
8
|
|
|
|
|
56
|
return $type =~ s#\.#-#gr =~ s#/#.#gr =~ s/;.*$//r; |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
1; |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
__END__ |