RRDs::graph中关于TICK框与标签重叠的不兼容性

编程语言 2026-07-10

很多年前我写了一个监控工具,用RRD来收集数据(其实使用的是perl模块 RRDs)。当时的操作系统是SLES 10(rrdtool 1.2012和 rrdtool 1.3007)。

自从升级到SLES 15 SP6(perl-rrdtool-1.8.0-150600.1.4.x86_64)后,我发现我的TICK区块会与标签重叠。

图表底部看起来是这样的:

Screenshot showing bottom of incorrect RRD graph

TICK的作用只是对柱状图的一种“颜色图例”,用来对未显示的状态进行分类(绿色/黄色/橙色/红色)。

绘制底部那部分的相关代码看起来是这样的(来自 RRDs::graph($fname, @settings, @graph_args);@graph_args 数组):

...
51  'COMMENT:    Last\\t Minimum\\t Average\\t Maximum\\t  Sample\\n'
52  'GPRINT:S_A:LAST:  %6.2lf\\t\\g'
53  'GPRINT:V_S_I:  %6.2lf\\t\\g'
54  'GPRINT:V_S_A:  %6.2lf\\t\\g'
55  'GPRINT:V_S_X:  %6.2lf\\t\\g'
56  'LINE:S_I'
57  'AREA:S_R#F061::STACK'
58  'LINE1:S_I#F066'
59  'LINE1:S_X#F066'
60  'LINE1:S_A#F06:System  \\n'
61  'GPRINT:P_A:LAST:  %6.2lf\\t\\g'
62  'GPRINT:V_P_I:  %6.2lf\\t\\g'
63  'GPRINT:V_P_A:  %6.2lf\\t\\g'
64  'GPRINT:V_P_X:  %6.2lf\\t\\g'
65  'LINE:P_I'
66  'AREA:P_R#C601::STACK'
67  'LINE1:P_I#C606'
68  'LINE1:P_X#C606'
69  'LINE1:P_A#C60:Peer    \\n'
70  'GPRINT:C_A:LAST:  %6.2lf\\t\\g'
71  'GPRINT:V_C_I:  %6.2lf\\t\\g'
72  'GPRINT:V_C_A:  %6.2lf\\t\\g'
73  'GPRINT:V_C_X:  %6.2lf\\t\\g'
74  'LINE:C_I'
75  'AREA:C_R#3F31::STACK'
76  'LINE1:C_I#3F36'
77  'LINE1:C_X#3F36'
78  'LINE1:C_A#3F3:Clock   \\n'
79  'GPRINT:A_A:LAST:  %6.2lf\\t\\g'
80  'GPRINT:V_A_I:  %6.2lf\\t\\g'
81  'GPRINT:V_A_A:  %6.2lf\\t\\g'
82  'GPRINT:V_A_X:  %6.2lf\\t\\g'
83  'LINE:A_I'
84  'AREA:A_R#06F1::STACK'
85  'LINE1:A_I#06F6'
86  'LINE1:A_X#06F6'
87  'LINE1:A_A#06F:Total   \\n'
88  'TICK:S0X#F00C:0.06'
89  'TICK:S1X#F90C:0.06'
90  'TICK:S2X#FF0C:0.06'
91  'TICK:S3X#0C09:0.06'
92  'TICK:S0A#F00C:0.04:Failed'
93  'TICK:S1A#F90C:0.04:Bad'
94  'TICK:S2A#FF0C:0.04:Marginal'
95  'TICK:S3A#0C09:0.04:Good'
96  'TICK:S0I#F00C:0.02'
97  'TICK:S1I#F90C:0.02'
98  'TICK:S2I#FF0C:0.02'
99  'TICK:S3I#0C09:0.02'

(该命令是以某种复杂的方式组装的,因此展示那段代码只会分散注意力。因此我使用Perl调试器来提取关键设置)

下面给出一个例子,展示旧版rrdtool的图形底部是怎样的(调用它的代码并未改变):

bottom of rrdtool graph showing correct TICKs

手册仍然声称 TICK 的语法是:

TICK:vname#rrggbb[aa][:fraction[:legend]]

软件包版本

由于问题可能出在 rrdtool 之外,我将补充更多软件包版本信息:

> rpm -qa rrdtool librrd libpango\*
libpango-1_0-0-32bit-1.51.1-150600.1.3.x86_64
libpangomm-1_4-1-2.46.3-150600.1.2.x86_64
libpango-1_0-0-1.51.1-150600.1.3.x86_64
rrdtool-1.8.0-150600.1.4.x86_64

