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.