Sentry-SDK/lib/Sentry/Transport/Http.pm
package Sentry::Transport::Http;
use Mojo::Base -base, -signatures;
use HTTP::Status qw(:constants);
use Mojo::JSON 'encode_json';
use Mojo::UserAgent;
use Mojo::Util 'dumper';
use Readonly;
use Sentry::Envelope;
use Sentry::Hub;
use Sentry::Logger 'logger';
Readonly my $SENTRY_API_VERSION => '7';
has _http => sub {
Mojo::UserAgent->new(request_timeout => 5, connect_timeout => 1);
};
has _sentry_client => 'perl-sentry/1.0';
has _headers => sub ($self) {
my @header = (
"Sentry sentry_version=$SENTRY_API_VERSION",
"sentry_client=" . $self->_sentry_client,
'sentry_key=' . $self->dsn->user,
);
my $pass = $self->dsn->pass;
push @header, "sentry_secret=$pass" if $pass;
return {
'Content-Type' => 'application/json',
'X-Sentry-Auth' => join(', ', @header),
};
};
has _sentry_url => sub ($self) {
my $dsn = $self->dsn;
die 'DSN missing' unless $dsn;
return
sprintf('%s://%s/api/%d', $dsn->protocol, $dsn->host_port,
$dsn->project_id);
};
has dsn => undef;
sub send ($self, $payload) {
return unless $self->dsn;
my $is_transaction = ($payload->{type} // '') eq 'transaction';
my $endpoint = $is_transaction ? 'envelope' : 'store';
my $tx;
my $url = $self->_sentry_url . "/$endpoint/";
if ($is_transaction) {
my $envelope = Sentry::Envelope->new(
event_id => $payload->{event_id},
body => $payload,
);
$payload = $envelope->serialize;
$tx = $self->_http->post($url => $self->_headers, $payload);
} else {
$tx = $self->_http->post($url => $self->_headers, json => $payload);
}
logger->log(
sprintf(
qq{Sentry request done. Payload: \n<<<<<<<<<<<<<<\n%s\n<<<<<<<<<<<<<<\nCode: %s},
$tx->req->body, $tx->res->code // 'ERROR'
),
__PACKAGE__
);
if (!defined $tx->res->code || $tx->res->is_error) {
logger->warn('Error: ' . ($tx->res->error // {})->{message});
return;
}
if ($tx->res->code == HTTP_BAD_REQUEST) {
logger->error($tx->res->body);
}
return $tx->res->json;
}
1;