Stats truncated during parsing of showServers()
threatstop opened this issue · comments
Hi Denis,
We found the following issue in the module: the output of showServers() can end up truncated, as the length of the data can exceed the length of the header, which is used to split each row in https://github.com/dmachard/python-dnsdist-console/blob/master/dnsdist_console/statistics.py#L39
For example, if a dnsdist server has served 12345678 queries, the module will truncate the leading 1 and return 2345678
DNSDist console
> showServers()
showServers()
# Name Address State Qps Qlim Ord Wt Queries Drops Drate Lat Outstanding Pools
0 127.0.0.1:5353 127.0.0.1:5353 down 0.0 0 1 1 12345678 0 0.0 0.0 0 a pool with spaces
All 0.0 0 0
Python side
console = Console(host="127.0.0.1", port=5199, key="redacted")
stats = Statistics(console)
print(stats['backends'][0])
{'#': '0', 'Name': '127.0.0.1:5353', 'Address': '127.0.0.1:5353', 'State': 'down', 'Qps': '0.0', 'Qlim': '0', 'Ord': '1', 'Wt': '1', 'Queries': '2345678', 'Drops': '0', 'Drate': '0.0', 'Lat': '0.0', 'Outstanding': '0', 'Pools': 'a pool with spaces'}
Here is a possible fix, although it only works as long as pools remains the only field with spaces.
*** statistics.py.orig 2023-01-31 17:02:15.650733020 +0000
--- statistics.py 2023-01-31 17:42:18.499797146 +0000
***************
*** 36,51 ****
svr_hdr = o_list[0]
svr_stats = []
for s in o_list[1:]:
! svr = {}
! i = 0
! j = 0
! for i in range(len(svr_hdr)):
! if i == len(svr_hdr)-1:
! svr[svr_hdr[j:].strip().lower()] = s[j:].strip()
! if svr_hdr[i].isupper():
! svr[svr_hdr[j:i].strip().lower()] = s[j:i].strip()
! j = i
svr_stats.append(svr)
self.__stats__["backends"] = svr_stats
--- 36,44 ----
svr_hdr = o_list[0]
svr_stats = []
+ headers = re.sub('\s+', ' ', svr_hdr).split(' ')
for s in o_list[1:]:
! svr = dict(zip(headers, re.sub('\s+', ' ', s).split(' ', len(headers) - 1)))
svr_stats.append(svr)
self.__stats__["backends"] = svr_stats
Thank to report this issue, can you push your fix through a pull request ?
The name field can also contains spaces; perhaps we can ignore this field and remove-it during parsing ?
The name can be extracted with getServer(<server_id>):getName()
Adjusting the fix to accounts for spaces in server names. Will submit PR once addressed.
This is quite difficult to parse, given that the server name can also get truncated in the output of showServers() (20 char limit) but isn't in the output of getServer(<server_id>). Sending PR, as ugly as it is.
Not perfect but better than the initial code, thanks again for the PR.
I also added some tests regarding this parsing
Thank you for the quick response