Hi Karen,
Herewith the link to the PerlMonks node where I understood the Moose include to be the major delay in running Perl scripts which utilise your MikroTik API:
http://www.perlmonks.org/?node_id=1186845
If I create a virtually empty script file, only including libraries that the MikroTik API includes itself and test with Perl's DProf, I obtain the following:
[admin@zabbix externalscripts]# cat test.pl:
#!/usr/bin/perl
use strict;
use warnings;
use Moose;
use namespace::autoclean;
use Digest::MD5;
use IO::Socket::INET;
use IO::Socket::SSL;
use Time::Out qw{ timeout };
[admin@zabbix externalscripts]# perl -d:DProf ./test.pl; dprofpp
Total Elapsed Time = 0.43 Seconds
User+System Time = 0.41 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c Name
9.76 0.040 0.040 1606 0.0000 0.0000 Package::Stash::PP::_deconstruct_variable_name
4.88 0.020 0.410 11 0.0018 0.0373 main::BEGIN
4.88 0.020 0.270 24 0.0008 0.0113 Moose::BEGIN
4.88 0.020 0.060 1107 0.0000 0.0001 Package::Stash::PP::get_symbol
4.88 0.020 0.030 139 0.0001 0.0002 Class::MOP::Class::__ANON__
4.88 0.020 0.030 18 0.0011 0.0017 Moose::Meta::Class::BEGIN
4.88 0.020 0.020 116 0.0002 0.0002 Class::MOP::Method::Generated::_eval_closure
2.44 0.010 0.010 3 0.0033 0.0033 Moose::Deprecated::BEGIN
2.44 0.010 0.010 32 0.0003 0.0003 strict::unimport
2.44 0.010 0.050 15 0.0007 0.0033 Class::MOP::BEGIN
2.44 0.010 0.040 53 0.0002 0.0008 base::import
2.44 0.010 0.030 17 0.0006 0.0018 Class::MOP::Class::BEGIN
2.44 0.010 0.020 14 0.0007 0.0014 Package::Stash::PP::BEGIN
2.44 0.010 0.010 74 0.0001 0.0001 Package::Stash::PP::new
2.44 0.010 0.010 459 0.0000 0.0000 Package::Stash::PP::_valid_for_type
If I comment out ‘Moose’ and ‘namespace:autoclean’:
[admin@zabbix externalscripts]# perl -d:DProf ./test.pl; dprofpp
Total Elapsed Time = 0.059172 Seconds
User+System Time = 0.059172 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c Name
33.8 0.020 0.059 7 0.0028 0.0085 main::BEGIN
16.9 0.010 0.010 10 0.0010 0.0010 vars::import
16.9 0.010 0.010 4 0.0025 0.0025 Socket6::BEGIN
16.9 0.010 0.010 11 0.0009 0.0009 strict::unimport
16.9 0.010 0.010 6 0.0017 0.0016 IO::Socket::INET::BEGIN
0.00 0.000 0.000 1 0.0000 0.0000 Net::SSLeay::VERIFY_NONE
0.00 0.000 0.000 1 0.0000 0.0000 Net::SSLeay::VERIFY_PEER
0.00 0.000 0.000 1 0.0000 0.0000 Net::SSLeay::VERIFY_FAIL_IF_NO_PEER_CERT
0.00 0.000 0.000 1 0.0000 0.0000 Net::SSLeay::VERIFY_CLIENT_ONCE
0.00 0.000 0.000 1 0.0000 0.0000 Config::launcher
0.00 0.000 0.000 1 0.0000 0.0000 AutoLoader::AUTOLOAD
0.00 0.000 0.000 1 0.0000 0.0000 Net::SSLeay::randomize
0.00 0.000 0.000 1 0.0000 0.0000 Net::SSLeay::ERROR_WANT_READ
0.00 0.000 0.000 1 0.0000 0.0000 Net::SSLeay::ERROR_WANT_WRITE
0.00 - -0.000 1 - - Config::AUTOLOAD
PS: System’s own load influences the difference between ‘total elapsed time’ and ‘user+system time’
For what it’s worth, you can gladly include the following Zabbix MikroTik BGP session monitoring script as part of your public examples. The script supports JSON discovery, locking and value caching to avoid the API being called too often or concurrently:
#!/usr/bin/perl
use strict;
use warnings;
use MikroTik::API; #
http://search.cpan.org/~martingo/MikroTik-API/lib/MikroTik/API/Examples.pm
use Fcntl qw(:flock);
use Storable qw(lock_store lock_nstore lock_retrieve);
my ($router, $api_user, $api_passwd, $command, $peer, $key) = @ARGV;
if (not defined $router) { print STDERR "Need router FQDN or IP, as first parameter.\n"; exit 3 };
if (not defined $api_user) { print STDERR "Need MikroTik API username, as second parameter.\n"; exit 4 };
if (not defined $api_passwd) { print STDERR "Need MikroTik API password, as third parameter.\n"; exit 5 };
my $cache_ttl = 595;
my $cachefile = '/tmp/mtapi.'.$router.'.cache';
sub mtdate {
my $hdate = shift;
my ($years, $weeks, $days, $hours, $minutes, $seconds) = (0) x 7;
if ($hdate =~ /^\d+y/) { ($years = $hdate) =~ s/^(\d+)y.*/$1/ };
if ($hdate =~ /(^|[y])\d+w/) { ($weeks = $hdate) =~ s/.*?(\d+)w.*/$1/ };
if ($hdate =~ /(^|[yw])\d+d/) { ($days = $hdate) =~ s/.*?(\d+)d.*/$1/ };
if ($hdate =~ /(^|[ywd])\d+h/) { ($hours = $hdate) =~ s/.*?(\d+)h.*/$1/ };
if ($hdate =~ /(^|[ywdh])\d+m/) { ($minutes = $hdate) =~ s/.*?(\d+)m.*/$1/ };
if ($hdate =~ /(^|[ywdhm])\d+s/) { ($seconds = $hdate) =~ s/.*?(\d+)s.*/$1/ };
return ($years*31536000)+($weeks*604800)+($days*86400)+($hours*3600)+($minutes*60)+$seconds;
}
my $api = MikroTik::API->new (
{
host => $router,
username => $api_user,
password => $api_passwd,
use_ssl => 1,
autoconnect => 0,
}
);
my %bgp_peer;
my $cached = 0;
my $modified = (stat($cachefile))[9];
open our $lockfile, '<', $0 || die $!;
if (defined $modified) {
if (($modified >= (time-$cache_ttl)) || (!flock $lockfile, LOCK_EX | LOCK_NB)) {
if (%bgp_peer = %{lock_retrieve($cachefile)}) { $cached = 1 };
}
}
if ($cached == 0) {
if (!flock $lockfile, LOCK_EX | LOCK_NB) { print STDERR "Another process is already using MikroTik API.\n"; exit 6 };
$api->connect();
$api->login();
%bgp_peer = $api->get_by_key('/routing/bgp/peer/print', 'name');
$api->logout();
lock_nstore \%bgp_peer, $cachefile;
chmod 0660, $cachefile;
flock $lockfile, LOCK_UN;
}
if ($command =~ /^(-d|--discover)$/) {
print "{\n\t\"data\": [\n";
my $first = 1;
foreach my $peer ( sort keys %bgp_peer ) {
if ($first == 0) { print ",\n" };
print "\t\t{ \"{#BGPPEER}\": \"", $peer, "\" }";
$first = 0;
}
print "\n\t]\n}\n";
}
elsif ($command =~ /^(-c|--croak)$/) {
foreach my $peer ( sort keys %bgp_peer ) {
print "peer: ", $peer, "\n ", join("\n ", sort map{qq{$_=$bgp_peer{$peer}->{$_}}} keys %{$bgp_peer{$peer}}, "\n" ), "\n";
}
}
elsif ($command =~ /^(-t|--table)$/) {
printf ("%-25s %-7s %9s %15s %9s %18.18s %s\n", "Peer", "Active", "Prefixes", "Remote IP", "Remote AS", "Uptime", "State");
foreach my $peer ( sort keys %bgp_peer ) {
printf ("%-25.25s %-7.7s %9.9s %15.15s %9.9s %18.18s %s\n", $peer, $bgp_peer{$peer}->{'disabled'} eq 'true' ? 'no' : 'yes', $bgp_peer{$peer}->{'prefix-count'}, $bgp_peer{$peer}->{'remote-address'}, $bgp_peer{$peer}->{'remote-as'}, $bgp_peer{$peer}->{'uptime'}, $bgp_peer{$peer}->{'state'} );
}
}
elsif ($command =~ /^(-g|--get)$/) {
if (not defined $peer) { print STDERR "No peer specified.\n"; exit 8 };
if (not defined $key) { print STDERR "No key specified.\n"; exit 9 };
if (defined $bgp_peer{$peer}->{$key}) {
if ($key =~ /^uptime$/) {
print &mtdate($bgp_peer{$peer}->{$key}),"\n";
}
elsif ($key =~ /^disabled$/) {
print $bgp_peer{$peer}->{$key} eq "true" ? 2 : 1,"\n";
}
elsif ($key =~ /^(as-override|as4-capability|established|multihop|passive|refresh-capability|remove-private-as|route-reflect|use-bfd)$/) {
print $bgp_peer{$peer}->{$key} eq "true" ? 1 : 2,"\n";
}
else { print "$bgp_peer{$peer}->{$key}\n" }
}
else {
print STDERR "MikroTik API response does not contain \$bgp_peer{'$peer'}->{'$key'}.\n";
exit 10;
}
}
else {
print STDERR <<EOF;
Missing or invalid command. Usage $0 <router> <api username> <api password> <command> [<peer>] :
-d|--discover Zabbix LLD (low level discovery). In JSON format.
-c|--croak Dumps all available data. Usable as \$bgp_peer{'\$peer'}->{'key'}
-t|--table Displays tabled overview
-g|--get <peer> <key> example: -g \"Syrex - Primary\" state
Examples:
Discovery : $0 10.0.0.1 syrexnms \"FakeP\@ssw0rd\" -d
Sample : {
\"data\": [
{ \"{#BGPPEER}\": \"Syrex - Primary\" },
{ \"{#BGPPEER}\": \"Syrex - Secondary\" }
]
}
Get item : $0 10.0.0.1 syrexnms \"FakeP\@ssw0rd\" \"Syrex - Primary\" state
Sample : established
EOF
exit 7;
}
exit 0;
PS: I’ll gladly export and provide our Zabbix template, so that the script can easily be used by others…
Sample text table output:
[admin@zabbix externalscripts]# ./mikrotik-api-bgp_status.pl zatjnb01-pe01.syrex.co.za syrexnms ‘FakeP@ssw0rd' -t
Peer Active Prefixes Remote IP Remote AS Uptime State
ECN yes 2 172.37.17.205 36968 2w1d15h37m26s established
Google yes 401 41.79.22.65 15169 3d7h48m30s established
NAPAfrica - Collector yes 0 196.60.9.1 37186 1w5d10h4m8s established
NAPAfrica - Primary yes 45604 196.60.9.2 37195 1w5d10h4m9s established
NAPAfrica - Secondary yes 45531 196.60.9.3 37195 1w5d10h4m9s established
Seacom yes 1 105.22.33.33 37100 2w1d15h37m26s established
Spamhaus yes 1420 94.228.136.140 65190 3d7h16m42s established
Syrex - zatjnb01-rr01 yes 1118 41.79.22.6 37314 2w1d15h37m13s established
Syrex - zatjnb01-rr02 yes 1118 41.79.22.7 37314 2w1d15h37m19s established
Team Cymru - Bogons yes 3797 38.229.66.20 65332 22h6m32s established
Team Cymru - UTRS yes 54 154.35.32.141 64496 2d16h17m29s established
Telkom yes 103 196.25.155.41 5713 2w1d15h37m26s established
XConnect yes 3 41.242.227.66 37105 2w1d15h37m27s established
iOnline yes 24 198.19.28.106 327909 2w1d15h37m26s established
Zabbix – Establishment graph:
[cid:image001.png@01D2B83F.42A78150]
Zabbix – BGP prefix activity graph:
[cid:image002.png@01D2B83F.42A78150]
Zabbix – BGP prefix count graph:
[cid:image003.png@01D2B840.31212840]
Zabbix – BGP session uptime graph:
[cid:image004.png@01D2B840.31212840]
Regards
David Herselman
Show quoted text-----Original Message-----
From: Karen Etheridge via RT [mailto:bug-MikroTik-API@rt.cpan.org]
Sent: Tuesday, 18 April 2017 2:22 AM
To: David Herselman <dhe@syrex.co>
Subject: [rt.cpan.org #121198] Moose, slow initialisation
<URL:
https://rt.cpan.org/Ticket/Display.html?id=121198 >
On 2017-04-16 23:20:45, dhe@syrex.co<mailto:dhe@syrex.co> wrote:
> Disclaimer: I'm really not a programmer but recommendations on
> PerlMonks were to try replacing Moose with Mouse.
What post was that? It must have been very old -- I would recommend looking at Moo instead.