File Coverage

blib/lib/WebService/Rollbar/Notifier.pm
Criterion Covered Total %
statement 54 63 85.7
branch 15 20 75.0
condition 3 5 60.0
subroutine 15 19 78.9
pod 8 8 100.0
total 95 115 82.6


line stmt bran cond sub pod time code
1              
2             package WebService::Rollbar::Notifier;
3              
4 2     2   644684 use strict;
  2         20  
  2         75  
5 2     2   17 use warnings;
  2         5  
  2         113  
6              
7             our $VERSION = '1.002009'; # VERSION
8              
9 2     2   17 use Carp;
  2         6  
  2         179  
10 2     2   17 use Scalar::Util qw/blessed/;
  2         6  
  2         128  
11 2     2   350 use Mojo::Base -base;
  2         14705  
  2         15  
12 2     2   665 use Mojo::UserAgent;
  2         363413  
  2         25  
13              
14             # HTTPS for some reason fails on Solaris, based on smoker tests
15             my $API_URL = ($^O eq 'solaris'?'http':'https').'://api.rollbar.com/api/1/';
16              
17             has _ua => sub { Mojo::UserAgent->new; };
18             has callback => sub {
19             ## Null by default, but not undef, because undef for callback
20             ## means we want to block
21             };
22              
23             has environment => 'production';
24             has [ qw/access_token code_version framework language server/ ];
25              
26 0     0 1 0 sub critical { my $self = shift; $self->notify( 'critical', @_ ); }
  0         0  
27 0     0 1 0 sub error { my $self = shift; $self->notify( 'error', @_ ); }
  0         0  
28 0     0 1 0 sub warning { my $self = shift; $self->notify( 'warning', @_ ); }
  0         0  
29 2     2 1 16748 sub info { my $self = shift; $self->notify( 'info', @_ ); }
  2         10  
30 0     0 1 0 sub debug { my $self = shift; $self->notify( 'debug', @_ ); }
  0         0  
31              
32             sub _parse_message_param {
33 5     5   14 my $message = shift;
34              
35 5 100       23 if (ref($message) eq 'ARRAY') {
36 3   100     19 return ($message->[0], $message->[1]||{});
37             } else {
38 2         11 return ($message, {} );
39             }
40             }
41             sub report_message {
42 5     5 1 14344 my ($self) = shift;
43 5         16 my ($message, $request_params) = @_;
44              
45 5         19 my ($body, $custom) = _parse_message_param($message);
46              
47             return $self->_post(
48             {
49             message => {
50             body => $body,
51 5         26 %{ $custom },
  5         35  
52             },
53             },
54             $request_params,
55             );
56             }
57              
58             sub notify {
59 2     2 1 7 my $self = shift;
60 2         7 my ( $severity, $message, $custom ) = @_;
61              
62 2         13 return $self->report_message( [$message, $custom], {level => $severity} );
63             }
64              
65              
66             my @frame_optional_fields =
67             qw/lineno colno method code context argspec varargspec keywordspec locals /
68             ;
69              
70             sub _parse_exception_params {
71 2     2   11 my @params = @_;
72              
73 2 50       18 my $request_params =
74             ref $params[-1] eq 'HASH'
75             ? pop @params
76             : {}
77             ;
78 2         13 my $frames = _extract_frames(pop @params);
79              
80 2         18 my ($class, $message, $description) = @params;
81              
82             return (
83             {
84 2 100       29 class => $class,
    50          
85             (defined $message ? (message => $message) : ()),
86             (defined $description ? (description => $description) : ()),
87             },
88             $frames,
89             $request_params,
90             );
91             }
92             sub _devel_stacktrace_frame_to_rollbar {
93 3     3   7 my $frame = shift;
94             return {
95 3         7 filename => $frame->filename,
96             lineno => $frame->line,
97             method => $frame->subroutine,
98             # code
99             # context {}
100             # varargspec: args
101             # locals: { args => ... }
102             }
103             }
104             sub _extract_frames {
105 2     2   10 my $trace = shift;
106              
107 2 100       13 if ( ref($trace) eq 'ARRAY' ) {
108             # Assume rollbar-ready frames
109 1         8 return $trace;
110             }
111 1 50 33     19 if ( blessed($trace) and $trace->isa("Devel::StackTrace") ) {
112             return [
113 1         6 map { _devel_stacktrace_frame_to_rollbar( $_ ) }
  3         252  
114             $trace->frames
115             ];
116             }
117              
118 0         0 return ();
119             }
120              
121             sub report_trace {
122 2     2 1 10798 my $self = shift;
123              
124 2         14 my ($exception_data, $frames, $request_params) = _parse_exception_params(@_);
125              
126 2         20 return $self->_post(
127             {
128             trace => {
129             exception => $exception_data,
130             frames => $frames,
131             }
132             },
133             $request_params,
134             );
135             }
136              
137             sub _post {
138 7     7   22 my $self = shift;
139 7         24 my ( $body, $request_optionals ) = @_;
140              
141 7 100       60 my @instance_optionals = (
142             map +( defined $self->$_ ? ( $_ => $self->$_ ) : () ),
143             qw/code_version framework language server/
144             );
145             my @request_optionals = (
146 7 100       228 map +( exists $request_optionals->{$_} ? ( $_ => $request_optionals->{$_} ) : () ),
147             qw/level context request person server client custom fingerprint uuid title/
148             );
149              
150 7 50       39 my $response = $self->_ua->post(
151             $API_URL . 'item/',
152             json => {
153             access_token => $self->access_token,
154             data => {
155             environment => $self->environment,
156              
157             body => $body,
158              
159             platform => $^O,
160             timestamp => time(),
161              
162             @instance_optionals,
163              
164             context => scalar( caller 3 ),
165              
166             @request_optionals,
167              
168             notifier => {
169             name => 'WebService::Rollbar::Notifier',
170             version => $VERSION,
171             },
172              
173             },
174             },
175              
176             ( $self->callback ? $self->callback : () ),
177             );
178              
179 7 50       909178 return $self->callback ? (1) : $response;
180             }
181              
182              
183             '
184             "Most of you are familiar with the virtues of a programmer.
185             There are three, of course: laziness, impatience, and hubris."
186             -- Larry Wall
187             ';
188              
189             __END__