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   704020 use strict;
  2         19  
  2         63  
5 2     2   12 use warnings;
  2         4  
  2         83  
6              
7             our $VERSION = '1.002010'; # VERSION
8              
9 2     2   15 use Carp;
  2         5  
  2         125  
10 2     2   33 use Scalar::Util qw/blessed/;
  2         5  
  2         128  
11 2     2   528 use Mojo::Base -base;
  2         193533  
  2         19  
12 2     2   1142 use Mojo::UserAgent;
  2         269184  
  2         19  
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 17375 sub info { my $self = shift; $self->notify( 'info', @_ ); }
  2         9  
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       27 if (ref($message) eq 'ARRAY') {
36 3   100     26 return ($message->[0], $message->[1]||{});
37             } else {
38 2         13 return ($message, {} );
39             }
40             }
41             sub report_message {
42 5     5 1 12617 my ($self) = shift;
43 5         18 my ($message, $request_params) = @_;
44              
45 5         21 my ($body, $custom) = _parse_message_param($message);
46              
47             return $self->_post(
48             {
49             message => {
50             body => $body,
51 5         26 %{ $custom },
  5         69  
52             },
53             },
54             $request_params,
55             );
56             }
57              
58             sub notify {
59 2     2 1 6 my $self = shift;
60 2         6 my ( $severity, $message, $custom ) = @_;
61              
62 2         12 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   8 my @params = @_;
72              
73 2 50       12 my $request_params =
74             ref $params[-1] eq 'HASH'
75             ? pop @params
76             : {}
77             ;
78 2         12 my $frames = _extract_frames(pop @params);
79              
80 2         21 my ($class, $message, $description) = @params;
81              
82             return (
83             {
84 2 100       23 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   6 my $frame = shift;
94             return {
95 3         9 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   5 my $trace = shift;
106              
107 2 100       11 if ( ref($trace) eq 'ARRAY' ) {
108             # Assume rollbar-ready frames
109 1         5 return $trace;
110             }
111 1 50 33     16 if ( blessed($trace) and $trace->isa("Devel::StackTrace") ) {
112             return [
113 1         6 map { _devel_stacktrace_frame_to_rollbar( $_ ) }
  3         294  
114             $trace->frames
115             ];
116             }
117              
118 0         0 return ();
119             }
120              
121             sub report_trace {
122 2     2 1 7719 my $self = shift;
123              
124 2         12 my ($exception_data, $frames, $request_params) = _parse_exception_params(@_);
125              
126 2         16 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   20 my $self = shift;
139 7         23 my ( $body, $request_optionals ) = @_;
140              
141 7 100       55 my @instance_optionals = (
142             map +( defined $self->$_ ? ( $_ => $self->$_ ) : () ),
143             qw/code_version framework language server/
144             );
145             my @request_optionals = (
146 7 100       275 map +( exists $request_optionals->{$_} ? ( $_ => $request_optionals->{$_} ) : () ),
147             qw/level context request person server client custom fingerprint uuid title/
148             );
149              
150 7 50       36 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       914887 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__