NAME

CGI::Application::Plugin::OpenTracing - Use OpenTracing in CGI Applications

SYNOPSIS

Inside your own CGI Application:

package MyCGI;

use strict;
use warnings;

use base qw/CGI::Application/;

use CGI::Application::Plugin::OpenTracing ( YourImplementation => %options);

Before Setup, initialize the Global Tracer with the following callback to add a list of implementation specific context parameters:

sub opentracing_bootstrap_options {
    service_name    => __PACKAGE__,
    service_type    => 'web',
    resource_name   => 'test.cgi',
}

After Setup, before Run, initialize the Global Tracer with the following callback:

 # any key/values that will be carried over to child spans
 #
 sub opentracing_baggage_items {
     client_id => '123XXX',
     database  => 'secret_toys',
}

DESCRIPTION

This plugin will use the return value from the opentracing_implementation callback to bootstrap a OpenTracing::GlobalTracer, with OpenTracing::Implementation. It uses all the parameters as mentioned in that set method.

It will automatically create a new tracer, with a total of four spans:

cgi_application

This is the root span, wich will have a start time at the beginning of the cgi request, and last till the entire request will be finished.

On top of this rootspan, the following three child-spans will be created:

setup

A childspan, that will take the duration of the entire setup process.

run

After the tracer has been setup (using the information from the callback), this span will be started for the actual duration of the request handling

teardown

OOPS ... not implemented (yet)

ADDING DEEPER INSTRUMENTATION

This plugin only initiates the tracer, and three childspans. For more detail at deeper call levels, one would need the OpenTracing::GlobalTracer and add manual instrumentation using start_active_span:

use OpenTracing::GlobalTracer qw/$TRACER/;

and later per subroutine:

sub foo {
    my $opentracing_scope = $TRACER->start_active_span( foo => \%options );
    
    ...
    
    $opentracing_scope->close( )
}

Alternatively, on can use OpenTracing::AutoScope, which handles all the work in one go:

use OpenTracing::AutoScope;

and later per subroutine:

sub foo {
    OpenTracing::AutoScope->start_guarded_span;
    
    ...
    
}

Lastly, use OpenTracing::Wrap, to automagically wrap scopes and traces around a list of mentioned (fully qualified) subroutine names.

CAVEATS

Probably a few...

Originally, OpenTracing Implementations should extract any context and build new spans based on that. Sadly, no implementations are providing these features.

Since the tracer is only initialised, right before 'run' phase, it is useless to even try to add deeper level of instrumentation during 'setup'. Those will use the default OpenTracing::Implementation::NoOp which ... does nothing.

Traces will get lost, when the rootspan is not closed properly.

Multi-valued query parameters

Query parameters will be automatically added to the cgi_request span as tags with a http.query. prefix. Since span tags cannot contain references, query parameters appearing multiple times will be concatenated with a comma.

You can use a different format by defining an opentracing_format_query_params method in your CGI Application. If present, this method will be called whenever a query parameter is assigned to a tag, with the parameter name and all values as an array reference (even if the parameter only has a single value) as arguments.

For example, to encode values as JSON:

sub opentracing_format_query_params {
    my ($self, $name, $values_ref) = @_;
    return JSON::encode($values_ref);
}

AUTHOR

Theo van Hoesel <tvanhoesel@perceptyx.com>

COPYRIGHT AND LICENSE

'OpenTracing::Implementation::NoOp' is Copyright (C) 2019 .. 2020, Perceptyx Inc

This library is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.

This package is distributed in the hope that it will be useful, but it is provided "as is" and without any express or implied warranties.

For details, see the full text of the license in the file LICENSE.