File Coverage

blib/lib/Net/Airbrake.pm
Criterion Covered Total %
statement 54 54 100.0
branch 5 8 62.5
condition 4 8 50.0
subroutine 14 14 100.0
pod 4 4 100.0
total 81 88 92.0


line stmt bran cond sub pod time code
1             package Net::Airbrake;
2              
3 2     2   857 use strict;
  2         2  
  2         53  
4 2     2   8 use warnings;
  2         2  
  2         67  
5              
6             our $VERSION = '0.02';
7              
8 2     2   1609 use HTTP::Tiny;
  2         73162  
  2         77  
9 2     2   19 use JSON qw(decode_json);
  2         3  
  2         16  
10 2     2   7115 use Scope::Guard qw(guard);
  2         694  
  2         93  
11 2     2   625 use Net::Airbrake::Request;
  2         7  
  2         65  
12 2     2   763 use Net::Airbrake::Error;
  2         5  
  2         152  
13              
14             use Class::Tiny {
15             api_key => undef,
16             project_id => undef,
17             environment_name => $ENV{PLACK_ENV} || 'development',
18             base_url => "https://airbrake.io",
19 1         19 _errors => sub { [] },
20 1         9 _ua => sub { HTTP::Tiny->new(agent => "Net-Airbrake/$VERSION", timeout => 5) }
21 2   50 2   11 };
  2         3  
  2         31  
22              
23             sub add_error {
24 2     2 1 1 my $self = shift;
25 2         2 my ($error) = @_;
26              
27 2         3 push @{$self->_errors}, Net::Airbrake::Error->new($error);
  2         39  
28             }
29              
30             sub has_error {
31 2 50   2 1 2 scalar @{shift->_errors} ? 1 : 0;
  2         30  
32             }
33              
34             sub send {
35 2     2 1 2 my $self = shift;
36 2         2 my ($option) = @_;
37              
38 2 50       5 return unless $self->has_error;
39              
40 2 50       20 my $context = {
41             os => $^O,
42             language => "Perl $^V",
43             environment => $self->environment_name,
44 2         69 %{$option->{context} || {}},
45             };
46 2   50     26 my $req = Net::Airbrake::Request->new({
      50        
      50        
47             errors => $self->_errors,
48             context => $context,
49             environment => $option->{environment} || {},
50             session => $option->{session} || {},
51             params => $option->{params} || {},
52             });
53              
54 2     2   84 my $guard = guard { $self->_errors([]) };
  2         80  
55 2         82 my $res = $self->_ua->request(POST => $self->_url, {
56             content => $req->to_json,
57             headers => { 'Content-Type' => 'application/json' },
58             });
59 2 100       230 die "Request failed to Airbrake: @{[$res->{status}]} @{[$res->{reason}]} (@{[$res->{content}]})"
  1         4  
  1         3  
  1         12  
60             unless $res->{success};
61              
62 1         10 decode_json($res->{content});
63             }
64              
65             sub notify {
66 2     2 1 2743 my $self = shift;
67 2         2 my ($error, $option) = @_;
68              
69 2         5 $self->add_error($error);
70 2         34 $self->send($option);
71             }
72              
73             sub _url {
74 2     2   110 my $self = shift;
75              
76 2         30 $self->base_url . "/api/v3/projects/@{[$self->project_id]}/notices?key=@{[$self->api_key]}";
  2         36  
  2         36  
77             }
78              
79             1;
80             __END__