Server monitoring

Hi all

Just wanted to contribute something maybe useful to the community :-)

I use EmonCMS mostly for the solar logging of the Enecsys Stuff I have written but I always thought there is more usage of it and I made a Server monitoring script which uses the Windows WMI stuff to read out the syste information. WMI is really powerful and once understood you can change and read out almost everything of Windows. I have it tested on Win8 and Windows Server 2012.

To browse through the WMI Namespaces I suggest to use a tool called WMI Explorer: https://wmie.codeplex.com/
WMI Explorer is a utility intended to provide the ability to browse and view WMI namespaces/classes/instances/properties in a single pane of view.

A demo of what you can do with it is here: http://swiss-solar-log.ch:85/firefox&id=62

Here is the code:

#!/usr/bin/perl
#---------------------------------------------------------------------
# This is a simple Monitoring script which reads out data from Windows WMI
# Storage. WMI can be accessed and used like SQL Queries. Use Tools like
# WMI Explorer to browse through all the available classes. Microsoft already 
# pre formatted a lot of the data so you can most of the time use the data without
# any calculations!
# To access the data you have to use the connection string:
# $objWMIService = Win32::OLE->GetObject 
#    ("winmgmts:\\\\$computer\\root\\CIMV2") or die "WMI connection failed.\n"; 
# U can exchange the CIMV2 with an other object to access other data. Most of the data
#  however is available in CIMV2 as you can see in the script below.
#
# Author: Andreas Messerli, Switzerland
# e-mail of Author: firefox7518(at)gmail.com
# If you find issues or failures please let the author now about it so that he can update and
# enhance the script for the usage of all of us.
#---------------------------------------------------------------------

use Win32::OLE('in'); 
use constant wbemFlagReturnImmediately => 0x10; 
use constant wbemFlagForwardOnly => 0x20; 
use LWP::Simple;
use IO::Socket;

my $apikey="Your write Api Key here";
my $emonhost = "Your EmonCMS IP or domain name here";
# To poll for example running servers like MySQL, E-Mail POP etc. you have to define the Server IP here or use 127.0.0.1
my $host = "Server IP adress";

 
$computer = "."; 
$objWMIService = Win32::OLE->GetObject 
    ("winmgmts:\\\\$computer\\root\\CIMV2") or die "WMI connection failed.\n"; 
    
    

# Init WMI for CPU
my $wmi = Win32::OLE->GetObject("winmgmts://./root/cimv2")
    or die "Failed getobject\n";

# get WMI values for CPU
sub get_wmi{
    my $wmi = shift;
    my $list, my $v;
    my @properties = qw(PercentProcessorTime TimeStamp_Sys100NS);
    my $class = 'Win32_PerfRawData_PerfOS_Processor';
    my $key = 'Name';
    $list = $wmi->InstancesOf("$class")
        or die "Failed getobject\n";
    my $hash;
    foreach $v (in $list) {        
        $hash->{$v->{$key}}->{$_}  = $v->{$_} for @properties;
    }
    $hash;
}

my $cpu;
my $hash_prev = get_wmi($wmi);
    
 
while (1){ 

    $RAMItems = $objWMIService->ExecQuery 
        ("SELECT * FROM Win32_OperatingSystem","WQL",wbemFlagReturnImmediately | wbemFlagForwardOnly); 

    $CPUItems = $objWMIService->ExecQuery 
        ("SELECT * FROM Win32_PerfRawData_PerfOS_Processor","WQL",wbemFlagReturnImmediately | wbemFlagForwardOnly); 

    $HDDItems = $objWMIService->ExecQuery 
        ("SELECT * FROM Win32_LogicalDisk","WQL",wbemFlagReturnImmediately | wbemFlagForwardOnly); 
        
    $Perfitems = $objWMIService->ExecQuery 
        ("SELECT * FROM Win32_PerfFormattedData_PerfOS_System","WQL",wbemFlagReturnImmediately | wbemFlagForwardOnly);     

    $IISItems = $objWMIService->ExecQuery 
        ("SELECT * FROM Win32_PerfRawData_W3SVC_WebService","WQL",wbemFlagReturnImmediately | wbemFlagForwardOnly);        
        
    #--------------------------------------------------------------------
    #  Start Server Performance Usasge Check section
    #--------------------------------------------------------------------    
    {
    foreach my $objItem (in $Perfitems) {

    my $FileDataOperationsPersec = $objItem->{FileDataOperationsPersec};
    my $FileReadKBytesPersec = $objItem->{FileReadBytesPersec} / 1024;
    my $FileReadOperationsPersec = $objItem->{FileReadOperationsPersec};
    my $FileWriteKBytesPersec = $objItem->{FileWriteBytesPersec} / 1024;
    my $FileWriteOperationsPersec = $objItem->{FileWriteOperationsPersec};
    my $FloatingEmulationsPersec = $objItem->{FloatingEmulationsPersec};
    my $Processes = $objItem->{Processes};
    my $ProcessorQueueLength = $objItem->{ProcessorQueueLength};
    my $SystemCallsPersec = $objItem->{SystemCallsPersec};
    my $Threads = $objItem->{Threads};
    
      print "File Data Operations Per sec: $objItem->{FileDataOperationsPersec}\n";
      print "File Read KBytes Per sec: $FileReadKBytesPersec\n";
      print "File Read Operations Per sec: $objItem->{FileReadOperationsPersec}\n";
      print "File Write KBytes Per sec : $FileWriteKBytesPersec \n";
      print "File Write Operations Per sec : $objItem->{FileWriteOperationsPersec}\n";
      print "Floating Emulations Per sec : $objItem->{FloatingEmulationsPersec}\n";
      print "Processes : $objItem->{Processes}\n";
      print "Processor Queue Length : $objItem->{ProcessorQueueLength}\n";
      print "System Calls Per sec : $objItem->{SystemCallsPersec}\n";
      print "Threads : $objItem->{Threads}\n";
      print "\n"; 
      
    my $IDDec = "OS_Performance_Data";
    my $url = "http://$emonhost/input/post.json?node=$IDDec&json={FileDataOperationsPersec:$FileDataOperationsPersec, FileReadKBytesPersec:$FileReadKBytesPersec, FileReadOperationsPersec:$FileReadOperationsPersec, FileWriteKBytesPersec:$FileWriteKBytesPersec, FileWriteOperationsPersec:$FileWriteOperationsPersec, FloatingEmulationsPersec:$FloatingEmulationsPersec, Processes:$Processes, ProcessorQueueLength:$ProcessorQueueLength, SystemCallsPersec:$SystemCallsPersec, Threads:$Threads}&apikey=$apikey"; 
    my $content = get $url;
    print "Sending data to EmonCMS = $url\n";
    }
    }
    
    #--------------------------------------------------------------------
    #  End Server Performance Usasge Check section
    #--------------------------------------------------------------------    

    
        
    #--------------------------------------------------------------------
    #  Start IIS Usasge Check section
    #--------------------------------------------------------------------    
    {
    
        foreach my $objItem (in $IISItems){ 
        my $AnonymousUsersPersec = $objItem->{AnonymousUsersPersec};
        my $BytesReceivedPersec = $objItem->{BytesReceivedPersec};
        my $KBytesReceivedPersec = $objItem->{BytesReceivedPersec} / 1024;
        my $BytesSentPersec = $objItem->{BytesSentPersec};
        my $KBytesSentPersec = $objItem->{BytesSentPersec} / 1024;
        my $CurrentConnections = $objItem->{CurrentConnections};
        my $BytesSentPersec = $objItem->{BytesSentPersec};
         
        print "Websitename: $objItem->{Name}\n";
        print "Anonymous Users Per sec: $objItem->{AnonymousUsersPersec}\n";
        print "Bytes Received Per sec: $objItem->{BytesReceivedPersec}\n";
        print "Bytes Sent Per sec: $objItem->{BytesSentPersec}\n";
        print "Current Connections: $objItem->{CurrentConnections}\n"; 
        print "Bytes Sent Per sec: $objItem->{BytesSentPersec}\n";
        print "\n"; 
          
        my $IDDec = $objItem->{Name};
        my $url = "http://$emonhost/input/post.json?node=$IDDec&json={AnonymousUsersPersec:$AnonymousUsersPersec , BytesReceivedPersec:$BytesReceivedPersec , BytesSentPersec:$BytesSentPersec , CurrentConnections:$CurrentConnections , BytesSentPersec:$BytesSentPersec, KBytesSentPersec:$KBytesSentPersec, KBytesReceivedPersec:$KBytesReceivedPersec}&apikey=$apikey"; 
        my $content = get $url;
        print "Sending data to EmonCMS = $url\n";
        } 
    }
    
    #--------------------------------------------------------------------
    #  End IIS Usasge Check section
    #--------------------------------------------------------------------    

    
    #--------------------------------------------------------------------
    #  Start Memomry Usasge Check section
    #--------------------------------------------------------------------
        {
        foreach my $objItem (in $RAMItems){ 
          $total_mem = $objItem->{TotalVisibleMemorySize} / 1024;
          $free_mem = $objItem->{FreePhysicalMemory} / 1024;
          $used_mem = $total_mem - $free_mem;
          $mem_percent = sprintf("%.2f", $used_mem / $total_mem * 100);
          $free_percent  =  sprintf("%.2f", $free_mem / $total_mem * 100);
          
          
          print "Free Physical Memory: $objItem->{FreePhysicalMemory}\n"; 
          print "Free Virtual Memory: $objItem->{FreeVirtualMemory}\n"; 
          print "Number Of Processes: $objItem->{NumberOfProcesses}\n"; 
          print "Total Virtual Memory Size: $objItem->{TotalVirtualMemorySize}\n"; 
          print "Total Visible Memory Size: $objItem->{TotalVisibleMemorySize}\n"; 
          print "Used Memory: $used_mem \n";
          print "Used Memory Percent: $mem_percent \n";
          print "Free Memory percent: $free_percent \n";
          print "\n"; 
          my $IDDec = "RAM-data";
          my $url = "http://$emonhost/input/post.json?node=$IDDec&json={Memory_used_percent:$mem_percent,Memory_free_percent:$free_percent,Memory_total:
$total_mem,Memory_used:$used_mem,Memory_free:$free_mem}&apikey=$apikey"; 
          my $content = get $url;
          print "Sending data to EmonCMS = $url\n";
        } 
    }
    #--------------------------------------------------------------------
    #  End Memomry Usasge Check section
    #--------------------------------------------------------------------
    
    
    #--------------------------------------------------------------------
    #  Start HDD Usasge Check section
    #--------------------------------------------------------------------
    {
        foreach my $objItem (in $HDDItems){ 
          $free_hdd = $objItem->{FreeSpace} / 1024 / 1024;
          $hdd_size = $objItem->{Size} / 1024 / 1024;
          $hdd_used = $hdd_size - $free_hdd;
          $hdd_used_percent = sprintf("%.2f", $hdd_used / $hdd_size * 100);
          $hdd_free_percent  =  sprintf("%.2f", $free_hdd / $hdd_size * 100);
          
          
          print "Free Space: $free_hdd\n"; 
          print "Size: $hdd_size\n"; 
          print "\n"; 
          
          my $IDDec = "HDD-Usage";
          my $url = "http://$emonhost/input/post.json?node=$IDDec&json={HDD_Free_Space:$free_hdd,HDD_free_percent:$hdd_free_percent}&apikey=$apikey"; 
          my $content = get $url;
          print "Sending data to EmonCMS = $url\n";
        } 
    }
    #--------------------------------------------------------------------
    #  End HDD Usasge Check section
    #--------------------------------------------------------------------
    
    
    #--------------------------------------------------------------------
    #  Start CPU Usasge Check section
    #--------------------------------------------------------------------
    {
    my $hash = get_wmi($wmi);
    $cpu = sprintf("%.2f", 
        (
            1 - (
                    $hash->{'_Total'}->{'PercentProcessorTime'} - $hash_prev->{'_Total'}->{'PercentProcessorTime'}
                ) / 
                (
                    $hash->{'_Total'}->{'TimeStamp_Sys100NS'} - $hash_prev->{'_Total'}->{'TimeStamp_Sys100NS'}
                ) 
        )* 100 );    
    print "CPU=$cpu\n";    
    $hash_prev = $hash;
    my $IDDec = "CPU-Usage";
    my $url = "http://$emonhost/input/post.json?node=$IDDec&json={CPU_Average:$cpu}&apikey=$apikey"; 
    my $content = get $url;
    print "Sending data to EmonCMS = $url\n";
    
    }
    #--------------------------------------------------------------------
    #  End CPU Usasge Check section
    #--------------------------------------------------------------------
            
    #--------------------------------------------------------------------
    #  Start MySQL Server Check section
    #--------------------------------------------------------------------
    {
    my $port = "3307";
    #
    #  Try to connect
    #
    my $remote = IO::Socket::INET->new(
    Proto    => "tcp",
    PeerAddr => $host,
    PeerPort => $port,
    Timeout  => 8,
    );

    #
    #  Print response
    #
    if ($remote) {
        my $url = "http://$emonhost/input/post.json?node=MySQLServer&json={Server-running:1}&apikey=$apikey"; 
        my $content = get $url;
        print "$host MySQL Server is alive\n";
        close $remote;
        
    }
    else {
        my $url2 = "http://$emonhost/input/post.json?node=MySQLServer&json={Server-running:0}&apikey=$apikey"; 
        my $content2 = get $url2;
        print "$host MySQL Server failed\n";
        
        }
    }
    #--------------------------------------------------------------------
    #  End MySQL Server Check section
    #--------------------------------------------------------------------
    
    print "Restart monitoring in 10secodns";
    sleep 20;
}
# End of Script, it will loop forever because of while(1) 

If you don't have IIS installed you can delete the IIS section. 

If you find issues or failures please let me know. I'm not a pro when it comes to programming, still have to learn a lot.....

Hope there people out there finding it useful....

Enjoy
Andreas

 

Edit - wrapped long lines - BT

pisoni.silvano@gmail.com's picture

Re: Server monitoring

Great work!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.