File Coverage

blib/lib/Metrics/Any.pm
Criterion Covered Total %
statement 20 20 100.0
branch 2 4 50.0
condition 3 9 33.3
subroutine 6 6 100.0
pod 0 1 0.0
total 31 40 77.5


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, 2020-2021 -- leonerd@leonerd.org.uk
5              
6             package Metrics::Any 0.10;
7              
8 12     12   1910115 use v5.14;
  12         110  
9 12     12   78 use warnings;
  12         37  
  12         310  
10              
11 12     12   6259 use Metrics::Any::Collector;
  12         38  
  12         1672  
12              
13             =head1 NAME
14              
15             C - abstract collection of monitoring metrics
16              
17             =head1 SYNOPSIS
18              
19             In a module:
20              
21             use Metrics::Any '$metrics',
22             strict => 0,
23             name_prefix => [ 'my_module_name' ];
24              
25             sub do_thing {
26             $metrics->inc_counter( 'things_done' );
27             }
28              
29             In a program or top-level program-like module:
30              
31             use Metrics::Any::Adapter 'Prometheus';
32              
33             =head1 DESCRIPTION
34              
35             Provides a central location for modules to report monitoring metrics, such as
36             counters of the number of times interesting events have happened, and programs
37             to collect up and send those metrics to monitoring services.
38              
39             Inspired by L, this module splits the overall problem into two
40             sides. Modules wishing to provide metrics for monitoring purposes can use the
41             C statement to obtain a I into which they can
42             report metric events. By default this collector doesn't actually do anything,
43             so modules can easily use it without adding extra specific dependencies for
44             specific reporting.
45              
46             A program using one or more such modules can apply a different policy and
47             request a particular I implementation in order to actually report
48             these metrics to some external system, by using the
49             C statement.
50              
51             This separation of concerns allows module authors to write code which will
52             report metrics without needing to care about the exact mechanism of that
53             reporting (as well as to write code which does not itself depend on the code
54             required to perform that reporting).
55              
56             =head2 Future Direction
57              
58             At present this interface is in an early state of experimentation. The API
59             is fairly specifically-shaped for L at present, but it is
60             hoped with more adapter implementations (such as for statsd or OpenTelemetry)
61             the API shapes can be expanded and made more generic to support a wider
62             variety of reporting mechanisms.
63              
64             As a result, any API details for now should be considered experimental and
65             subject to change in later versions.
66              
67             =cut
68              
69             =head1 USE STATEMENT
70              
71             For a module to use this facility, the C statement importing it should
72             give the name of a variable (as a plain string) to store the collector for
73             that package.
74              
75             use Metrics::Any '$metrics';
76              
77             This variable will be created in the calling package and populated with an
78             instance of L. The module can then use the collector
79             API to declare new metrics, and eventually report values into them.
80              
81             Note that the variable is created at the package level; any other packages
82             within the same file will not see it and will have to declare their own.
83              
84             =cut
85              
86             sub import
87             {
88 14     14   124 my $pkg = shift;
89 14         32 my $caller = caller;
90 14         55 $pkg->import_into( $caller, @_ );
91             }
92              
93             my %collector_for_package;
94              
95             sub import_into
96             {
97 14     14 0 47 my ( $pkg, $caller, @args ) = @_;
98              
99 14 50 33     190 my $varname = $1 and shift @args if @args and $args[0] =~ m/^\$(.*)$/;
      33        
100              
101 14   33     99 my $collector = $collector_for_package{$caller} //= Metrics::Any::Collector->new( $caller, @args );
102              
103 14 50       64 if( defined $varname ) {
104 12     12   94 no strict 'refs';
  12         24  
  12         962  
105 14         28 *{"${caller}::${varname}"} = \$collector;
  14         11545  
106             }
107             }
108              
109             =head1 SEE ALSO
110              
111             =over 4
112              
113             =item *
114              
115             The name and overall concept of this module is heavily influenced by a similar
116             module for logging, L.
117              
118             =item *
119              
120             For reporting metrics to one specific target collector, there are specific
121             modules for systems like F (L, L) or
122             F (L, L).
123              
124             =item *
125              
126             There is also a similar concept in L.
127              
128             =back
129              
130             =cut
131              
132             =head1 AUTHOR
133              
134             Paul Evans
135              
136             =cut
137              
138             0x55AA;