GrowthForecast

 view release on metacpan or  search on metacpan

lib/GrowthForecast/RRD.pm  view on Meta::CPAN

        $period_title = '8 Hours (5min avg)';
        $period_title = '8 Hours (1min avg)' if $span eq 's8h'; 
        $period = -1 * 8 * 60 * 60;
        $xgrid = 'MINUTE:30:HOUR:1:HOUR:1:0:%H:%M';
    }
    elsif ( $span eq '4h' || $span eq 's4h') {
        $period_title = '4 Hours (5min avg)';
        $period_title = '4 Hours (1min avg)' if $span eq 's4h'; 
        $period = -1 * 4 * 60 * 60;
        $xgrid = 'MINUTE:30:HOUR:1:MINUTE:30:0:%H:%M';
    }
    else {
        $period_title = 'Day (5min avg)';
        $period_title = 'Day (1min avg)' if $span eq 'sd';
        $period = -1 * 60 * 60 * 33; # 33 hours
        $xgrid = 'HOUR:1:HOUR:2:HOUR:2:0:%H';
    }

    return ( $period_title, $period, $end, $xgrid);
}


sub graph {
    my $self = shift;
    my $datas = shift;
    my @datas = ref($datas) eq 'ARRAY' ? @$datas : ($datas);
    my $args = shift;
    my ($a_gmode, $span, $from, $to, $width, $height) = map { $args->{$_} } qw/gmode t from to width height/;
    $span ||= 'd';
    $width ||= 390;
    $height ||= 110;

    my ( $period_title, $period, $end, $xgrid ) = $self->calc_period($span, $from, $to);

    if ( @datas == 1 && $a_gmode eq 'subtract' ) { $period_title = "[subtract] $period_title" } 
    my ($tmpfh, $tmpfile) = File::Temp::tempfile(UNLINK => 0, SUFFIX => ".png");
    my @opt = (
        $tmpfile,
        '-w', $width,
        '-h', $height,
        '-a', 'PNG',
        '-l', 0, #minimum
        '-u', 2, #maximum
        '-x', $args->{xgrid} ? $args->{xgrid} : $xgrid,
        '-s', $period,
        '-e', $end,
        '--slope-mode',
        '--disable-rrdtool-tag',
        '--color', 'BACK#'.uc($args->{background_color}),
        '--color', 'CANVAS#'.uc($args->{canvas_color}),
        '--color', 'FONT#'.uc($args->{font_color}),
        '--color', 'FRAME#'.uc($args->{frame_color}),
        '--color', 'AXIS#'.uc($args->{axis_color}),
        '--color', 'SHADEA#'.uc($args->{shadea_color}),
        '--color', 'SHADEB#'.uc($args->{shadeb_color}),
        '--border', $args->{border},
    );

    push @opt, '-y', $args->{ygrid} if $args->{ygrid};
    push @opt, '-t', "$period_title" if !$args->{notitle};
    push @opt, '--no-legend' if !$args->{legend};
    push @opt, '--only-graph' if $args->{graphonly};
    push @opt, '--logarithmic' if $args->{logarithmic};
    push @opt, '--font', "AXIS:8:";
    push @opt, '--font', "LEGEND:8:";
    push @opt, '-u', $args->{upper_limit} if defined $args->{upper_limit};
    push @opt, '-l', $args->{lower_limit} if defined $args->{lower_limit};
    push @opt, '-r' if $args->{rigid};

    my $i=0;
    my @defs;
    for my $data ( @datas ) {
        my $gmode = ($data->{c_gmode}) ? $data->{c_gmode} : $a_gmode;
        my $type = ($data->{c_type}) ? $data->{c_type} : ( $gmode eq 'subtract' ) ? $data->{stype} : $data->{type};
        my $gdata = ( $gmode eq 'subtract' ) ? 'sub' : 'num';
        my $llimit = ( $gmode eq 'subtract' ) ? $data->{sllimit} : $data->{llimit};
        my $ulimit = ( $gmode eq 'subtract' ) ? $data->{sulimit} : $data->{ulimit};
        my $stack = ( $data->{stack} && $i > 0 ) ? ':STACK' : '';
        my $file = $span =~ m!^s! ? $self->path_short($data) : $self->path($data);
        my $unit = $data->{unit};
        $unit =~ s!%!%%!;
        push @opt, 
            sprintf('DEF:%s%dt=%s:%s:AVERAGE', $gdata, $i, $file, $gdata),
            sprintf('CDEF:%s%d=%s%dt,%s,%s,LIMIT,%d,%s', $gdata, $i, $gdata, $i, $llimit, $ulimit, $data->{adjustval}, $data->{adjust}),
            sprintf('%s:%s%d%s:%s %s', $type, $gdata, $i, $data->{color}, $self->_escape($data->{graph_name}), $stack),
            sprintf('GPRINT:%s%d:LAST:Cur\: %%4.1lf%%s%s', $gdata, $i, $unit),
            sprintf('GPRINT:%s%d:AVERAGE:Avg\: %%4.1lf%%s%s', $gdata, $i, $unit),
            sprintf('GPRINT:%s%d:MAX:Max\: %%4.1lf%%s%s', $gdata, $i, $unit),
            sprintf('GPRINT:%s%d:MIN:Min\: %%4.1lf%%s%s\l', $gdata, $i, $unit),
            sprintf('VDEF:%s%dcur=%s%d,LAST', $gdata, $i, $gdata, $i),
            sprintf('PRINT:%s%dcur:%%.8lf',$gdata, $i),
            sprintf('VDEF:%s%davg=%s%d,AVERAGE', $gdata, $i, $gdata, $i),
            sprintf('PRINT:%s%davg:%%.8lf',$gdata, $i),
            sprintf('VDEF:%s%dmax=%s%d,MAXIMUM', $gdata, $i, $gdata, $i),
            sprintf('PRINT:%s%dmax:%%.8lf',$gdata, $i),
            sprintf('VDEF:%s%dmin=%s%d,MINIMUM', $gdata, $i, $gdata, $i),
            sprintf('PRINT:%s%dmin:%%.8lf',$gdata, $i);
        push @defs, sprintf('%s%d',$gdata, $i);
        $i++;
    }
    if ( $args->{sumup} ) {
        my @sumup = (shift @defs);
        my $unit = $datas[0]->{unit};
        $unit =~ s!%!%%!;
        push @sumup, $_, '+' for @defs;
        push @opt, 
            sprintf('CDEF:sumup=%s',join(',',@sumup)),
            sprintf('LINE0:sumup#cccccc:total'),
            sprintf('GPRINT:sumup:LAST:Cur\: %%4.1lf%%s%s', $unit),
            sprintf('GPRINT:sumup:AVERAGE:Avg\: %%4.1lf%%s%s', $unit),
            sprintf('GPRINT:sumup:MAX:Max\: %%4.1lf%%s%s', $unit),
            sprintf('GPRINT:sumup:MIN:Min\: %%4.1lf%%s%s\l', $unit),
            sprintf('VDEF:sumupcur=sumup,LAST'),
            sprintf('PRINT:sumupcur:%%.8lf'),
            sprintf('VDEF:sumupavg=sumup,AVERAGE'),
            sprintf('PRINT:sumupavg:%%.8lf'),
            sprintf('VDEF:sumupmax=sumup,MAXIMUM'),
            sprintf('PRINT:sumupmax:%%.8lf'),
            sprintf('VDEF:sumupmin=sumup,MINIMUM'),
            sprintf('PRINT:sumupmin:%%.8lf');
    }

    my %same_vrule;
    for my $vrule ($self->{data}->get_vrule($span, $period, $end, '/'.join('/',@{$datas[0]}{qw(service_name section_name graph_name)}))) {
        my $desc = "";
        if ($vrule->{description}) {
            my $k = $vrule->{color}.'/'.$vrule->{description};
            unless ($same_vrule{$k}) {
                $desc = $vrule->{description};
                $desc =~ s/:/\\:/;
            }
            $same_vrule{$k}++;
        }

        push @opt, join(":",
                        'VRULE',
                        join("", $vrule->{time}, $vrule->{color}),
                        ($args->{vrule_legend} ? $desc : ""),
                        ($vrule->{dashes} ? 'dashes='.$vrule->{dashes} : ()),
                    );
    }
    push @opt, 'COMMENT:\n';

    my @graphv;
    eval {
        @graphv = RRDs::graph(map { Encode::encode_utf8($_) } @opt);
        my $ERR=RRDs::error;
        die $ERR if $ERR;
    };
    if ( $@ ) {
        unlink($tmpfile);
        die "draw graph failed: $@";
    }

    $i=0;
    my %graph_args;
    for my $data ( @datas ) {
        my ($current,$average,$max,$min) = (
            $graphv[0]->[$i],
            $graphv[0]->[$i+1],
            $graphv[0]->[$i+2],
            $graphv[0]->[$i+3]
        );
        my $graph_path = join('/', $data->{service_name}, $data->{section_name}, $data->{graph_name});
        $graph_args{$graph_path} = [$current, $average, $max, $min];
        $i = $i + 4;
    }
    if ( $args->{sumup} ) {
        my ($current,$average,$max,$min) = (
            $graphv[0]->[$i],
            $graphv[0]->[$i+1],
            $graphv[0]->[$i+2],
            $graphv[0]->[$i+3]
        );
        $graph_args{'total'} = [$current, $average, $max, $min];
    }
    open( my $fh, '<:bytes', $tmpfile ) or die "cannot open graph tmpfile: $!";
    local $/;
    my $graph_img = <$fh>;
    unlink($tmpfile);

    die 'something wrong with image' unless $graph_img;

    return ($graph_img,\%graph_args);
}

sub export {
    my $self = shift;
    my $datas = shift;
    my @datas = ref($datas) eq 'ARRAY' ? @$datas : ($datas);
    my $args = shift;
    my ($a_gmode, $span, $from, $to, $width, $cf) = map { $args->{$_} } qw/gmode t from to width cf/;
    $span ||= 'd';
    $width ||= 390;

    my ( $period_title, $period, $end, $xgrid ) = $self->calc_period($span, $from, $to);

    my @opt = (



( run in 0.627 second using v1.01-cache-2.11-cpan-5b529ec07f3 )