line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Plack::Middleware::AccessLog::Structured; |
2
|
|
|
|
|
|
|
{ |
3
|
|
|
|
|
|
|
$Plack::Middleware::AccessLog::Structured::VERSION = '0.001000'; |
4
|
|
|
|
|
|
|
} |
5
|
1
|
|
|
1
|
|
101108
|
use parent qw(Plack::Middleware); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
8
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
# ABSTRACT: Access log middleware which creates structured log messages |
8
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
18259
|
use strict; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
35
|
|
10
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
25
|
|
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
11
|
use Carp; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
77
|
|
13
|
1
|
|
|
1
|
|
22
|
use MRO::Compat; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
29
|
|
14
|
1
|
|
|
1
|
|
3144
|
use Time::HiRes; |
|
1
|
|
|
|
|
2160
|
|
|
1
|
|
|
|
|
6
|
|
15
|
1
|
|
|
1
|
|
144
|
use Plack::Util::Accessor qw(logger callback extra_field); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
10
|
|
16
|
1
|
|
|
1
|
|
1133
|
use Net::Domain qw(hostname hostfqdn); |
|
1
|
|
|
|
|
12646
|
|
|
1
|
|
|
|
|
96
|
|
17
|
1
|
|
|
1
|
|
1698
|
use DateTime; |
|
1
|
|
|
|
|
233104
|
|
|
1
|
|
|
|
|
48
|
|
18
|
1
|
|
|
1
|
|
37
|
use Time::HiRes; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
9
|
|
19
|
1
|
|
|
1
|
|
1631
|
use JSON; |
|
1
|
|
|
|
|
16044
|
|
|
1
|
|
|
|
|
8
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub new { |
23
|
5
|
|
|
5
|
1
|
29759
|
my ($class, $arg_ref) = @_; |
24
|
|
|
|
|
|
|
|
25
|
5
|
|
|
|
|
37
|
my $self = $class->next::method($arg_ref); |
26
|
5
|
100
|
100
|
|
|
169
|
if (defined $self->callback() && ref $self->callback() ne 'CODE') { |
27
|
1
|
|
|
|
|
154
|
croak("Passed 'callback' parameter must be a code reference"); |
28
|
|
|
|
|
|
|
} |
29
|
4
|
100
|
100
|
|
|
571
|
if (defined $self->extra_field() && ref $self->extra_field() ne 'HASH') { |
30
|
1
|
|
|
|
|
22
|
croak("Passed 'extra_field' parameter must be a hash reference"); |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
3
|
|
|
|
|
44
|
return $self; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub call { |
39
|
3
|
|
|
3
|
1
|
60375
|
my ($self, $env) = @_; |
40
|
|
|
|
|
|
|
|
41
|
3
|
|
|
|
|
12
|
my $t_before = Time::HiRes::time(); |
42
|
3
|
|
|
|
|
25
|
my $res = $self->app->($env); |
43
|
3
|
|
|
|
|
38
|
my $t_after = Time::HiRes::time(); |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
return $self->response_cb($res, sub { |
46
|
3
|
|
|
3
|
|
54
|
my ($cb_res) = @_; |
47
|
|
|
|
|
|
|
|
48
|
3
|
|
|
|
|
17
|
my $h = Plack::Util::headers($res->[1]); |
49
|
3
|
|
|
|
|
117
|
my $content_type = $h->get('Content-Type'); |
50
|
3
|
100
|
33
|
|
|
117
|
my $log_entry = { |
|
|
|
33
|
|
|
|
|
51
|
|
|
|
|
|
|
class => ref($self), |
52
|
|
|
|
|
|
|
# Request data |
53
|
|
|
|
|
|
|
remote_addr => $env->{REMOTE_ADDR}, |
54
|
|
|
|
|
|
|
request_method => _safe($env->{REQUEST_METHOD}), |
55
|
|
|
|
|
|
|
request_uri => _safe($env->{REQUEST_URI}), |
56
|
|
|
|
|
|
|
server_protocol => $env->{SERVER_PROTOCOL}, |
57
|
|
|
|
|
|
|
http_user_agent => _safe($env->{HTTP_USER_AGENT}), |
58
|
|
|
|
|
|
|
http_host => $env->{HTTP_HOST} || $env->{SERVER_NAME}, |
59
|
|
|
|
|
|
|
http_referer => $env->{HTTP_REFERER}, |
60
|
|
|
|
|
|
|
remote_user => $env->{REMOTE_USER}, |
61
|
|
|
|
|
|
|
# Server information |
62
|
|
|
|
|
|
|
pid => $$, |
63
|
|
|
|
|
|
|
hostfqdn => hostfqdn(), |
64
|
|
|
|
|
|
|
hostname => hostname(), |
65
|
|
|
|
|
|
|
# Response data |
66
|
|
|
|
|
|
|
response_status => $cb_res->[0], |
67
|
|
|
|
|
|
|
content_length => Plack::Util::content_length($res->[2]) || $h->get('Content-Length'), |
68
|
|
|
|
|
|
|
content_type => defined $content_type ? "$content_type" : undef, |
69
|
|
|
|
|
|
|
# Timing |
70
|
|
|
|
|
|
|
request_duration => ( $t_after - $t_before ) * 1000, |
71
|
|
|
|
|
|
|
date => DateTime->from_epoch(epoch => $t_before)->strftime('%Y-%m-%dT%H:%M:%S.%3NZ'), |
72
|
|
|
|
|
|
|
epochtime => $t_before, |
73
|
|
|
|
|
|
|
}; |
74
|
|
|
|
|
|
|
|
75
|
3
|
100
|
|
|
|
2800
|
if ($self->extra_field()) { |
76
|
1
|
|
|
|
|
29
|
for my $env_field (keys %{$self->extra_field}) { |
|
1
|
|
|
|
|
4
|
|
77
|
1
|
|
|
|
|
10
|
$log_entry->{$self->extra_field()->{$env_field}} |
78
|
|
|
|
|
|
|
= $env->{$env_field}; |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
3
|
100
|
|
|
|
29
|
if ($self->callback()) { |
83
|
1
|
|
|
|
|
8
|
$log_entry = $self->callback()->($env, $log_entry); |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
3
|
|
50
|
|
|
30
|
my $logger = $self->logger() || sub { $env->{'psgi.errors'}->print($_[0] . "\n") }; |
87
|
3
|
|
|
|
|
89
|
$logger->(encode_json($log_entry)); |
88
|
|
|
|
|
|
|
|
89
|
3
|
|
|
|
|
61
|
return; |
90
|
3
|
|
|
|
|
39
|
}); |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# Taken from Plack::Middleware::AccessLog |
95
|
|
|
|
|
|
|
sub _safe { |
96
|
9
|
|
|
9
|
|
16
|
my ($string) = @_; |
97
|
9
|
100
|
|
|
|
30
|
$string =~ s/([^[:print:]])/"\\x" . unpack("H*", $1)/xeg |
|
0
|
|
|
|
|
0
|
|
98
|
|
|
|
|
|
|
if defined $string; |
99
|
9
|
|
|
|
|
51
|
return $string; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
1; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
__END__ |