AWS-XRay
view release on metacpan or search on metacpan
lib/AWS/XRay.pm view on Meta::CPAN
),
$AUTO_FLUSH,
);
}
sub new_trace_id {
sprintf(
"1-%x-%s",
CORE::time(),
unpack("H*", Crypt::URandom::urandom(12)),
);
}
sub new_id {
unpack("H*", Crypt::URandom::urandom(8));
}
sub is_valid_name {
$_[0] =~ $VALID_NAME_REGEXP;
}
# alias for backward compatibility
*trace = \&capture;
sub capture {
my ($name, $code) = @_;
if (!is_valid_name($name)) {
my $msg = "invalid segment name: $name";
$CROAK_INVALID_NAME ? croak($msg) : carp($msg);
}
my $wantarray = wantarray;
my $enabled;
my $sampled = $SAMPLED;
if (defined $ENABLED) {
$enabled = $ENABLED ? 1 : 0; # fix true or false (not undef)
}
elsif ($TRACE_ID) {
$enabled = 0; # called from parent capture
}
else {
# root capture try sampling
$sampled = $SAMPLER->() ? 1 : 0;
$enabled = $sampled ? 1 : 0;
}
local $ENABLED = $enabled;
local $SAMPLED = $sampled;
return $code->(AWS::XRay::Segment->new) if !$enabled;
local $TRACE_ID = $TRACE_ID // new_trace_id();
my $segment = AWS::XRay::Segment->new({ name => $name });
unless (defined $segment->{type} && $segment->{type} eq "subsegment") {
$_->apply_plugin($segment) for @PLUGINS;
}
local $SEGMENT_ID = $segment->{id};
my @ret;
eval {
if ($wantarray) {
@ret = $code->($segment);
}
elsif (defined $wantarray) {
$ret[0] = $code->($segment);
}
else {
$code->($segment);
}
};
my $error = $@;
if ($error) {
$segment->{error} = Types::Serialiser::true;
$segment->{cause} = {
exceptions => [
{
id => new_id(),
message => "$error",
remote => Types::Serialiser::true,
},
],
};
}
eval {
$segment->close();
};
if ($@) {
warn $@;
}
die $error if $error;
return $wantarray ? @ret : $ret[0];
}
sub capture_from {
my ($header, $name, $code) = @_;
my ($trace_id, $segment_id, $sampled) = parse_trace_header($header);
local $AWS::XRay::SAMPLED = $sampled // $SAMPLER->();
local $AWS::XRay::ENABLED = $AWS::XRay::SAMPLED;
local ($AWS::XRay::TRACE_ID, $AWS::XRay::SEGMENT_ID) = ($trace_id, $segment_id);
capture($name, $code);
}
sub parse_trace_header {
my $header = shift or return;
my ($trace_id, $segment_id, $sampled);
if ($header =~ /Root=([0-9a-fA-F-]+)/) {
$trace_id = $1;
}
if ($header =~ /Parent=([0-9a-fA-F]+)/) {
$segment_id = $1;
}
if ($header =~ /Sampled=([^;]+)/) {
$sampled = $1;
}
return ($trace_id, $segment_id, $sampled);
}
sub add_capture {
my ($class, $package, @methods) = @_;
no warnings 'redefine';
no strict 'refs';
for my $method (@methods) {
my $orig = $package->can($method) or next;
*{"${package}::${method}"} = sub {
my @args = @_;
capture(
$package,
sub {
my $segment = shift;
$segment->{metadata}->{method} = $method;
$segment->{metadata}->{package} = $package;
$orig->(@args);
},
);
};
}
}
if ($ENV{LAMBDA_TASK_ROOT}) {
# AWS::XRay is loaded in AWS Lambda worker.
# notify the Lambda Runtime that initialization is complete.
unless (mkdir '/tmp/.aws-xray') {
( run in 0.534 second using v1.01-cache-2.11-cpan-5a3173703d6 )