CGI-Application-Plugin-OpenTracing

 view release on metacpan or  search on metacpan

lib/CGI/Application/Plugin/OpenTracing.pm  view on Meta::CPAN

    my $cgi_app = shift;
    
    my $plugin = _get_plugin($cgi_app);
    
    $plugin->close_scope(       CGI_RUN                            );
    $plugin->start_active_span( CGI_TEARDOWN                       );
    
    return
}



sub load_tmpl {
    my $cgi_app = shift;
    
    my $plugin = _get_plugin($cgi_app);
    
    $plugin->close_scope(       CGI_LOAD_TMPL                      );
    
    return
}



sub teardown {
    my $cgi_app = shift;
    
    my $plugin  = _get_plugin($cgi_app);
    
    my %http_status_tags = _get_http_status_tags($cgi_app);
    my $error = 1
        if is_server_error([_cgi_get_header_status($cgi_app)]->[0]);
    
    $plugin->close_scope(       CGI_TEARDOWN                       );
    $plugin->add_tags(          CGI_REQUEST, %http_status_tags     );
    $plugin->add_tags(          CGI_REQUEST, maybe error => $error );
    $plugin->close_scope(       CGI_REQUEST                        );
    
    return
}



sub error {
    my ($cgi_app, $error) = @_;
    
    my $plugin  = _get_plugin($cgi_app);
    
    return if not $cgi_app->error_mode();    # we're dying
    
    $plugin->add_tags(TRC_ACTIVE_SCOPE,
        error   => 1,
        message => $error,
        grep_error_tags( $plugin->get_tags(TRC_ACTIVE_SCOPE) ),
    );
    
    # run span should continue
    my $root = $plugin->get_scope(CGI_RUN)->get_span;
    
    my $tracer = $plugin->get_tracer();
    _cascade_set_failed_spans($tracer, $error, $root);
    
    return;
}



################################################################################
#
#   Plugin methods - These do not require the CGI-App
#
################################################################################



sub set_tracer {
    my $plugin = shift;
    my $tracer = shift;
    
    $plugin->{TRACER} = $tracer;
}

sub get_tracer {
    my $plugin = shift;
    
    return $plugin->{TRACER}
}

sub start_active_span {
    my $plugin         = shift;
    my $scope_name     = shift;
    my %params         = @_;
    
    my $operation_name = lc $scope_name;
    
    my $tracer = $plugin->get_tracer();
    my $scope = $tracer->start_active_span( $operation_name, %params );
    
    $plugin->{SCOPE}{$scope_name} = $scope;
}

sub add_tags {
    my $plugin         = shift;
    my $scope_name     = shift;
    my %tags           = @_;
    
    my $span = $plugin->get_span($scope_name);
    $span && $span->add_tags(%tags);
}

sub get_tags {
    my $plugin         = shift;
    my $scope_name     = shift;
    
    my $span = $plugin->get_span($scope_name) or return ();
    $span && $span->get_tags();
}

sub add_baggage_items {
    my $plugin         = shift;
    my $scope_name     = shift;

lib/CGI/Application/Plugin/OpenTracing.pm  view on Meta::CPAN

}

sub close_scope {
    my $plugin         = shift;
    my $scope_name     = shift;
    
    my $scope = $plugin->get_scope($scope_name);
    $scope && $scope->close;
}

sub get_span {
    my $plugin         = shift;
    my $scope_name     = shift;
    
    my $scope = $plugin->get_scope($scope_name);
    $scope && $scope->get_span;
}

sub get_scope {
    my $plugin         = shift;
    my $scope_name     = shift;
    
    return $plugin->get_tracer()->get_scope_manager->get_active_scope()
        if $scope_name eq TRC_ACTIVE_SCOPE;
    
    return $plugin->{SCOPE}{$scope_name};
}



################################################################################
#
#   OpenTracing
#
################################################################################



sub _opentracing_init_tracer {
    my @bootstrap_options = @_;
    
    my $bootstrapped_tracer =
        $implementation_import_name ?
            OpenTracing::Implementation->bootstrap_tracer(
                $implementation_import_name,
                @implementation_import_opts,
                @bootstrap_options,
            )
            :
            OpenTracing::Implementation->bootstrap_default_tracer(
                @implementation_import_opts,
                @bootstrap_options,
            )
    ;
        
    return $bootstrapped_tracer;
}



sub _cascade_set_failed_spans {
    my ($tracer, $error, $root_span) = @_;
    my $root_addr = refaddr($root_span) if defined $root_span;

    while (my $scope = $tracer->get_scope_manager->get_active_scope()) {
        my $span = $scope->get_span();
        last if defined $root_addr and $root_addr eq refaddr($span);
        
#       $span->add_tags(error => 1, message => $error);
        $scope->close();
    }
    return;
}



sub grep_error_tags {
    my %tags = @_;
    
    return (
        maybe 'error'      => $tags{'error'},
        maybe 'message'    => $tags{'message'},
        maybe 'error.kind' => $tags{'error.kind'},
    )
}


################################################################################
#
#   CGI – purely CGI related
#
################################################################################



sub _cgi_get_run_mode {
    my $cgi_app = shift;
    
    my $run_mode = $cgi_app->get_current_runmode();
    
    return $run_mode
}



sub _cgi_get_run_method {
    my $cgi_app = shift;
    
    my $run_mode = $cgi_app->get_current_runmode();
    my $run_methode = { $cgi_app->run_modes }->{ $run_mode };
    
    return $run_methode
}


sub _cgi_get_header_status {
    my $cgi_app = shift;

    my %headers = $cgi_app->header_props();
    my $status = $headers{-status};
    

lib/CGI/Application/Plugin/OpenTracing.pm  view on Meta::CPAN

            }
        }
    }
    my $spec = sub {
        my ($name) = @_;
        
        # return match state separately to differentiate from undef processors
        return (1, $direct_match{$name}) if exists $direct_match{$name};
        
        foreach (@regex) {
            my ($re, $processor) = @$_;
            return (1, $processor) if $name =~ $re;
        }
        return;
    };
    
    return ($spec, $fallback);
}



sub _wrap_run {
    my ($orig) = @_;

    return sub {
        my $cgi_app = shift;

        my $res;
        my $wantarray = wantarray;    # eval has its own
        my $ok = eval {
            if ($wantarray) {
                $res = [ $cgi_app->$orig(@_) ];
            }
            else {
                $res = $cgi_app->$orig(@_);
            }
            1;
        };
        return $wantarray ? @$res : $res if $ok;

        my $error = $@;
        
        $cgi_app->header_add(-status => HTTP_INTERNAL_SERVER_ERROR);
        
        my $plugin = _get_plugin($cgi_app);
        
        $plugin->add_tags(CGI_REQUEST,
            _get_http_status_tags($cgi_app),
            grep_error_tags( $plugin->get_tags(TRC_ACTIVE_SCOPE) ),
            error   => 1,
            message => $error,
        );
        
        $plugin->add_tags(TRC_ACTIVE_SCOPE,
            error   => 1,
            message => $error,
            grep_error_tags( $plugin->get_tags(TRC_ACTIVE_SCOPE) ),
        );
        
        my $tracer = $plugin->get_tracer();
        _cascade_set_failed_spans($tracer, $error);

        die $error;
    };
}



1;



( run in 0.427 second using v1.01-cache-2.11-cpan-e93a5daba3e )