File Coverage

blib/lib/Net/Prometheus/PerlCollector.pm
Criterion Covered Total %
statement 35 35 100.0
branch 5 6 83.3
condition 1 3 33.3
subroutine 8 8 100.0
pod 0 2 0.0
total 49 54 90.7


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2018-2020 -- leonerd@leonerd.org.uk
5              
6             package Net::Prometheus::PerlCollector;
7              
8 10     10   72 use strict;
  10         21  
  10         297  
9 10     10   52 use warnings;
  10         18  
  10         358  
10              
11             BEGIN {
12 10     10   450 our $VERSION = '0.12';
13             }
14              
15 10         50 use constant HAVE_XS => defined eval {
16 10         80 require XSLoader;
17 10         4978 XSLoader::load( __PACKAGE__, our $VERSION );
18 10         945 1;
19 10     10   54 };
  10         30  
20              
21 10     10   79 use Net::Prometheus::Types qw( MetricSamples Sample );
  10         18  
  10         1632  
22              
23             our $DETAIL = 0;
24              
25             =head1 NAME
26              
27             C - obtain statistics about the perl interpreter
28              
29             =head1 SYNOPSIS
30              
31             use Net::Prometheus;
32             use Net::Prometheus::PerlCollector;
33              
34             my $client = Net::Prometheus->new;
35             $client->register( Net::Prometheus::PerlCollector->new );
36              
37             =head1 DESCRIPTION
38              
39             This module provides a class that collects metrics about the perl interpreter
40             itself.
41              
42             =head2 Metrics
43              
44             The following metrics are collected:
45              
46             =over 2
47              
48             =item * C
49              
50             An info gauge (i.e. whose value is always 1) with a C label giving
51             the perl interpreter version
52              
53             # HELP perl_info Information about the Perl interpreter
54             # TYPE perl_info gauge
55             perl_info{version="5.30.0"} 1
56              
57             =back
58              
59             If the optional XS module was compiled at build time, the following extra are
60             also reported:
61              
62             =over 2
63              
64             =item * C
65              
66             A gauge giving the number of arenas the heap is split into.
67              
68             =item * C
69              
70             A gauge giving the total number of SVs allocated on the heap.
71              
72             =back
73              
74             # HELP perl_heap_arenas Number of arenas in the Perl heap
75             # TYPE perl_heap_arenas gauge
76             perl_heap_arenas 159
77             # HELP perl_heap_svs Number of SVs in the Perl heap
78             # TYPE perl_heap_svs gauge
79             perl_heap_svs 26732
80              
81             Note that the way these metrics are collected requires counting them all every
82             time. While this code is relatively efficient, it is still a linear scan, and
83             may itself cause some slowdown of the process at the time it is collected, if
84             the heap has grown very large, containing a great number of SVs.
85              
86             Extra detail can be obtained about the types of heap objects by setting
87              
88             $Net::Prometheus::PerlCollector::DETAIL = 1;
89              
90             This will be slightly more expensive to count, but will yield in addition a
91             detailed breakdown by object type.
92              
93             # HELP perl_heap_svs_by_type Number of SVs classified by type
94             # TYPE perl_heap_svs_by_type gauge
95             perl_heap_svs_by_type{type="ARRAY"} 2919
96             perl_heap_svs_by_type{type="CODE"} 1735
97             perl_heap_svs_by_type{type="GLOB"} 2647
98             perl_heap_svs_by_type{type="HASH"} 470
99             perl_heap_svs_by_type{type="INVLIST"} 68
100             perl_heap_svs_by_type{type="IO"} 12
101             perl_heap_svs_by_type{type="NULL"} 8752
102             perl_heap_svs_by_type{type="REGEXP"} 171
103             perl_heap_svs_by_type{type="SCALAR"} 9958
104              
105             This level of detail is unlikely to be useful for most generic production
106             purposes but may be helpful to set in specific processes when investigating
107             specific memory-related issues for a limited time.
108              
109             For an even greater level of detail, set the value to 2 to additionally obtain
110             another breakdown of blessed objects by class:
111              
112             # HELP perl_heap_svs_by_class Number of SVs classified by class
113             # TYPE perl_heap_svs_by_class gauge
114             ...
115             perl_heap_svs_by_class{class="Net::Prometheus"} 1
116             perl_heap_svs_by_class{class="Net::Prometheus::PerlCollector"} 1
117             perl_heap_svs_by_class{class="Net::Prometheus::ProcessCollector::linux"} 1
118              
119             Note that this will yield a large amount of output for any non-trivially sized
120             program, so should only be enabled under carefully-controlled conditions.
121              
122             The value of this variable can be overridden on a per-collection basis by
123             passing the option
124              
125             Net::Prometheus->render( { perl_collector_detail => 1 } ); # or 2
126              
127             This may be more convenient for short-term traces from exporters that parse
128             HTTP query parameters into collector options.
129              
130             GET .../metrics?perl_collector_detail=1
131              
132             =cut
133              
134             sub new
135             {
136 4     4 0 10 my $class = shift;
137              
138 4         16 return bless {}, $class;
139             }
140              
141             # Might as well keep these as constants
142             use constant
143 10     10   80 PERL_VERSION => ( $^V =~ m/^v(.*)$/ )[0];
  10         35  
  10         3495  
144              
145             sub collect
146             {
147 7     7 0 14 shift;
148 7         17 my ( $opts ) = @_;
149              
150 7 50 33     51 local $DETAIL = $opts->{perl_collector_detail} if $opts and exists $opts->{perl_collector_detail};
151              
152 7         40 my @ret = (
153             MetricSamples( "perl_info", gauge => "Information about the Perl interpreter",
154             [ Sample( "perl_info", [ version => PERL_VERSION ], 1 ) ] ),
155             );
156              
157 7         70 if( HAVE_XS ) {
158 7         11343 my ( $arenas, $svs, $svs_by_type, $svs_by_class ) = count_heap( $DETAIL );
159              
160 7         53 push @ret,
161             MetricSamples( "perl_heap_arenas", gauge => "Number of arenas in the Perl heap",
162             [ Sample( "perl_heap_arenas", [], $arenas ) ] ),
163             MetricSamples( "perl_heap_svs", gauge => "Number of SVs in the Perl heap",
164             [ Sample( "perl_heap_svs", [], $svs ) ] );
165              
166 7 100       136 if( $svs_by_type ) {
167             push @ret, MetricSamples( "perl_heap_svs_by_type", gauge => "Number of SVs classified by type",
168 2         18 [ map { Sample( "perl_heap_svs_by_type", [ type => $_ ], $svs_by_type->{$_} ) } sort keys %$svs_by_type ] );
  18         111  
169             }
170              
171 7 100       42 if( $svs_by_class ) {
172             push @ret, MetricSamples( "perl_heap_svs_by_class", gauge => "Number of SVs classified by class",
173 1         12 [ map { Sample( "perl_heap_svs_by_class", [ class => $_ ], $svs_by_class->{$_} ) } sort keys %$svs_by_class ] );
  23         161  
174             }
175             }
176              
177 7         43 return @ret;
178             }
179              
180             =head1 AUTHOR
181              
182             Paul Evans
183              
184             =cut
185              
186             0x55AA;