我发现Fedora 42中的 rrdtool-1.9.0-3.fc42.x86_64 也有同样的问题:

$ rpm -qa rrdtool rrd\* pango\* cairo\*
cairo-1.18.2-3.fc42.x86_64
cairo-gobject-1.18.2-3.fc42.x86_64
cairomm-1.14.5-8.fc42.x86_64
cairomm1.16-1.18.0-8.fc42.x86_64
pangomm-2.46.4-3.fc42.x86_64
pangomm2.48-2.56.1-1.fc42.x86_64
pango-1.56.4-2.fc42.x86_64
rrdtool-1.9.0-3.fc42.x86_64

简化测试用例

我设法创建了一个简化的测试用例:

首先是示例RRD数据库的转储:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE rrd SYSTEM "https://oss.oetiker.ch/rrdtool/rrdtool.dtd">
<!-- Round Robin Database Dump -->
<rrd>
        <version>0003</version>
        <step>60</step> <!-- Seconds -->
        <lastupdate>1751958726</lastupdate> <!-- 2025-07-08 09:12:06 CEST -->

        <ds>
                <name> N_SYS </name>
                <type> GAUGE </type>
                <minimal_heartbeat>105</minimal_heartbeat>
                <min>0.0000000000e+00</min>
                <max>NaN</max>

                <!-- PDP Status -->
                <last_ds>1</last_ds>
                <value>6.0000000000e+00</value>
                <unknown_sec> 0 </unknown_sec>
        </ds>

        <ds>
                <name> N_PEER </name>
                <type> GAUGE </type>
                <minimal_heartbeat>105</minimal_heartbeat>
                <min>0.0000000000e+00</min>
                <max>NaN</max>

                <!-- PDP Status -->
                <last_ds>0.7</last_ds>
                <value>4.2000000000e+00</value>
                <unknown_sec> 0 </unknown_sec>
        </ds>

        <ds>
                <name> N_ALL </name>
                <type> GAUGE </type>
                <minimal_heartbeat>105</minimal_heartbeat>
                <min>0.0000000000e+00</min>
                <max>NaN</max>

                <!-- PDP Status -->
                <last_ds>0.769230769230769</last_ds>
                <value>4.6153846154e+00</value>
                <unknown_sec> 0 </unknown_sec>
        </ds>

        <!-- Round Robin Archives -->
        <rra>
                <cf>AVERAGE</cf>
                <pdp_per_row>1</pdp_per_row> <!-- 60 seconds -->

                <params>
                <xff>9.0000000000e-01</xff>
                </params>
                <cdp_prep>
                        <ds>
                        <primary_value>1.0000000000e+00</primary_value>
                        <secondary_value>1.0000000000e+00</secondary_value>
                        <value>NaN</value>
                        <unknown_datapoints>0</unknown_datapoints>
                        </ds>
                        <ds>
                        <primary_value>7.0000000000e-01</primary_value>
                        <secondary_value>6.0000000000e-01</secondary_value>
                        <value>NaN</value>
                        <unknown_datapoints>0</unknown_datapoints>
                        </ds>
                        <ds>
                        <primary_value>7.6923076923e-01</primary_value>
                        <secondary_value>6.9230769231e-01</secondary_value>
                        <value>NaN</value>
                        <unknown_datapoints>0</unknown_datapoints>
                        </ds>
                </cdp_prep>
                <database>
                        <!-- 2025-07-08 09:12:00 CEST / 1751958720 --> <row><v>1.0000000000e+00</v><v>8.0000000000e-01</v><v>8.4615384615e-01</v></row>
                </database>
        </rra>
</rrd>

用来创建 demo.png 的命令:

$ rrdtool restore /tmp/demo.dump /tmp/demo.rrd
$ rrdtool graph /tmp/demo.png 'DEF:S_A=/tmp/demo.rrd:N_SYS:AVERAGE' 'CDEF:S1A=S_A,0.30,GT,S_A,UNKN,IF' 'TICK:S1A#F90C:0.04:Bad'

这会得到下图:

Output of test case

解决方案

SUSE的一个支持案例也不能真正解释发生了什么,但升级到SP7(rrdtool-1.8.0-150600.1.4.x86_64)后,TICK标记又看起来正常了。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章