1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::Metrics::Reporter::ElasticSearch;
use 5.10.1;
use strict;
use warnings;
use base 'Bugzilla::Metrics::Reporter';
use constant DETACH => 1;
sub report {
my ($self) = @_;
# build path array and flatten
my @timers;
$self->walk_timers(sub {
my ($timer, $parent) = @_;
$timer->{id} = scalar(@timers);
if ($parent) {
if (exists $timer->{children}) {
if ($timer->{type} eq 'tmpl') {
$timer->{node} = 'tmpl: ' . $timer->{file};
}
elsif ($timer->{type} eq 'db') {
$timer->{node} = 'db';
}
else {
$timer->{node} = '?';
}
}
$timer->{path} = [ @{ $parent->{path} }, $parent->{node} ];
$timer->{parent} = $parent->{id};
}
else {
$timer->{path} = [ ];
$timer->{node} = $timer->{name};
}
push @timers, $timer;
});
# calculate timer-only durations
$self->walk_timers(sub {
my ($timer) = @_;
my $child_duration = 0;
if (exists $timer->{children}) {
foreach my $child (@{ $timer->{children} }) {
$child_duration += $child->{duration};
}
}
$timer->{this_duration} = $timer->{duration} - $child_duration;
});
# massage each timer
my $start_time = $self->{times}->{start_time};
foreach my $timer (@timers) {
# remove node name and children
delete $timer->{node};
delete $timer->{children};
# show relative times
$timer->{start_time} = $timer->{start_time} - $start_time;
delete $timer->{end_time};
# show times in ms instead of fractional seconds
foreach my $field (qw( start_time duration this_duration )) {
$timer->{$field} = sprintf('%.4f', $timer->{$field} * 1000) * 1;
}
}
# remove private data from env
delete $self->{env}->{user_agent};
delete $self->{env}->{referer};
# throw at ES
require ElasticSearch;
my $es = ElasticSearch->new(
servers => Bugzilla->params->{metrics_elasticsearch_server},
transport => 'http',
);
# the ElasticSearch module queries the server for a list of nodes and
# connects directly to a random node. that bypasses our load balancer so we
# disable that by setting the server list directly.
$es->transport->servers(Bugzilla->params->{metrics_elasticsearch_server});
# as the discovered node list is lazy-loaded, increase _refresh_in so it
# won't call ->refresh_servers()
$es->transport->{_refresh_in} = 1;
$es->index(
index => Bugzilla->params->{metrics_elasticsearch_index},
type => Bugzilla->params->{metrics_elasticsearch_type},
ttl => Bugzilla->params->{metrics_elasticsearch_ttl},
data => {
env => $self->{env},
times => \@timers,
},
);
}
1;
|