How-to write Perl script for MongoDB

First of all, you need to install the MongoDB module for Perl. The easiest way is to use CPAN to install it.

perl -MCPAN -e shell
cpan> install MongoDB

Then, you can start to write scripts. Here is a script I wrote to get some MongoDB status information. 

#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Std;                                 # Parm passing routine
use MongoDB;
use Time::Local;

format HEADER =
------------------------------------------------------------------------------
Syntax : $0 -h vipname -p portnum -u usage


Options:

   -h vipname  
   -p portnum  - default is 27017
   -u usage

------------------------------------------------------------------------------
.

my $hostname;
my $portnum;
my $dbconn;
my $dbadmin;
my $dbcollection;

# ---------------------
# Main
# ---------------------

&do_opts();
&db_connect();
&get_stats();
&db_disconnect();

sub do_opts {
  #--------------------------------------------------------------------------
  # Split the options and load variables
  #--------------------------------------------------------------------------

  # Exempt these varaibles from needing to be declared
  use vars  '$opt_h','$opt_p','$opt_u';

  my $returncode = getopts('h:p:u') ;

  &do_help if (defined $opt_u or $returncode != 1 );
  &do_help if (! $opt_h);

  $hostname          = $opt_h;
  $portnum           = $opt_p || 27017;
}

sub db_connect {
  $dbconn    = MongoDB::Connection->new(host => "mongodb://$hostname:$portnum");
  $dbadmin   = $dbconn->admin;
}

sub db_disconnect {
}

sub do_help {
  #--------------------------------------------------------------------------
  # Give help screen and exit
  #--------------------------------------------------------------------------
  $~ = "HEADER";
  write;
  &quit(0);
}


sub quit {
  exit;
}

sub get_stats {

  my $result = $dbadmin->run_command({serverStatus => 1});
  #my $result = $dbadmin->run_command({'serverStatus' => 1, 'repl' => 2});      #didn't work with 2 parameters
  #my $result = $dbadmin->get_collection('$cmd')->find_one(Tie::IxHash->new('serverStatus' => 1, 'repl' => 2));   #works, but complex syntax

  print "current : $result->{connections}->{current}\n";

  print "resident : $result->{mem}->{resident}\n";
  print "mapped : $result->{mem}->{mapped}\n";
  print "virtual : $result->{mem}->{virtual}\n";

  print "accesses : $result->{indexCounters}->{btree}->{accesses}\n";
  print "hits : $result->{indexCounters}->{btree}->{hits}\n";
  print "misses : $result->{indexCounters}->{btree}->{misses}\n";
  print "resets : $result->{indexCounters}->{btree}->{resets}\n";

  print "flushes : $result->{backgroundFlushing}->{flushes}\n";
  print "total_ms : $result->{backgroundFlushing}->{total_ms}\n";
  print "average_ms : $result->{backgroundFlushing}->{average_ms}\n";
  print "last_ms : $result->{backgroundFlushing}->{last_ms}\n";

  print "insert : $result->{opcounters}->{insert}\n";
  print "query : $result->{opcounters}->{query}\n";
  print "update : $result->{opcounters}->{update}\n";
  print "delete : $result->{opcounters}->{delete}\n";
  print "getmore : $result->{opcounters}->{getmore}\n";
  print "command : $result->{opcounters}->{command}\n";

  my $lagsec = -1;
  my $primary_optimeDate;
  my $primary_time;
  my $my_optimeDate;
  my $my_time;
  $result = $dbadmin->run_command({replSetGetStatus => 1});
  foreach my $repl ( @{$result->{members}} ) {
     if ($repl->{stateStr} eq "PRIMARY") {
       $primary_optimeDate = $repl->{optimeDate};
     }
     if (exists($repl->{self}) && $repl->{self} == 1) {
       $my_optimeDate = $repl->{optimeDate};
     }
  }

  #data format:  2011-09-20T21:08:04
  #print "$primary_optimeDate : $my_optimeDate\n";
  if($primary_optimeDate =~ /(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)/) {
    my ($p_sec, $p_min, $p_hour, $p_day, $p_mon,$p_year) = ($6, $5, $4, $3, $2, $1);
    $p_mon = $p_mon - 1;
    $p_year = $p_year - 1900;
    $primary_time = timegm($p_sec, $p_min, $p_hour, $p_day, $p_mon,$p_year);
  }
  if($my_optimeDate =~ /(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)/) {
    my ($m_sec, $m_min, $m_hour, $m_day, $m_mon,$m_year) = ($6, $5, $4, $3, $2, $1);
    #print "$m_sec, $m_min, $m_hour, $m_day, $m_mon, $m_year\n";
    $m_mon = $m_mon - 1;
    $m_year = $m_year - 1900;
    $my_time = timegm($m_sec, $m_min, $m_hour, $m_day, $m_mon,$m_year);
  }
  $lagsec = $primary_time - $my_time if($my_time && $primary_time);
  print "$primary_time: $my_time\n";
  print "lagSeconds : $lagsec\n";
}

