• RRDtool绘制lvs连接数图形


    需求:用RRDtool绘制lvs的连接数图形

    RRDtool是一个强大的绘图工具,作者是Tobias Oetiker。

    RRD全称Round Robin Database,轮转数据库,也是一个时间序列数据库。数据库文件以rrd结尾,RRD在创建好后大小是固定的,超过容量之后旧数据会被新采集的数据覆盖。

    看看官方说明:

    RRDtool is designed to store time series of data. With every data update, an associated time stamp is stored. Time is always expressed in seconds passed since epoch (01-01-1970). 
    
    It comes with a command set to carry out various operations on RRD databases. This command set can be accessed from the command line, as well as from Shell or Perl scripts. The scripts act as wrappers for accessing data stored in RRDtool databases.
    

    这个数据库里存的数据不一定是直接获取到的源数据,源数据获取到后是存放在一个数据库的一个临时区域,这些源数据叫做PDP,RRDtool把这些PDP数据作为数据源通过分组、利用聚合函数计算后把结果存入RRD数据库,这些数据叫做CDP,CDP才是RRDTool绘图时真正打交道的数据。在从源数据中取数据做聚合计算时会有一个挑选数据的基准,也就是说是以几个源数据为一组做聚合,根据现实需求的不同,对源数据可以很灵活的选择不同的时间段提取源数据,再聚合提取不同的聚合值,这样就产生不同组别的CDP数据,这些有以相同时间段挑选源数据及相同聚合函数计算的结果组成的数据就叫RRA,所以根据挑选源数据的标准及采用的聚合函数的不同,RRA可以有多个。

    RRDtool绘图流程:

    创建RRD数据库 -> 获取数据 -> updatev将数据存入数据库 -> 设置计划任务每五分钟更新一次数据 -> cgi文件画图和展示

    1、创建RRD数据库

    rrdcreate - Set up a new Round Robin Database
    
    rrdtool create filename [--start|-b start time] [--step|-s step] [DS:ds-name:DST:dst arguments] [RRA:CF:cf arguments]
    
    DS:variable_name:DST:heartbeat:min:max
    RRA:CF:xff:step:rows
    
    DS:ds-name:COMPUTE:rpn-expression
    
    filename:表示RRD数据库文件的名称,默认以.rrd结尾。
    --start|-b:给出第一个记录的起始时间。
    --step|-s:定义rrd接收数据的时间间隔,默认是5分钟。我们的脚本也应该是每5分钟运行一次,这个时间间隔接收到的数据叫做PDP。
    DS:用于定义Data Soure数据源。也就是用于存放脚本的结果的变量名(DSN)。可以定义多个。
    DST:就是Data Source Type的意思。有 COUNTER、GAUGE、DERIVE、ABSOLUTE、COMPUTE 5种。
      GAUGE:表示rrd接收到什么数据库中就保存什么值,不作任何计算,直接存源数据;
      COUNTER:保存的是相对值,但是这种类型只能记录递增的数据。示例:DS:eth0_bytes:COUNTER:600:0:U
      DERIVE:也是保存的相对值,不过这种类型递增递减都可以记录。
      ABSOLUTE:每次都假定前一个interval的值是0,再计算平均值。
      COMPUTE:它的定义是一个表达式,引用其它DS计算出某个值。示例:DS:eth0_bits:COMPUTE:bytes,8,*
    
    PDP :Primary Data Point。主数据节点,每个时间点产生的数据,即是搜集的源数据,没有做聚合的数据。
    CF:Consolidation Function。合并或聚合函数。有 AVERAGE、MAX、MIN、LAST 四种,分别表示对多个PDP进行取平均、取最大值、取最小值、取当前值四种类型。用在update数据时。
    CDP:Consolidation Data Point。RRDtool使用多个PDP合并为(计算出)一个CDP。也就是通过上面的CF计算后的结果。这个值就是存入RRA的数据,绘图时使用的也是这些数据。
    RRA:Round Robin Archive。用于指定数据如何存放。我们可以把一个RRA看成一个表,各保存不同interval的统计结果。即以相同的分组、聚合函数计算后的CDP数据组就组成了RRA。
    
    heartbeat:心跳,表示rrdtool如果在设定心跳的时间内没有收到数据,那就把这个数据定为"UNKNOWN"。
    min:max:表示rrdtool所能存储数据的最小值与最大值,如果不作限制可以用U代替。
    
    xff:表示一个比例值,即在聚合计算中挑选出的PDP中有多大比例是UNKNOWN,如果小于定义的比例,则认为数据是可用的。如果大于等于定义的比例,则计算出的CDP也为UNKNOWN。这个比例通常定义为0.5。比如,如果24个PDP中有12个或者超过12个PDP的值是UNKNOWN,则CPD计算的结果为UNKNOWN。如果是11个PDP的值为UNKNOWN,则该CDP的值等于剩下13个PDP的聚合结果。
    step:定义此聚合计算是对多少个连续的PDP进行的。
    rows:定义保存数据的行数,即个数。
    
    --resolution|-r:解析度。这是一个时间跨度,是每个CDP所代表的时间范围,或者说RRA中每个CDP之间的时间间隔。resolution=create数据库时定义的一个PDP的间隔时间(--step)*RRA中定义的step(即当前CDP是对多少个连续的PDP聚合计算的)。
    
    # vim graphics.sh
    
    rrdtool create LVS117_80.rrd 
    --start `date +%s` 
    --step 300 
    DS:lvs_active:GAUGE:600:U:U 
    DS:lvs_inactive:GAUGE:600:U:U 
    RRA:AVERAGE:0.5:1:105120 
    RRA:AVERAGE:0.5:24:21900
    
    # ./graphics.sh
    # rrdtool info LVS117_80.rrd
    filename = "LVS117_80.rrd"
    rrd_version = "0003"
    step = 300
    last_update = 1505098803
    header_size = 1184
    ds[lvs_active].index = 0
    ds[lvs_active].type = "GAUGE"
    ds[lvs_active].minimal_heartbeat = 600
    ds[lvs_active].min = NaN
    ds[lvs_active].max = NaN
    ds[lvs_active].last_ds = "177894"
    ds[lvs_active].value = 5.3368200000e+05
    ds[lvs_active].unknown_sec = 0
    ds[lvs_inactive].index = 1
    ds[lvs_inactive].type = "GAUGE"
    ds[lvs_inactive].minimal_heartbeat = 600
    ds[lvs_inactive].min = NaN
    ds[lvs_inactive].max = NaN
    ds[lvs_inactive].last_ds = "39644"
    ds[lvs_inactive].value = 1.1893200000e+05
    ds[lvs_inactive].unknown_sec = 0
    rra[0].cf = "AVERAGE"
    rra[0].rows = 105120
    rra[0].cur_row = 82956
    rra[0].pdp_per_row = 1
    rra[0].xff = 5.0000000000e-01
    rra[0].cdp_prep[0].value = NaN
    rra[0].cdp_prep[0].unknown_datapoints = 0
    rra[0].cdp_prep[1].value = NaN
    rra[0].cdp_prep[1].unknown_datapoints = 0
    rra[1].cf = "AVERAGE"
    rra[1].rows = 21900
    rra[1].cur_row = 795
    rra[1].pdp_per_row = 24
    rra[1].xff = 5.0000000000e-01
    rra[1].cdp_prep[0].value = 1.4519434767e+06
    rra[1].cdp_prep[0].unknown_datapoints = 4
    rra[1].cdp_prep[1].value = 3.1224582000e+05
    rra[1].cdp_prep[1].unknown_datapoints = 4
    

    2、采集数据

    RRDtool自身不带数据采集功能,所以这里并没有相应的子命令,需要自己用SHELL脚本或SNMP等工具来采集。

    # vim lvs.sh
    #!/bin/bash
    
    vip=122.14.206.117
    lvs_active=$(ssh $vip ipvsadm -ln | sed -n '19,24p' | awk 'BEGIN{sum=0} {sum+=$5} END{print sum}')
    lvs_inactive=$(ssh $vip ipvsadm -ln | sed -n '19,24p' | awk 'BEGIN{sum=0} {sum+=$6} END{print sum}') 
    echo $lvs_active
    echo $lvs_inactive
    

    3、将数据存入数据库

    rrdupdate - Store a new set of values into the RRD
    
    rrdtool {update|updatev} filename [--template|-t ds-name[:ds-name]...] N|timestamp:value[:value...] at-timestamp@value[:value...] [timestamp:value[:value...] ...]
    
    N|timestamp:value[:value...]
    
    filename:数据库文件的名称。
    N表示now的意思,会被RRDtool替换为当前时间的timestamp,也就是'date +%s'的结果。
    timestamp比较灵活,可以是数字形式,也可以是AT-风格的时间(参考at命令的manual),有点类似于自然语言的风格。例如now、yesterday、now-1hour、now+5min都是AT风格的时间。
    value可以有多个,当create数据库时定义了多个ds时value就会有多个,这里value的顺序要和create数据库时定义的ds的顺序相同,或者是与"[--template|-t ds-name[:ds-name]...]"重新定义的顺序相同。
    
    rrdtool updatev /minirrd/projects/lvs117_80/LVS117_80.rrd $(date +%s):$lvs_active:$lvs_inactive
    

    命令行测试

    # vip=122.14.206.117
    # rrdtool updatev LVS117_80.rrd $(date +%s):$(ssh $vip ipvsadm -ln | sed -n '19,24p' | awk 'BEGIN{sum=0} {sum+=$5} END{print sum}'):$(ssh $vip ipvsadm -ln | sed -n '19,24p' | awk 'BEGIN{sum=0} {sum+=$6} END{print sum}')
    return_value = 0
    [1505100300]RRA[AVERAGE][1]DS[lvs_active] = 1.8115796333e+05
    [1505100300]RRA[AVERAGE][1]DS[lvs_inactive] = 4.0723040000e+04
    

    return_value返回值为0表示成功,-1则表示失败。

    4、将采集数据和存数据放入同一个脚本

    # cat lvs.sh
    #!/bin/bash
    
    #获取数据
    vip=122.14.206.117
    lvs_active=$(ssh $vip ipvsadm -ln | sed -n '19,24p' | awk 'BEGIN{sum=0} {sum+=$5} END{print sum}')
    lvs_inactive=$(ssh $vip ipvsadm -ln | sed -n '19,24p' | awk 'BEGIN{sum=0} {sum+=$6} END{print sum}')
    echo $lvs_active
    echo $lvs_inactive
    
    #将数据存入数据库
    echo "$(date +%s):$lvs_active:$lvs_inactive" >> update.log
    rrdtool updatev /minirrd/projects/lvs117_80/LVS117_80.rrd $(date +%s):$lvs_active:$lvs_inactive
    

    5、把脚本放入crontab中,每五分钟执行一次。

    # crontab -e
    */5 * * * * /minirrd/projects/lvs117_80/lvs.sh >> /minirrd/projects/lvs117_80/lvs.sh.out 2>&1
    

    6、有数据了,接下来就是画图了

    rrdgraph - Round Robin Database tool graphing functions
    
    rdtool graph|graphv filename [option] [data definition ...] [data calculation ...] [variable definition ...] [graph element ...] [print element ...]
    
    filename:是你想要生成的图片文件的名称,默认是png格式。你可以通过选项修改图片的类型,可以有PNG、SVG、EPS、PDF四种。
    
    data definiton
    DEF:<vname>=<rrdfile>:<ds-name>:<CF>[:step=<step>][:start=<time>][:end=<time>][:reduce=<CF>]
    
    DEF:Definition,定义的意思。DEF就是告诉RRDtool从哪个RRD中取出指定DS的某个类型的统计值,并把这些值放入到一个自定义的变量<vname>中。
    vname:一个自定义的变量名。
    rrdfile:rrd文件的路径。
    ds-name:创建rrd数据库时定义的DS名称。
    
    variable definition
    VDEF:vname=RPN expression 
    
    VDEF:Variable Definition,变量定义的意思。这个变量专门存放某个DS某种类型的值,例如lvs_active的最大值、lvs_active的当前值等。
    
    data calculation
    CDEF:vname=RPN expression
    
    CDEF:Calculation Define,计算定义的意思。CDEF支持很多数学运算,甚至还支持简单的逻辑运算if-then-else,不过这一切都需要熟悉RPN(反波兰表达式)的语法。
    

    RRDtool支持5种画图类型,分别是:AREA、LINE1、LINE2、LINE3、STACK

    • AREA:表示区域图或者火焰图。
    • LINE:表示线形图,LINE1|2|3表示线条粗细。
    • STACK:表示叠加图,在前一个对象的基础上画图。

    绘制线形图格式

    LINE[width]:value[#color][:[legend][:STACK][:skipscale][:dashes[=on_s[,off_s[,on_s,off_s]...]][:dash-offset=offset]]]
    
    LINE[width]:表示线条粗细。
    value:表示在DEF中定义的vname。
    #color:定义线条颜色,不定义颜色时线条不可见。
    legend:表示显示绘制线条的图例信息。
    

    OPTIONS:

    a、Time range:用于控制图表的X轴显示的起始/结束时间,也包括从RRA中提取指定时间的数据。

    [-s|--start time] [-e|--end time] [-S|--step seconds]
    如果没有指定–-end ,则默认为now;如果没有指定–-start,则默认为1天前。如果两者都没有指定,则图表默认显示从当前算起1天内的数据。
    

    b、Labels:用于控制X/Y轴的说明文字。

    [-t|--title string] [-v|--vertical-label string]
    -t 是用于图表上方的标题
    -v 是用于Y轴的说明文字
    

    c、Size:用于控制图片的大小。

    [-w|--width pixels] [-h|--height pixels] [-D|--full-size-mode]
    这里说图表大小而不是图片大小,是因为–w,-h控制的是X/Y轴共同围起来的那部分大小,而不是整个图片的大小。
    [-D|--full-size-mode]:表示自动缩放至全屏大小。
    

    d、Limits:用于控制Y轴的上下限。

    [-u|--upper-limit value] [-l|--lower-limit value] [-r|--rigid]
    默认情况下,RRDtool会自动调整Y轴的数值(及自动缩放),来配合当前的数值大小。如果想禁止该特性,可以通过--upper-limit和--lower-limit来做限制,表示Y轴显示的值从多少到多少。如果没有指定--rigid,则在图表的上下边界处还是会有一些延伸,但如果指定了--rigid ,则严格按照--upper-limit和--lower-limit绘制。
    在使用–lower-limit时要注意,如果数据中有负数,如果--lower-limit为0,则负数部分不会显示。
    
    [-u|--upper-limit value]:指定Y轴上限。
    [-l|--lower-limit value]:指定Y轴下限。
    [-r|--rigid]:严格限制最大和最小值,不再自动缩放。
    [-A|--alt-autoscale]:即使指定好Y轴的上下限后依然可缩放,但不能超过上下限值。
    

    e、Grid:用于控制X/Y轴的刻度如何显示。

    [-x|--x-grid GTM:GST:MTM:MST:LTM:LST:LPR:LFM] 
    [-x|--x-grid none]
    
    [-y|--y-grid grid step:label factor] 
    [-y|--y-grid none]
    
    [-Y|--alt-y-grid] 
    [-X|--units-exponent value]
    
    [-N|--no-gridfit]:不显示网格线
    

    在垂直的线中,红色的线称为Major Grid(主要网格线),灰色的线称为Base Grid(次要网格线)。
    去掉X/Y轴的刻度:--x-grid none 和 --y-grid none

    GTM:GST:控制次要格网线的位置。GTM是一个时间单位,可以是SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、YEAR。GST则是一个数字,控制每隔多长时间放置一根次要格线。例如我们要画一个1天的图表,决定每15分钟一根次要网格线,则格式为 MINUTE:15
    
    MTM:MST:控制主要网格线的位置。MTM同样是时间单位,MST是一个数字。接上面的例子,决定一个小时1根主要网格线。则格式为 HOUR:1 
    
    LTM:LST:控制每隔多长时间输出一个label。决定为1小时1个label。则格式为 HOUR:1。
    
    LPR:LFM:LTM:LST只是决定了label的显示位置了,没有指定要显示什么内容。LPR指的是如何放置label。如果LPR为0,则数字对齐格线(适用于显示时间)。如果不为0,则会做一些偏移(适用于显示星期几、月份等)。至于LFM 则需要熟悉一下 date 命令的参数,常用的有 %a(星期几)、%b(月份)、%d(天)、%H(小时)、%M(分)、%Y(年)。我们决定显示小时和分,所以用 %H%M 综合起来,X轴的刻度定义就是 –-x-grid MINUTE:15:HOUR:1:HOUR:1:0:'%H:%M' 最好把 %H:%M 括起来。
    
    建议MST是GST的2-6倍,MST和LST相同。这样画出来的图比较美观一些。
    
    grid step:用于控制Y轴每隔多少显示一根水平线。
    label factor:默认为1,也就是在每根水平线的高度那里显示一个值。
    
    Y轴还有一个很方便的选项就是 –Y ,它可以最大限度的优化Y轴的刻度,建议每次绘图都加上去。
    Y轴另外一个有用的选项就是–X(虽然选项名是-X,但确实是用来设置Y轴刻度值的)。RRDtool自动对Y轴的值进行调整,以k为单位显示。但如果你不想以k显示,而是想固定以某个单位来显示(M,b)该怎么办呢?这就要用到 –X 选项了。-X后面跟一个参数,参数值的范围是-18、-15、-12、-9、-6、-3、0、3、6、9、12、15、18。0表示以原值显示,3表示数值除以1000,也就是以k为单位显示,6就是以M显示,9就是以G显示。如果你给出1或者2,RRDtool也可以接受,但会被―静悄悄地改为0。
    

    f、Miscellaneous:其他选项。例如显示中文、水印效果等等。

    [-n|--font FONTTAG:size:[font]] 
    [-g|--no-legend] 
    [-b|--base value]
    
    -n|--font:显示中文,中文字体不宜小于7 ,否则看不清楚。确定你要修改的是图表的那个部分。有 DEFAULT(全部),TITLE(标题)、AXIS(X轴字体)、UNIT(Y轴说明文字字体)、LEGEND(图例字体)几种。
    -g|--no-legend:用于取消图表下方的图例,不过不建议这么做。
    -b|--base value:默认1k=1000,使用–b可以进行调整,例如 –b 1024。
    
    -n TITLE:12: simhei.ttf       #修改标题字体
    -n AXIS:8: simhei.ttf         #修改X轴数据字体,如01 02 03 04...
    -n LEGEND:10: simhei.ttf      #修改数字报表字体,如最大、最小、平均值及其它
    -n UNIT:8: simhei.ttf         #修改Y轴说明文字字体,如"流量"
    -n WATERMARK:8: simhei.ttf    #数据区右侧字体,如"RRDTOOL-TOBIOETIKER"
    

    g、Report:数字报表。

    GPRINT:就是在图表的下方输出最大值、最小值、平均值这些东东。GPRINT的格式是GPRINT:vname:CF:format。由于format部分太多参数了,我这里就用最常用的那个:%x.ylf。
    COMMENT:就是用来输出一些字符串,例如报表的表头。COMMENT的格式是COMMENT:"text"。要注意 COMMENT 默认是不输出换行的,如果要输出换行,必须用 "
    "。
    

    h、特殊功能

    VRULE:time#color[:legend] 
    HRULE:value#color[:legend] 
    SHIFT:vname:offset
    

    VRULE:绘制垂直线。比如在当前时间画一条竖线。
    HRULE:绘制水平线。比如画一条水平线表示报警阈值。HRULE:100000#ff0000:"报警值"。
    SHIFT:可以把曲线/方块沿着X轴移动(左右都可以),达到垂直比较同期数据的目的。

    例如,使用SHIFT绘制连续三天的垂直数据:

    # rrdtool graph 3.png  
    > DEF:value1=eth0.rrd:eth0_in:AVERAGE:end=now:start=now-1d     # 1天前 
    > DEF:value2=eth0.rrd:eth0_in:AVERAGE:end=now-1d:start=now-2d  # 2天前 
    > DEF:value3=eth0.rrd:eth0_in:AVERAGE:end=now-2d:start=now-3d  # 3天前 
    > LINE1:value1#00ff00:"1 day ago"  
    > SHIFT:value2:86400 LINE1:value2#ff0000:"2 days ago"      # 把曲线向右移动1天 
    > SHIFT:value3:172800 LINE1:value3#000000:"3 days ago"     # 把曲线向右移动2天
    > -Y –w 600 475x168
    

    回到需求上来,这里使用HTML+cgi的方式来绘制和展示图形,代码如下:

    # vim /var/www/metrics/all-dev.cgi
    <tr>
    
    <!-- lvs-117:80-active -->
    <td>
    <RRD::SETVAR aggr1 "lvs_active">
    <RRD::SETVAR aggr2 "lvs_inactive">
    <RRD::GRAPH img_all_dev/<RRD::GETVAR aggr1>.png
    -t "LVS-117:80 Connections Stats"
    -v "Sum of all Real Servers"
    -Y -X 3
    --x-grid HOUR:1:HOUR:6:HOUR:6:0:'%a:%H'
    --imginfo '<IMG SRC=img_all_dev/%s WIDTH=%lu HEIGHT=%lu >'
    --lower-limit=0 --upper-limit=900000 --rigid
    -w <RRD::GETVAR imagew1> 
    -h <RRD::GETVAR imageh1>
    --start=<RRD::GETVAR start1>
    --end=<RRD::GETVAR end1>
    --step <RRD::GETVAR step1>
    
    DEF:value_active=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr1>:AVERAGE
    DEF:value_inactive=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr2>:AVERAGE
    
    DEF:active_tp1=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr1>:AVERAGE:start=<RRD::GETVAR tp1_start>:end=<RRD::GETVAR tp1_end>
    SHIFT:active_tp1:<RRD::GETVAR tp1_shift>
    
    DEF:active_tp2=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr1>:AVERAGE:start=<RRD::GETVAR tp2_start>:end=<RRD::GETVAR tp2_end>
    SHIFT:active_tp2:<RRD::GETVAR tp2_shift>
    
    DEF:active_tp3=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr1>:AVERAGE:start=<RRD::GETVAR tp3_start>:end=<RRD::GETVAR tp3_end>
    SHIFT:active_tp3:<RRD::GETVAR tp3_shift>
    
    DEF:active_tp4=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr1>:AVERAGE:start=<RRD::GETVAR tp4_start>:end=<RRD::GETVAR tp4_end>
    SHIFT:active_tp4:<RRD::GETVAR tp4_shift>
    
    DEF:active_tp5=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr1>:AVERAGE:start=<RRD::GETVAR tp5_start>:end=<RRD::GETVAR tp5_end>
    SHIFT:active_tp5:<RRD::GETVAR tp5_shift>
    
    DEF:inactive_tp1=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr2>:AVERAGE:start=<RRD::GETVAR tp1_start>:end=<RRD::GETVAR tp1_end>
    SHIFT:inactive_tp1:<RRD::GETVAR tp1_shift>
    
    DEF:inactive_tp2=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr2>:AVERAGE:start=<RRD::GETVAR tp2_start>:end=<RRD::GETVAR tp2_end>
    SHIFT:inactive_tp2:<RRD::GETVAR tp2_shift>
    
    DEF:inactive_tp3=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr2>:AVERAGE:start=<RRD::GETVAR tp3_start>:end=<RRD::GETVAR tp3_end>
    SHIFT:inactive_tp3:<RRD::GETVAR tp3_shift>
    
    DEF:inactive_tp4=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr2>:AVERAGE:start=<RRD::GETVAR tp4_start>:end=<RRD::GETVAR tp4_end>
    SHIFT:inactive_tp4:<RRD::GETVAR tp4_shift>
    
    DEF:inactive_tp5=/minirrd/projects/lvs117_80/LVS117_80.rrd:<RRD::GETVAR aggr2>:AVERAGE:start=<RRD::GETVAR tp5_start>:end=<RRD::GETVAR tp5_end>
    SHIFT:inactive_tp5:<RRD::GETVAR tp5_shift>
    
    CDEF:tpX_active_avg=active_tp1,active_tp2,active_tp3,active_tp4,active_tp5,+,+,+,+,5,/
    CDEF:tpX_active_min=active_tp1,active_tp2,active_tp3,active_tp4,active_tp5,MIN,MIN,MIN,MIN
    CDEF:tpX_active_max=active_tp1,active_tp2,active_tp3,active_tp4,active_tp5,MAX,MAX,MAX,MAX
    CDEF:tpX_active_width=tpX_active_max,tpX_active_min,-
    
    CDEF:tpX_inactive_avg=inactive_tp1,inactive_tp2,inactive_tp3,inactive_tp4,inactive_tp5,+,+,+,+,5,/
    CDEF:tpX_inactive_min=inactive_tp1,inactive_tp2,inactive_tp3,inactive_tp4,inactive_tp5,MIN,MIN,MIN,MIN
    CDEF:tpX_inactive_max=inactive_tp1,inactive_tp2,inactive_tp3,inactive_tp4,inactive_tp5,MAX,MAX,MAX,MAX
    CDEF:tpX_inactive_width=tpX_inactive_max,tpX_inactive_min,-
    
    VDEF:active_last=value_active,LAST
    VDEF:active_max=value_active,MAXIMUM
    VDEF:active_min=value_active,MINIMUM
    VDEF:active_avg=value_active,AVERAGE
    
    VDEF:inactive_last=value_inactive,LAST
    VDEF:inactive_max=value_inactive,MAXIMUM
    VDEF:inactive_min=value_inactive,MINIMUM
    VDEF:inactive_avg=value_inactive,AVERAGE
    
    VRULE:<RRD::TIME::STRFTIME START now now "%s">#000000
    
    AREA:tpX_active_min#ffffff
    STACK:tpX_active_width#FA8072:"Last 5days of Active"
    LINE1:tpX_active_avg#FF6A6A:"Avg.last 5days of Active"
    LINE2:active_tp1#FF7F24:"Yesterday of Active"
    STACK:inactive_tp1#20B2AA:"Yesterday of Inactive"
    LINE2:value_active#dc143c:"Current of Active:"
    GPRINT:active_last:"%6.0lf l"
    STACK:value_inactive#228B22:"Current of Inactive:"
    GPRINT:inactive_last:"%6.0lf l"
    COMMENT:"Max of Active:"
    GPRINT:active_max:"%6.0lf "
    COMMENT:"Avg of Active:"
    GPRINT:active_avg:"%6.0lf l"
    COMMENT:"
    "
    COMMENT:"Max of Inctive:"
    GPRINT:inactive_max:"%6.0lf "
    COMMENT:"Avg of Inctive:"
    GPRINT:inactive_avg:"%6.0lf l"
    >
    </td>
    
    </tr>
    

    效果如下图,这里本来绘制了5天前的数据,但是由于时间没到,只显示了两天的数据:

  • 相关阅读:
    Spring中的@Transactional以及事务的详细介绍
    Shiro缓存使用Redis、Ehcache、自带的MpCache实现的三种方式实例
    使用shiro缓存用户身份信息的时候报:java.io.NotSerializableException: org.apache.shiro.util.SimpleByteSource
    rocketmq 延时消息
    用区块链技术做一个 不可被修改的 恋爱记录 app 我叫<<誓言>>
    java 调用区块链 发布和调用智能合约
    centos 以太坊多节点私链搭建
    数据库的死锁原因 和 处理办法
    聚簇索引
    Java 容易疑惑的一些杂记录
  • 原文地址:https://www.cnblogs.com/keithtt/p/7505109.html
Copyright © 2020-2023  润新知