File Coverage

blib/lib/Sentry/Transport/Http.pm
Criterion Covered Total %
statement 45 48 93.7
branch 7 10 70.0
condition 4 9 44.4
subroutine 10 10 100.0
pod 0 1 0.0
total 66 78 84.6


line stmt bran cond sub pod time code
1             package Sentry::Transport::Http;
2 4     4   24 use Mojo::Base -base, -signatures;
  4         6  
  4         28  
3              
4 4     4   1173 use HTTP::Status qw(:constants);
  4         7  
  4         1763  
5 4     4   1524 use Mojo::JSON 'encode_json';
  4         67846  
  4         260  
6 4     4   1750 use Mojo::UserAgent;
  4         755650  
  4         45  
7 4     4   211 use Mojo::Util 'dumper';
  4         10  
  4         279  
8 4     4   48 use Readonly;
  4         9  
  4         224  
9 4     4   2358 use Sentry::Envelope;
  4         14  
  4         27  
10 4     4   184 use Sentry::Hub;
  4         9  
  4         30  
11 4     4   142 use Sentry::Logger 'logger';
  4         9  
  4         3943  
12              
13             Readonly my $SENTRY_API_VERSION => '7';
14              
15             has _http => sub {
16             Mojo::UserAgent->new(request_timeout => 5, connect_timeout => 1);
17             };
18             has _sentry_client => 'perl-sentry/1.0';
19             has _headers => sub ($self) {
20             my @header = (
21             "Sentry sentry_version=$SENTRY_API_VERSION",
22             "sentry_client=" . $self->_sentry_client,
23             'sentry_key=' . $self->dsn->user,
24             );
25              
26             my $pass = $self->dsn->pass;
27             push @header, "sentry_secret=$pass" if $pass;
28              
29             return {
30             'Content-Type' => 'application/json',
31             'X-Sentry-Auth' => join(', ', @header),
32             };
33             };
34             has _sentry_url => sub ($self) {
35             my $dsn = $self->dsn;
36             die 'DSN missing' unless $dsn;
37              
38             return
39             sprintf('%s://%s/api/%d', $dsn->protocol, $dsn->host_port,
40             $dsn->project_id);
41             };
42             has dsn => undef;
43              
44 20     20 0 156 sub send ($self, $payload) {
  20         29  
  20         27  
  20         26  
45 20 50       61 return unless $self->dsn;
46 20   100     132 my $is_transaction = ($payload->{type} // '') eq 'transaction';
47 20 100       46 my $endpoint = $is_transaction ? 'envelope' : 'store';
48 20         27 my $tx;
49 20         46 my $url = $self->_sentry_url . "/$endpoint/";
50              
51 20 100       82 if ($is_transaction) {
52             my $envelope = Sentry::Envelope->new(
53             event_id => $payload->{event_id},
54 10         84 body => $payload,
55             );
56 10         125 $payload = $envelope->serialize;
57 10         826 $tx = $self->_http->post($url => $self->_headers, $payload);
58             } else {
59 10         29 $tx = $self->_http->post($url => $self->_headers, json => $payload);
60             }
61              
62 20   50     1018 logger->log(
63             sprintf(
64             qq{Sentry request done. Payload: \n<<<<<<<<<<<<<<\n%s\n<<<<<<<<<<<<<<\nCode: %s},
65             $tx->req->body, $tx->res->code // 'ERROR'
66             ),
67             __PACKAGE__
68             );
69              
70 20 50 33     289 if (!defined $tx->res->code || $tx->res->is_error) {
71 0   0     0 logger->warn('Error: ' . ($tx->res->error // {})->{message});
72 0         0 return;
73             }
74              
75 20 50       313 if ($tx->res->code == HTTP_BAD_REQUEST) {
76 0         0 logger->error($tx->res->body);
77             }
78              
79 20         122 return $tx->res->json;
80             }
81              
82             1;