The script run 2 commands to get the MongoDB status. We can get the same by run db._adminCommand({serverStatus : 1}) and db._adminCommand({replSetGetStatus : 1}) in MongoDB Shell .   Let’s take a look at the output of the later one:

shared:PRIMARY> db._adminCommand({replSetGetStatus : 1});
{
	"set" : "shared",
	"date" : ISODate("2011-09-22T14:36:40Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "shared.mongodb.org:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 28033,
			"optime" : {
				"t" : 1316677688000,
				"i" : 2
			},
			"optimeDate" : ISODate("2011-09-22T07:48:08Z"),
			"lastHeartbeat" : ISODate("2011-09-22T14:36:39Z")
		},
		{
			"_id" : 1,
			"name" : "shared.mongodb.org:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"optime" : {
				"t" : 1316677688000,
				"i" : 2
			},
			"optimeDate" : ISODate("2011-09-22T07:48:08Z"),
			"self" : true
		}
	],
	"ok" : 1
}

By comparing the output of MongoDB Shell command and the result in Perl. We can find that the result in Perl is mapped to a hash value, and the value of the hash may be a value, a hash or a array. It’s very easy to get the value we want. Here are the script output example:

./getMongoDBStats.pl -h sharedmongo1.mongodb.com
current : 3
resident : 33
mapped : 1392
virtual : 3915
accesses : 1
hits : 1
misses : 0
resets : 0
flushes : 10508
total_ms : 27876
average_ms : 2.65283593452608
last_ms : 0
insert : 0
query : 9
update : 164909
delete : 32
getmore : 164897
command : 253693
1316677688: 1316677688
lagSeconds : 0

Of course, it’s a quite simple one for MongoDB administrator. But it’s a good and great start 🙂

Advertisements

About Alex Zeng
I would be very happy if this blog can help you. I appreciate every honest comments. Please forgive me if I'm too busy to reply your comments in time.

8 Responses to How-to write Perl script for MongoDB

  1. Alex Zeng says:

    When installing Perl MongoDB module, if it kept prompt to ask you whether to install the missed packages, you can reference this page How to not Prompt when Installing a Module

  2. Pingback: How-to use cacti to monitor MongoDB « Oracle Explorer: Standing on the shoulders of giants

  3. raghu says:

    thanks Alex,

    Can you give me some simple examples , which beginners can understand better.
    Eg :
    1. connecting to server
    2.Inserting tables
    3.Retrieving data from the tables …..etc

  4. Pingback: How-to use cacti to monitor MongoDB « Standing on the shoulders of Giants

  5. Pingback: How to write perl script for mongodb | fitsmoke's Blog

  6. sujith says:

    HI Alex,

    Could you please let me know what is the use of -u usage option in script. i understood -h (hostname) -p (port number) but i didnot understand -u (usage). What should I use for this option

    • Alex Zeng says:

      “-u (usage)” means show you how to use the command, the HEADER part. Many scripts use “-h” for that purpose, but this one already used “-h” for hostname.
      Regards,
      Alex

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: