rrd로 트래픽수집을 하다보면 아래 그림처럼 갑자기 트래픽이 튀는 경우가 발생한다.
위와 같은 문제가 발생하면 rrd 디비를 dump -> 데이터수정 -> restore 를 해줘야 하는데
상당히 귀찮은 작업이다.
그래서 스크립트 하나 만들어 봄...
1. rrd 파일을 xml 로 dump 를 받고
2. Param 으로 받은 시간대의 데이터를 0.0000000000e+00 으로 수정
3. 수정된 xml 로 restore 를 진행한다.
tip:
dump 이후에 수집된 데이터는 누락이 되는 문제가 있어
dump 전/후 lastupdate 시간이 다를경우에 dump 후에 수집된 raw 데이터를 구하여
update를 진행합니다.
[root@new test]# /usr/local/python2.6/bin/python rrdmod.py -h
rrdmod.py [options]
Options:
-t, --time=<timestamp> time format %Y%m%d%H or %Y%m%d
-f, --file=<filename> rrd file name
코드는 아직 정리 전이라 보기에 좀 불편하겠지만 수정하여 다시 업데이트 할예정임...
import sys
import subprocess
import getopt
import datetime
import time
import re
import os
def get_rrd_lastinfo(rrd_file):
last_time, last_input, last_output = None, None, None
p = subprocess.Popen(
('rrdtool', 'lastupdate', rrd_file), stdout=subprocess.PIPE)
out, err = p.communicate()
for s in out.split("\n"):
m = re.search(r"(\d+): (\d+) (\d+)", s)
if m:
last_time, last_input, last_output = m.groups()
return last_time, last_input, last_output
def get_rrd_update_value(rrd_file, start_time, end_time, input, output):
values = []
p = subprocess.Popen(
('rrdtool', 'fetch', rrd_file, 'AVERAGE', '-s', start_time, '-e', end_time), stdout=subprocess.PIPE)
out, err = p.communicate()
for s in out.split("\n"):
m = re.search(r"(\d+): ([\.e\+\-\d]+) ([\.e\+\-\d]+)", s)
if m:
last_time, last_input, last_output = m.groups()
last_input = int(eval(last_input)*300)
last_output = int(eval(last_output)*300)
values.append((last_time,last_input, last_output))
values.reverse()
input = float(input)
output = float(output)
for n, v in enumerate(values):
input -= v[1]
output -= v[2]
v = v + ("%d" % input,)
v = v + ("%d" % output,)
values[n] = v
values.reverse()
for v in values:
print v
subprocess.Popen(
('rrdtool', 'update', rrd_file, '%s:%s:%s' % (v[0], v[3], v[4])), stdout=subprocess.PIPE).communicate()
def modrrd(mod_time, rrd_file):
"""
<!-- 2017-02-02 15:00:00 KST / 1486015200 --> <row><v>NaN</v><v>NaN</v></row>
"""
pattern = re.compile(r" %s\s?[:\d]+ \w+ / (\d+) --> <row><v>(.*)</v><v>(.*)</v></row>" % mod_time)
init_value = "0.0000000000e+00"
last_update_time = get_rrd_lastinfo(rrd_file)[0]
p1 = subprocess.Popen(
('rrdtool', 'dump', rrd_file), stdout=subprocess.PIPE)
if os.path.exists('%s.new.rrd' % rrd_file):
os.unlink('%s.new.rrd' % rrd_file)
fp = open("%s.xml" % rrd_file, "a+")
for num, line in enumerate(p1.stdout):
matching = pattern.search(line)
if matching:
if len(matching.groups()) == 3:
line = line.replace(matching.groups()[1], init_value).replace(matching.groups()[2], init_value)
fp.write(line)
fp.close()
p2 = subprocess.Popen(
('rrdtool', 'restore', "%s.xml" % rrd_file, '%s.new.rrd' % rrd_file), stdout=subprocess.PIPE)
out, err = p2.communicate()
if os.path.exists("%s.xml" % rrd_file):
os.unlink("%s.xml" % rrd_file)
_last_update_time, _last_input, _last_output = get_rrd_lastinfo(rrd_file)
if last_update_time != _last_update_time:
get_rrd_update_value(rrd_file, last_update_time, _last_update_time, _last_input, _last_output)
def usage():
print 'rrdmod.py [options]'
print 'Options:'
print '-t, --time=<timestamp> time format %Y%m%d%H or %Y%m%d'
print '-f, --file=<filename> rrd file name'
def main():
mod_time, rrd_file = None, None
try:
opts, args = getopt.getopt(sys.argv[1:],"ht:f:",["time=","file="])
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, value in opts:
if opt in ("-t", "--time"):
mod_time = value
if len(mod_time) == 10:
mod_time = datetime.datetime.strptime(mod_time, '%Y%m%d%H')
mod_time = mod_time.strftime("%Y-%m-%d %H")
elif len(mod_time) == 8:
mod_time = datetime.datetime.strptime(mod_time, '%Y%m%d')
mod_time = mod_time.strftime("%Y-%m-%d")
else:
usage()
sys.exit(2)
# make timestamp
#mod_time = time.mktime(mod_time.timetuple())
elif opt in ("-f", "--file"):
rrd_file = value
elif opt == "-h":
usage()
sys.exit()
if mod_time == None or rrd_file == None:
usage()
sys.exit()
modrrd(mod_time, rrd_file)
if __name__ == "__main__":
main()