2

I would like to log SOAP::Lite transport request/response contents using a custom identifier (e.g. a transaction-id or txn_id in my example below):

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

use SOAP::Lite +trace => [ transport => \&log_transport, ];

sub log_transport {
    my ($in) = @_;
    if (ref($in) eq "HTTP::Request") {
        # INSERT INTO logs ( txn_id, request ) VALUES ( $tnx_id, $in->content )
        say STDERR Dumper(ref($in), $in->content);
    }
    elsif (ref($in) eq "HTTP::Response") {
        # UPDATE logs SET response = '$in->content' WHERE txn_id = $tnx_id
        say STDERR Dumper(ref($in), $in->content);  
    }
}

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;
my $soap = SOAP::Lite->proxy('https://www.dataaccess.com/webservicesserver/NumberConversion.wso?op=NumberToWords');
$soap->serializer()->register_ns('http://www.dataaccess.com/webservicesserver/' ,"ns");

sub getWords
{
    my ($number, $txn_id) = @_ ;

    my $method = SOAP::Data->name("ns:NumberToWords");
    my @params = ( SOAP::Data->name("ubiNum" => $number) );
    my $response = $soap->call($method => @params);

    if (!$response->fault) {
        say STDOUT "NumberToWords = " . $response->result;
    }
    else {
        say STDERR "error: " . (defined $response->faultstring? $response->faultstring : $soap->transport->status);
    }
}

getWords(444, '123abc');

In my example above, how can I pass the transaction-id 123abc to my logger?

P.S. I do not wish to use:

$soap->outputxml(1)->call($method => @params)
h q
  • 1,168
  • 2
  • 10
  • 23
  • I am not sure if the trace allows parameters to be passed. As a work around you could use e.g. environment variables, lexical variable declared in the outer scope, or a package variable to communicate with the callback – Håkon Hægland Feb 18 '23 at 20:11

1 Answers1

1

It does not seem like the SOAP::Trace transport callback supports extra argument passing. As a workaround you could use a lexical variable declared in the outer scope like this:

use strict;
use warnings;
use Data::Dumper;

my $TXN_ID;
use SOAP::Lite +trace => [ transport => \&log_transport, ];

sub log_transport {
    my ($in) = @_;
    say STDERR "Logging transaction id: $TXN_ID:";
    if (ref($in) eq "HTTP::Request") {
        # INSERT INTO logs ( txn_id, request ) VALUES ( $tnx_id, $in->content )
        say STDERR Dumper(ref($in), $in->content);
    }
    elsif (ref($in) eq "HTTP::Response") {
        # UPDATE logs SET response = '$in->content' WHERE txn_id = $tnx_id
        say STDERR Dumper(ref($in), $in->content);  
    }
}

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;
my $soap = SOAP::Lite->proxy('https://www.dataaccess.com/webservicesserver/NumberConversion.wso?op=NumberToWords');
$soap->serializer()->register_ns('http://www.dataaccess.com/webservicesserver/' ,"ns");

sub getWords
{
    my ($number, $txn_id) = @_ ;

    $TXN_ID = $txn_id;
    my $method = SOAP::Data->name("ns:NumberToWords");
    my @params = ( SOAP::Data->name("ubiNum" => $number) );
    my $response = $soap->call($method => @params);

    if (!$response->fault) {
        say STDOUT "NumberToWords = " . $response->result;
    }
    else {
        say STDERR "error: " . (defined $response->faultstring? $response->faultstring : $soap->transport->status);
    }
}

getWords(444, '123abc');
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • Unfortunately, it is not possible with a multi-threaded applications. Concurrent calls to `getWords` will yield the wrong value in `$TXN_ID` and hence defeats the purpose. – h q Feb 19 '23 at 06:23
  • *"Concurrent calls to getWords will yield the wrong value in $TXN_ID"* : Can you give an example? Note that even package variables are thread safe in perl, see: https://stackoverflow.com/a/15206125/2173773 – Håkon Hægland Feb 19 '23 at 06:53
  • Thank you @Håkon Hægland. I was under the impression that `$TXN_ID` is a global variable, and it isn't thread-safe. I intend to use this in Mojolicious. – h q Feb 20 '23 at 18:04