Skip Menu |

This queue is for tickets about the MikroTik-API CPAN distribution.

Report information
The Basics
Id: 121198
Status: resolved
Priority: 0/
Queue: MikroTik-API

People
Owner: MARTINGO [...] cpan.org
Requestors: dhe [...] syrex.co
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 2.0.0



Subject: Moose, slow initialisation
Date: Mon, 17 Apr 2017 05:48:29 +0000
To: "bug-MikroTik-API [...] rt.cpan.org" <bug-MikroTik-API [...] rt.cpan.org>
From: David Herselman <dhe [...] syrex.co>
Hi, Firstly a massive thank you for releasing your Perl Mikrotik API to CPAN. We are successfully using it to monitor BGP sessions as RouterOS doesn't provide BGP SNMP monitoring capabilities. Our NMS (Zabbix) triggers a 'call' for each item we monitor (9 (admin & operational states, status, uptime, prefix count, withdrawns sent & received and updates sent & received)) for each BGP peer on each router. The Mikrotik API however unfortunately takes 0.5 seconds to initialise the big Moose library and very quickly generates a massive load on our Zabbix server when we set monitoring to 60 second intervals. I've adapted our script to use locking and caching retrieved API values but the Moose library continues to be a massive lumbering animal. Disclaimer: I'm really not a programmer but recommendations on PerlMonks were to try replacing Moose with Mouse. Are you still actively maintaining the API? Would it be possible to wish list replacing Moose with a faster/leaner library? PS: I can gladly share our script, if it's of use... Regards David Herselman
On 2017-04-16 23:20:45, dhe@syrex.co wrote: Show quoted text
> 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.
Subject: RE: [rt.cpan.org #121198] Moose, slow initialisation
Date: Tue, 18 Apr 2017 10:45:41 +0000
To: "bug-MikroTik-API [...] rt.cpan.org" <bug-MikroTik-API [...] rt.cpan.org>
From: David Herselman <dhe [...] syrex.co>
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.

Message body is not shown because it is too large.

Download image001.png
image/png 28.8k
image001.png
Download image002.png
image/png 41.3k
image002.png
Download image003.png
image/png 29.8k
image003.png
Download image004.png
image/png 32.9k
image004.png
Thank you for reporting. Did not have a look at the issue tracker for a while :) I know, Moose causes high delays. For my needs (permanently running with Catalyst) this is no real problem although having a few hundred calls per minute. Considered this high compile time during my design decisions (see POD). I know there will be much faster ways but for me comfort had priority over performance. This is also no build from scratch but simply an OO layer over other guys work. I guess you are the author of the changed API2.pm in the mikrotik forum? So you already have a solution? Currently there is no need for me, so no plans for changing the libs within the next months. Perhaps anytime or when someone else creates a pull request on github.
replaced Moose with Moo; shold be notably faster.