Perl RRD::Simple без отображения данных

Я новичок в Perl, а также RRD.

Я попытался реализовать простой пример, и хотя кажется, что он работает правильно, вывод не отображается. Снимки выводятся нормально, но на графиках нет данных.

Я следил за документацией CPAN для реализации RRD::Simple и теоретически я что-то делаю не так. Я пытался отладить код, и вроде все в порядке, но когда дело доходит до печати графиков, данных нет.

#!/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);
}

Часть вывода:

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

Я не понимаю, почему значение не определено?


person Thanos    schedule 30.11.2013    source источник


Ответы (2)


После 3-4 дней тестирования и поиска в Интернете дополнительной информации я нашел ответ на свою проблему. RRD — очень простой в использовании инструмент, но очень мощный. Я бы порекомендовал всем использовать его через Perl, особенно с модулем RRD::Simple, который очень прост.

Отвечать:

Я настроил частоту сердечных сокращений моего RRD на 10 секунд, а мой шаг (время сбора данных) по умолчанию равен 300. Если пользователь не укажет шаг «частота дискретизации» по умолчанию, система будет использовать 300. В результате график принимает 0 значений, поэтому не выводится. Дополнительную информацию и очень подробный анализ можно найти здесь HeartBeat.

Основываясь на своих экспериментах, я обнаружил, что, поскольку я использую цикл while внутри функции создания, я должен сначала дать команду:

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

и в качестве второго шага мне пришлось убить процесс и установить шаг, введя команду:

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

Основываясь на своих экспериментах, я обнаружил, что мне пришлось удалить этот блок кода ниже, чтобы добавить его в файл в качестве второго шага. Сначала нужно было создать творение, а затем добавить его в мой цикл. Это связано с тем, что сначала необходимо создать «myfile.rrd» со всеми настройками, прежде чем пользователь начнет их изменять.

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

Еще один момент, о котором стоит упомянуть, заключается в том, что по умолчанию для источника данных RRD (DS) установлено значение GAUGE. Дополнительную информацию можно найти здесь RRDtool.

Модуль Perl можно легко найти в CPAN RRD::Simple, который обеспечивает анализ и дополнительные «функции», которые вы можете добавить в свой код.

В заключение RRD::Simple очень прост, его можно выполнить путем копирования и вставки в вашу программу. Любые дальнейшие модификации (например, частоты дискретизации, средние/максимальные/минимальные значения и т. д.) требуют небольшого чтения, но определенно стоят затраченных усилий. К сожалению, в Интернете не так много примеров, поэтому необходимо провести некоторое тестирование, чтобы понять, что мне нужно изменить в моем коде, чтобы он работал. Написав этот краткий анализ и предоставив несколько ссылок для чтения, я надеюсь избавить кого-то еще от необходимости тратить несколько дней на поиск ответа на его проблему.

Опять же, я призываю всех попробовать реализовать RRD — очень мощный инструмент для графического просмотра результатов и хранения данных до 3 лет.

person Thanos    schedule 01.12.2013

Еще одно обновление, которое, я думаю, может быть полезно для некоторых людей. Вместо того, чтобы следовать всему этому процессу, добавляя и удаляя код, чтобы заставить файл rrd работать.

После модификаций и экспериментов я нашел другое решение.

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
        );

Есть несколько необязательных значений, которые кто-то может использовать, но я рекомендую использовать их все, чтобы вы могли полностью контролировать программу.

Я использую:

default_dstype => "COUNTER", #optional

Потому что по умолчанию RRD устанавливает GAUGE в качестве источника данных (DS). Установив для DS значение COUNTER, пользователь может установить минимальное и максимальное значения. Здесь также можно найти короткие примеры RRD:: Просто::Примеры.

person Thanos    schedule 01.12.2013