rrdtool - 修改 HWPREDICT rra

rrdtool - amend a HWPREDICT rra

我正在使用 rrdtool 来收集和处理一些系统指标。

我一直在试验相当奇妙的 HWPREDICT 功能,它允许您进行 Holt-Winters 季节性预测以检测偏差。

但是我现在遇到了一个问题,因为当我开始时,我将 HWPREDICT 参数设置为 "season" 一天:

rrdtool create <filename> -s 300 DS:curr_sessions:GAUGE:600:0:U RRA:AVERAGE:0.5:1:2880 RRA:AVERAGE:0.5:12:2016 RRA:AVERAGE:0.5:60:2400 RRA:HWPREDICT:1440:0.1:0.0001:288

间隔 5 分钟的 288 个样本意味着一天 'season'。

我想做的是扩展它,这样我的 'seasons' 就是 2016 年的样本 - 一周。

例如

RRA:HWPREDICT:4032:0.1:0.0001:2016

但我很难确定是否有任何方法可以在不重置源数据的情况下执行此操作。我看过 rrddump,它可以让你 dump/restore。这会导出 XML 但会保留 RRA 结构。

rrdtune 可让您调整 alpha/beta/gamma 的一些参数,但不能调整季长。

并且 rrdresize 允许您修改 RRA 的长度,但不能修改季节的长度。

有没有人有好的解决方案可以让我重新创建我的 rrd 但保留其中保存的数据? (我不介意 'losing' 我的 HWPREDICT RRA 数据因为改变季节周期几乎会使它无效,但很想将我现有的数据保留在其他 RRA 中)。

加分 - 我最熟悉 perl,所以如果有人能给我一个正确方向的建议,请不要介意 fiddle 和 perl/XML。 (我可以 'fudge' 以某种方式导出 XML 只是 'feed' 它是一个带有一堆未初始化值的新 RRA 吗?)

目前的部分答案:

使用新参数创建新的 rrd 文件。包括 --start 以允许您回溯足够远的日期。 (在倾倒的 XML 中找到最低的 'timestamp')。

处理转储 XML 并提取数据。这里有一个问题 - 如果您有重叠的 RRA,rrdtool 将不接受 'clashing' 时间戳。例如,如果您有一个 MAX 和一个 AVERAGE

我选择了 MAX,因为这可能对我最有用。

我也这样做了 'in order' 因为我已经按照适当的顺序指定了我的初始 RRA(例如,首先是最小的分辨率)。这可能会以其他方式工作,但请记住,您可能会在较粗略的分辨率下得到一些不同的值 'MAX'。

#!/usr/local/bin/perl

use strict;
use warnings;

use XML::Twig;

my %update_vals;

sub parse_rra {
    my ( $twig, $rra ) = @_;

    return unless $rra->first_child_text('cf') eq 'MAX';
    my $step      = $twig->root->first_child_text('step');
    my $lastupd   = $twig->root->first_child_text('lastupdate');
    my $base_time = $lastupd - $lastupd % $step;
    my $pdp_step  = $rra->first_child_text('pdp_per_row');

    my @row_vals;
    foreach my $row ( $rra->first_child('database')->children('row') ) {
        my $val = $row->first_child_text('v');
        push( @row_vals, $val );
    }

    my $start_rra = $base_time - $#row_vals * $step * $pdp_step;
    foreach my $value (@row_vals) {
        if (   not $value eq "NaN"
            or not defined $update_vals{$start_rra} )
        {
            $update_vals{$start_rra} = $value;
            $start_rra += $step * $pdp_step;
        }
    }
}

my $target_file      = "your_rrd_dump.xml";
my $destination_file = "new.rrd";

my $twig = XML::Twig->new( 'twig_handlers' => { 'rra' => \&parse_rra } )
    ->parsefile($target_file);

foreach my $timestamp ( sort keys %update_vals ) {
    print
        `rrdtool update $destination_file $timestamp:$update_vals{$timestamp}`;
}

现在,到目前为止 - 所有这一切都是 'replay' 您可用的所有时间戳。不幸的是 - 它根本不适用于任何合并数据点(基于 RRA 配置),因为您没有足够的样本用于该分辨率(例如每天 1 个)。

因此作为第二种方法(已编辑):

  • 创建您的 'source' RRD。
  • 使用所需参数创建 'new' RRD。

使用 XML::Twig 进行处理 - 首先保留 'non HWPREDICT' 数据并删除 HWPREDICT 内容。第二个你处理并将 HWPREDICT RRAs 拼接到前一个,以创建一个新的 XML 转储......你恢复。

注意 - 如果您的数据差异很大,这可能无法正常工作。 (请注意 - HWPREDICT 重新初始化的东西可能需要一段时间才能再次 'settle down')。

#!/usr/local/bin/perl

use strict;
use warnings;

use XML::Twig;

my @cf_to_replace =
    qw ( HWPREDICT MHWPREDICT SEASONAL DEVSEASONAL DEVPREDICT FAILURES );
my %hwp_cf = map { $_ => 1 } @cf_to_replace;

my $xml_doc;

sub discard_hwp {
    my ( $twig, $rra ) = @_;
    my $CF = $rra->first_child_text('cf');
    if ( $hwp_cf{$CF} ) { $rra->delete }
}

sub splice_hwp {
    my ( $twig, $rra ) = @_;
    my $CF = $rra->first_child_text('cf');
    if ( $hwp_cf{$CF} ) {
        $rra->cut;
        $rra->paste( 'last_child', $xml_doc->root );
    }
}

my $orig_file             = 'your_xml_dump.xml';
my $newly_created_rrddump = 'new_params.xml';

$xml_doc = XML::Twig->new(
    'pretty_print'  => 'indented',
    'twig_handlers' => { 'rra' => \&discard_hwp }
)->parsefile($orig_file);

my $new = XML::Twig->new( 'twig_handlers' => { 'rra' => \&splice_hwp } )
    ->parsefile($newly_created_rrddump);

open( my $output, ">", "new.xml" ) or die $!;
print {$output} $xml_doc->sprint;
close($output);

这基本上是运行通过两个单独的'rrdtool dumps'拼接在一起的RRA。我会试一试,看看它是否真的能满足我的需要——在 Holt-Winters 函数稳定下来之前我不会知道。