| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Prometheus::Tiny::Shared; | 
| 2 |  |  |  |  |  |  | $Prometheus::Tiny::Shared::VERSION = '0.025'; | 
| 3 |  |  |  |  |  |  | # ABSTRACT: A tiny Prometheus client with a shared database behind it | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 18 |  |  | 18 |  | 1307080 | use warnings; | 
|  | 18 |  |  |  |  | 226 |  | 
|  | 18 |  |  |  |  | 680 |  | 
| 6 | 18 |  |  | 18 |  | 116 | use strict; | 
|  | 18 |  |  |  |  | 38 |  | 
|  | 18 |  |  |  |  | 546 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 18 |  |  | 18 |  | 8607 | use Prometheus::Tiny 0.009; | 
|  | 18 |  |  |  |  | 29994 |  | 
|  | 18 |  |  |  |  | 595 |  | 
| 9 | 18 |  |  | 18 |  | 8323 | use parent 'Prometheus::Tiny'; | 
|  | 18 |  |  |  |  | 5550 |  | 
|  | 18 |  |  |  |  | 113 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 | 18 |  |  | 18 |  | 13267 | use Hash::SharedMem qw(shash_open shash_get shash_set shash_cset shash_keys_array shash_group_get_hash); | 
|  | 18 |  |  |  |  | 54078 |  | 
|  | 18 |  |  |  |  | 2041 |  | 
| 12 | 18 |  |  | 18 |  | 13635 | use JSON::XS qw(encode_json decode_json); | 
|  | 18 |  |  |  |  | 134200 |  | 
|  | 18 |  |  |  |  | 1507 |  | 
| 13 | 18 |  |  | 18 |  | 14456 | use File::Temp qw(tempdir); | 
|  | 18 |  |  |  |  | 360583 |  | 
|  | 18 |  |  |  |  | 1515 |  | 
| 14 | 18 |  |  | 18 |  | 169 | use File::Path qw(rmtree); | 
|  | 18 |  |  |  |  | 41 |  | 
|  | 18 |  |  |  |  | 808 |  | 
| 15 | 18 |  |  | 18 |  | 117 | use Carp qw(croak); | 
|  | 18 |  |  |  |  | 43 |  | 
|  | 18 |  |  |  |  | 22800 |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | sub new { | 
| 18 | 53 |  |  | 53 | 1 | 33256 | my ($class, %args) = @_; | 
| 19 |  |  |  |  |  |  |  | 
| 20 | 53 | 100 |  |  |  | 220 | if (exists $args{cache_args}) { | 
| 21 | 1 |  |  |  |  | 22 | croak < | 
| 22 |  |  |  |  |  |  | The 'cache_args' argument to Prometheus::Tiny::Shared::new has been removed. | 
| 23 |  |  |  |  |  |  | Read the docs for more info, and switch to the 'filename' argument. | 
| 24 |  |  |  |  |  |  | EOF | 
| 25 |  |  |  |  |  |  | } | 
| 26 |  |  |  |  |  |  |  | 
| 27 | 52 |  |  |  |  | 131 | my $filename = delete $args{filename}; | 
| 28 | 52 |  | 50 |  |  | 290 | my $init_file = delete $args{init_file} || 0; | 
| 29 |  |  |  |  |  |  |  | 
| 30 | 52 |  |  |  |  | 311 | my $self = $class->SUPER::new(%args); | 
| 31 |  |  |  |  |  |  |  | 
| 32 | 52 | 100 |  |  |  | 719 | if ($filename) { | 
| 33 | 5 | 50 |  |  |  | 15 | rmtree($filename) if $init_file; | 
| 34 |  |  |  |  |  |  | } | 
| 35 |  |  |  |  |  |  | else { | 
| 36 | 47 |  |  |  |  | 207 | $filename = tempdir('pts-XXXXXXXX', TMPDIR => 1, CLEANUP => 1); | 
| 37 |  |  |  |  |  |  | } | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 52 |  |  |  |  | 61897 | $self->{_shash} = shash_open($filename, 'rwc'); | 
| 40 |  |  |  |  |  |  |  | 
| 41 | 52 |  |  |  |  | 633 | return $self; | 
| 42 |  |  |  |  |  |  | } | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | sub set { | 
| 45 | 65 |  |  | 65 | 1 | 5211 | my ($self, $name, $value, $labels, $timestamp) = @_; | 
| 46 |  |  |  |  |  |  |  | 
| 47 | 65 |  |  |  |  | 303 | my $key = join('-', 'k', $name, $self->_format_labels($labels)); | 
| 48 | 65 |  |  |  |  | 7907 | shash_set($self->{_shash}, $key, encode_json([$value, $timestamp])); | 
| 49 |  |  |  |  |  |  |  | 
| 50 | 65 |  |  |  |  | 348 | return; | 
| 51 |  |  |  |  |  |  | } | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | sub add { | 
| 54 | 136 |  |  | 136 | 1 | 2883 | my ($self, $name, $diff, $labels) = @_; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 136 |  |  |  |  | 374 | my $key = join('-', 'k', $name, $self->_format_labels($labels)); | 
| 57 |  |  |  |  |  |  |  | 
| 58 | 136 |  |  |  |  | 2675 | my ($ov, $nv); | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | do { | 
| 61 | 136 |  |  |  |  | 372 | $ov = shash_get($self->{_shash}, $key); | 
| 62 | 136 | 100 |  |  |  | 334 | if ($ov) { | 
| 63 | 87 |  |  |  |  | 279 | my $ar = decode_json($ov); | 
| 64 | 87 |  |  |  |  | 204 | $ar->[0] += $diff; | 
| 65 | 87 |  |  |  |  | 586 | $nv = encode_json($ar); | 
| 66 |  |  |  |  |  |  | } | 
| 67 |  |  |  |  |  |  | else { | 
| 68 | 49 |  |  |  |  | 2518 | $nv = encode_json([$diff]); | 
| 69 |  |  |  |  |  |  | } | 
| 70 | 136 |  |  |  |  | 225 | } until shash_cset($self->{_shash}, $key, $ov, $nv); | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 136 |  |  |  |  | 412 | return; | 
| 73 |  |  |  |  |  |  | } | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | sub clear { | 
| 76 | 1 |  |  | 1 | 1 | 886 | my ($self, $name) = @_; | 
| 77 |  |  |  |  |  |  |  | 
| 78 | 1 |  |  |  |  | 3 | for my $key (grep { substr($_, 0, 1) eq 'k' } @{shash_keys_array($self->{_shash})}) { | 
|  | 4 |  |  |  |  | 12 |  | 
|  | 1 |  |  |  |  | 7 |  | 
| 79 | 2 |  |  |  |  | 7 | shash_set($self->{_shash}, $key, undef); | 
| 80 |  |  |  |  |  |  | } | 
| 81 |  |  |  |  |  |  |  | 
| 82 | 1 |  |  |  |  | 3 | return; | 
| 83 |  |  |  |  |  |  | } | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | sub declare { | 
| 86 | 29 |  |  | 29 | 1 | 7961 | my ($self, $name, %meta) = @_; | 
| 87 |  |  |  |  |  |  |  | 
| 88 | 29 |  |  |  |  | 89 | my $key = join('-', 'm', $name); | 
| 89 | 29 |  |  |  |  | 180 | my $value = encode_json(\%meta); | 
| 90 |  |  |  |  |  |  |  | 
| 91 | 29 | 100 |  |  |  | 3110 | return if shash_cset($self->{_shash}, $key, undef, $value); | 
| 92 |  |  |  |  |  |  |  | 
| 93 | 13 |  |  |  |  | 88 | my $old = decode_json(shash_get($self->{_shash}, $key)); | 
| 94 |  |  |  |  |  |  |  | 
| 95 | 13 | 100 | 100 |  |  | 192 | if ( | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
| 96 |  |  |  |  |  |  | ((exists $old->{type} ^ exists $meta{type}) || | 
| 97 |  |  |  |  |  |  | (exists $old->{type} && $old->{type} ne $meta{type})) || | 
| 98 |  |  |  |  |  |  | ((exists $old->{help} ^ exists $meta{help}) || | 
| 99 |  |  |  |  |  |  | (exists $old->{help} && $old->{help} ne $meta{help})) || | 
| 100 |  |  |  |  |  |  | ((exists $old->{enum} ^ exists $meta{enum}) || | 
| 101 |  |  |  |  |  |  | (exists $old->{enum} && $old->{enum} ne $meta{enum})) || | 
| 102 |  |  |  |  |  |  | ((exists $old->{buckets} ^ exists $meta{buckets}) || | 
| 103 |  |  |  |  |  |  | (exists $old->{buckets} && ( | 
| 104 |  |  |  |  |  |  | @{$old->{buckets}} ne @{$meta{buckets}} || | 
| 105 |  |  |  |  |  |  | grep { $old->{buckets}[$_] != $meta{buckets}[$_] } (0 .. $#{$meta{buckets}}) | 
| 106 |  |  |  |  |  |  | )) | 
| 107 |  |  |  |  |  |  | ) || | 
| 108 |  |  |  |  |  |  | ((exists $old->{enum_values} ^ exists $meta{enum_values}) || | 
| 109 |  |  |  |  |  |  | (exists $old->{enum_values} && ( | 
| 110 |  |  |  |  |  |  | @{$old->{enum_values}} ne @{$meta{enum_values}} || | 
| 111 |  |  |  |  |  |  | grep { $old->{enum_values}[$_] ne $meta{enum_values}[$_] } (0 .. $#{$meta{enum_values}}) | 
| 112 |  |  |  |  |  |  | )) | 
| 113 |  |  |  |  |  |  | ) | 
| 114 |  |  |  |  |  |  | ) { | 
| 115 | 10 |  |  |  |  | 131 | croak "redeclaration of '$name' with mismatched meta"; | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  |  | 
| 118 | 3 |  |  |  |  | 19 | return; | 
| 119 |  |  |  |  |  |  | } | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | sub histogram_observe { | 
| 122 | 9 |  |  | 9 | 1 | 128 | my $self = shift; | 
| 123 | 9 |  |  |  |  | 26 | my ($name) = @_; | 
| 124 |  |  |  |  |  |  |  | 
| 125 | 9 |  |  |  |  | 27 | my $key = join('-', 'm', $name); | 
| 126 |  |  |  |  |  |  |  | 
| 127 | 9 |  | 100 |  |  | 87 | $self->{meta}{$name} = decode_json(shash_get($self->{_shash}, $key) || '{}'); | 
| 128 |  |  |  |  |  |  |  | 
| 129 | 9 |  |  |  |  | 48 | return $self->SUPER::histogram_observe(@_); | 
| 130 |  |  |  |  |  |  | } | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | sub enum_set { | 
| 133 | 2 |  |  | 2 | 1 | 21 | my $self = shift; | 
| 134 | 2 |  |  |  |  | 7 | my ($name) = @_; | 
| 135 |  |  |  |  |  |  |  | 
| 136 | 2 |  |  |  |  | 7 | my $key = join('-', 'm', $name); | 
| 137 |  |  |  |  |  |  |  | 
| 138 | 2 |  | 50 |  |  | 25 | $self->{meta}{$name} = decode_json(shash_get($self->{_shash}, $key) || '{}'); | 
| 139 |  |  |  |  |  |  |  | 
| 140 | 2 |  |  |  |  | 16 | return $self->SUPER::enum_set(@_); | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | sub format { | 
| 144 | 53 |  |  | 53 | 1 | 260665 | my $self = shift; | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 53 |  |  |  |  | 107 | my (%metrics, %meta); | 
| 147 |  |  |  |  |  |  |  | 
| 148 | 53 |  |  |  |  | 434 | my $hash = shash_group_get_hash($self->{_shash}); | 
| 149 | 53 |  |  |  |  | 350 | while ( my ($k, $v) = each %$hash ) { | 
| 150 | 130 |  |  |  |  | 437 | my ($t, $name, $fmt) = split '-', $k, 3; | 
| 151 | 130 | 100 |  |  |  | 333 | if ($t eq 'k') { | 
| 152 | 112 |  |  |  |  | 734 | $metrics{$name}{$fmt} = decode_json($v); | 
| 153 |  |  |  |  |  |  | } | 
| 154 |  |  |  |  |  |  | else { | 
| 155 | 18 |  |  |  |  | 132 | $meta{$name} = decode_json($v); | 
| 156 |  |  |  |  |  |  | } | 
| 157 |  |  |  |  |  |  | } | 
| 158 | 53 |  |  |  |  | 179 | $self->{metrics} = \%metrics; | 
| 159 | 53 |  |  |  |  | 132 | $self->{meta} = \%meta; | 
| 160 |  |  |  |  |  |  |  | 
| 161 | 53 |  |  |  |  | 297 | return $self->SUPER::format(@_); | 
| 162 |  |  |  |  |  |  | } | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | 1; | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | __END__ |