Server log with Thingspeak

After deciding to use Perl instead of Python, things started moving. I have been putting things off for too long. My first project is to log CPU usage, memory usage and average load on my Linux server. The logged data is uploaded to Thingspeak. My Thingspeak data for this project is public, and you may see it here (https://thingspeak.com/channels/10946).

About the server

I have a HP Proliant Micro Server running Windows 7. Inside Windows I run a VirtualBox Linux server (CentOS 6.5). I use this Linux server mainly for backing up the web server at work, but decided to put it to other uses as well. It will become the gateway for my smart home projects alongside the backup.

About Thingspeak

Thingspeak is, according to themselves, "an open application platform designed to enable meaningful connection between things and people". Or in short, connect your stuff to The Internet. You may choose to let your data from Thingspeak be either public or private. I looked around a lot before deciding on Thingspeak. I found other platforms, but I found them hard to understand and/or use. I'm not very found of reading documentation...

How it works

In short, a Perl script reads the servers (inside VirtualBox) CPU, free memory and the average CPU load every 20 seconds and upload it to Thingspeak. And here is the beauty of it: To upload data to Thingspeak you only need to provide your API key and the data you want to upload. No hard to understand encoding. 

Here's an upload example:
http://api.thingspeak.com/update?key=YOUR_API_KEY&field1=data1&field2=data2&field3=data3

You will get one API key for each channel you create. Each channel contains 8 fields you populate with data of your choice, including GPS coordinates. To read the data you may visit your channel page(es), or download the data in your own scripts and manipulate it as you see fit. As of now Thingspeak supports JSON, XML and CSV, which means you can download your data in any of these formats and present it on your own website if you want.

The Perl script

Below is the Perl script used to read and upload the data to Thingspeak:

#!/usr/bin/perl
 
# Get CPU usage in % and Memory free in MB
# Upload results to Thingspeak
###########################################################
 
use strict;
use warnings 'all';
use utf8;
use HTTP::Tiny qw();
use Sys::Statistics::Linux;
use Time::HiRes qw (sleep);
 
$| = 1;

main();


sub main {
	# Get CPU and amount of free memory (MB)
while(1) {
	my $avg = getCPUAvg(); 
	my $cpu =  getCPUUsage() ;
	my $memfree = (getMemFree() / 1024);
	sendToThingspeak("YOUR_API_KEY",$cpu,$memfree,$avg);
	# sleep for 17 seconds before next upload to Thingspeak
	sleep(17);
	}
}

###########################
# Send data to Thingspeak
# @1 = Api key
# @2 = field1
# @3 = field2
# @3 = field3
###########################
sub sendToThingspeak {
	my $apikey =  $_[0];
	my $field1 =  $_[1];
	my $field2 =  $_[2];
	my $field3 =  $_[3];

	my $url = "http://api.thingspeak.com/update?key=".$apikey."&field1=".$field1."&field2=".$field2."&field3=".$field3;
		my $response = HTTP::Tiny->new->get($url);
		if ($response->{success}) {
		 #   print $response->{content};
		}
		 # You may do some error checking here...
		 # print $response->{status};
	}


###################################
# Return load on CPU this instant
###################################
sub getCPUUsage {
	# https://metacpan.org/pod/Sys::Statistics::Linux

	my $lxs = Sys::Statistics::Linux->new( cpustats => 1 );
	sleep(1);
	my $stat = $lxs->get;
	my $cpu  = $stat->cpustats->{cpu};
    return($cpu->{total});
}

###############################
# Return number of bytes free 
###############################
sub getMemFree {

	# https://metacpan.org/pod/Sys::Statistics::Linux::MemStats

	my $lxs = Sys::Statistics::Linux->new( memstats => 1 );
	sleep(1);
	my $stat = $lxs->get;
	my $mem  = $stat->memstats->{memfree};
    return($mem);
}


###############################################
# Return average CPU load the last 15 minutes 
###############################################
sub getCPUAvg {

	my $lxs  = Sys::Statistics::Linux->new( loadavg => 1 );
    sleep(1);
    my $stat = $lxs->get;
	my $avg_15  = $stat->loadavg->{'avg_15'};
	my $avg_5  = $stat->loadavg->{'avg_5'};
	my $avg_1  = $stat->loadavg->{'avg_1'};
    return($avg_15);
}

Tags: