Domanda

I am new in Perl and also RRDs.

I have tried to implement a simple example, and although it seems that is operating correctly the output is not displayed. The pictures are produced normally but there is no data in the graphs.

I have been following the CPAN documentation for implementation RRD::Simple and theoretically I am doing something wrong. I tried to debug the code and it seems fine, but when it comes to print the graphs there is no data.

#!/usr/bin/perl
use strict;
use warnings;

use RRD::Simple ();
use Data::Dumper;

$| = 1;    # Flush the output

my ($rrd, $unixtime, $file);

$file = "perl.txt";
my $path    = '/home/os/Desktop/Test_Perl/';
my $period  = '3years';
my $rrdfile = 'myfile.rrd';

while (sleep 15) {

  open(FH, ">>", $file) || die "Unable to open $file: $!\n";

  my $range   = 50;
  my $minimum = 100;

  my $random_number_in  = int(rand($range)) + $minimum;
  my $random_number_out = int(rand($range)) + $minimum;
  my $random_number_sec = int(rand($range)) + $minimum;

  # Create an interface object
  $rrd = RRD::Simple->new(
    file => $rrdfile,
    cf   => [qw( AVERAGE MIN MAX LAST )],
    #default_dstype => "DERIVE",
  );

  unless (-e $rrdfile) {

    # Create a new RRD file with 3 data sources called
    # bytesIn, bytesOut and faultsPerSec.
    $rrd->create(
      $period,
      step         => 5,         # 5 sec interval
      bytesIn      => "GAUGE",
      bytesOut     => "GAUGE",
      faultsPerSec => "GAUGE"
    );
  }

  # Put some arbitary data values in the RRD file for the same
  # 3 data sources called bytesIn, bytesOut and faultsPerSec.
  $rrd->update(
    bytesIn      => $random_number_in,
    bytesOut     => $random_number_out,
    faultsPerSec => $random_number_sec
  );
  print FH "This is the bytes_in: $random_number_in\n";
  print FH "This is the bytes_out: $random_number_out\n";
  print FH "This is the bytes_sec: $random_number_sec\n";

  # Generate graphs:
  #  /home/os/Desktop/Test_Perl/myfile-hourly.png, /home/os/Desktop/Test_Perl/myfile-daily.png
  #  /home/os/Desktop/Test_Perl/myfile-weekly.png, /home/os/Desktop/Test_Perl/myfile-monthly.png

  my %rtn = $rrd->graph(
    $rrdfile,
    destination => $path,
    basename    => "my_graph",
    timestamp   => "both",                       # graph, rrd, both or none
    periods     => [qw(hour day week month)],    # omit to generate all graphs
    sources          => [qw(bytesIn bytesOut faultsPerSec)],
    source_colors    => [qw(ff0000 aa3333 000000)],
    source_labels    => [("Bytes In", "Bytes Out", "Faults Per Second")],
    source_drawtypes => [qw(LINE1 AREA LINE)],
    line_thickness   => 2,
    extended_legend  => 1,
    title            => "Network Interface eth0",
    vertical_label   => "Bytes/Faults",
    width            => 800,
    height           => 500,
    interlaced       => "", # If images are interlaced they become visible to browsers more quickly
  );

  printf("Created %s\n", join(", ", map { $rtn{$_}->[0] } keys %rtn));

  # Return information about an RRD file
  my $info = $rrd->info($rrdfile); # This method will return a complex data structure containing details about the RRD file, including RRA and data source information.
  print Data::Dumper::Dumper($info);

  my @sources = $rrd->sources($rrdfile);
  my $seconds = $rrd->retention_period($rrdfile); # This method will return the maximum period of time (in seconds) that the RRD file will store data for.

  # Get unixtime of when RRD file was last updated
  $unixtime = $rrd->last($rrdfile);
  print FH "myfile.rrd was last updated at " . scalar(localtime($unixtime)) . "\n";

  # Get list of data source names from an RRD file
  my @dsnames = $rrd->sources;
  print "Available data sources: " . join(", ", @dsnames) . "\n";
  my $heartbeat_In  = $rrd->heartbeat($rrdfile, "bytesIn");
  my $heartbeat_Out = $rrd->heartbeat($rrdfile, "bytesOut");
  my $heartbeat_sec = $rrd->heartbeat($rrdfile, "faultsPerSec");  # This method will return the current heartbeat of a data source.

  printf "This is the heartbeat_in: %s\n", $heartbeat_In;
  my @rtn_In  = $rrd->heartbeat($rrdfile, "bytesIn",      10);
  my @rtn_Out = $rrd->heartbeat($rrdfile, "bytesOut",     10);
  my @rtn_sec = $rrd->heartbeat($rrdfile, "faultsPerSec", 10);    # This method will set a new heartbeat of a data source.

  close(FH);
}

Part of the output:

'myfilerrd' => {
  'last_ds' => 'U',
  'value' => undef,
  'min' => '0',
  'max' => undef,
  'minimal_heartbeat' => 120,
  'index' => 3,
  'type' => 'DERIVE',
  'unknown_sec' => 15
}

I do not understand why the value is undefined?

È stato utile?

Soluzione

After 3-4 days of testing and searching over the Internet for more information I just found the answer to my problem. RRD is a very simple to use tool but very very powerful. I would recommend anybody to use it through Perl especially with RRD::Simple module is very easy.

Answer:

I was adjusting the heart beat of my RRD to 10 sec, while my step (data collection time) is 300 by default. If the user do not specify the step "sampling frequency" by default the system will use 300. In result the graph takes 0 values so there is not output. More information and very nice analysis can be found here HeartBeat

Based on my experimentation, I found that since I am using a while loop inside the create function I have to first give the command:

my $rrd = RRD::Simple->new( file => "myfile.rrd" );

and as a second step I had to kill the process and set the step by entering the command:

my $rrd = RRD::Simple->new( 
        file => "myfile.rrd",
        step => 50 );

Based on my experimentation I found that I had to remove this block of code below had to be added to the file as a second step. First had to make the creation and then add it on my loop. This is because initially the "myfile.rrd" has to be created with all the settings, before the user start modifying them.

unless (-f "myfile.rrd") {
    $rrd->create(
        step => 50,
        bytesIn => "GAUGE",
        bytesOut => "GAUGE",
        faultsPerSec => "COUNTER"
        );
    }

Another point that worth mentioning here is that by default RRD Data Source (DS) is set to GAUGE. More information can be found here RRDtool

The Perl module can be found easily CPAN RRD::Simple which provides analysis and extra "features" that you can add to your code.

In conclusion RRD::Simple is very simple, it can be executed by copy-paste into your program. Any further modifications (e.g sample rates, Average/Max/Min values etc.) need a bit of reading upon but definitely worth the effort. Unfortunately there is not much of examples online so some testing need it to be done in order to understand what I need to modify in my code to make it work. By writing this short analysis and providing some links to read upon I hope to save someone else from spending a few days to come up with the answer to his problem.

Again I encourage anyone to try implementing RRD's is a very powerful tool to graphically view your results and store the data up to 3 years.

Altri suggerimenti

Another update that I think is useful to some people maybe. Instead of following all this process by adding and removing code in order to make the rrd file working.

After modifications and experimentation I found another solution.

use strict;
use RRD::Simple;
use RRDs;

my $rrd = RRD::Simple->new(
        file => "myfile.rrd",
        rrdtool => "/usr/local/rrdtool-1.2.11/bin/rrdtool", #optional
        tmpdir => "/var/tmp", #optional
        cf => [ qw(AVERAGE MAX) ], #optional
        default_dstype => "COUNTER", #optional
        on_missing_ds => "add", #optional
        RRDs::tune("myfile.rrd", "-i", "Source_Name:0") #optional -i or --minimum
        RRDs::tune("myfile.rrd", "-a", "Source_Name:200") #optional -a or --maximum
        );

There are several optional values that someone can use, but I recommend to use all of them so you can take full control of the program.

I am using:

default_dstype => "COUNTER", #optional

Because by default RRD's will set GAUGE as Data Source (DS). By setting the DS to COUNTER the user can set the minimum and maximum values. Short examples can be found here also RRD::Simple::Examples.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top