mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-21 17:11:58 +00:00
b606882327
The change to tolerate either a space or no space ended up greedily consuming whitespace. Do best possible in two cases: For log, use the first line as a clue, and consistently pad or not pad according to first line. It won't catch different pad strategies, or handle first line being indented but other lines not being indented. For the textgroup variant, allow subsequent lines to revise the pad downward, and accept any whitespace, not just space.
130 lines
4.8 KiB
Python
Executable File
130 lines
4.8 KiB
Python
Executable File
#!/usr/bin/python2
|
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright 2017 Lenovo
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
# This is a utility to bring xcoll (plus enhancements) to confluent
|
|
# the core engine is textgroup.py, this simply provides a CLI to use
|
|
# generically
|
|
|
|
import optparse
|
|
import os
|
|
import re
|
|
import select
|
|
import sys
|
|
|
|
path = os.path.dirname(os.path.realpath(__file__))
|
|
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
|
|
if path.startswith('/opt'):
|
|
sys.path.append(path)
|
|
|
|
import confluent.textgroup as tg
|
|
import confluent.client
|
|
|
|
argparser = optparse.OptionParser(usage="Usage: <other command> | %prog [options]")
|
|
argparser.add_option('-a', '--abbreviate', action='store_true',
|
|
help='Attempt to use confluent server to shorten noderanges')
|
|
argparser.add_option('-b', '--base',
|
|
help='Use given node as reference for comparison when '
|
|
'using -d, instead of using the most common result')
|
|
argparser.add_option('-d', '--diff', action='store_true',
|
|
help='Show what differs between most common '
|
|
'output group and others')
|
|
argparser.add_option('-w', '--watch', action='store_true',
|
|
help='Show intermediate results while running')
|
|
argparser.add_option('-g', '--groupcount', action='store_true',
|
|
help='Show count of output groups rather than the actual output')
|
|
argparser.add_option('-s', '--skipcommon', action='store_true',
|
|
help='Do not print most common result, only non modal '
|
|
'groups, useful when combined with -d')
|
|
argparser.add_option('-c', '--count', action='store_true',
|
|
help='Also display count of nodes in a given group')
|
|
argparser.add_option('-r', '--reverse', action='store_true',
|
|
help='Reverse sort order to show biggest output group '
|
|
'last')
|
|
argparser.add_option('-l', '--log', action='store', type='string', dest='log',
|
|
help='Log each output to file, using {node} as a placeholder for node.')
|
|
(options, args) = argparser.parse_args()
|
|
if sys.stdin.isatty():
|
|
argparser.print_help()
|
|
sys.exit(1)
|
|
|
|
grouped = tg.GroupedData()
|
|
|
|
if options.abbreviate:
|
|
grouped = tg.GroupedData(confluent.client.Command())
|
|
else:
|
|
grouped = tg.GroupedData()
|
|
|
|
def print_current():
|
|
if options.diff:
|
|
grouped.print_deviants(skipmodal=options.skipcommon, count=options.count,
|
|
reverse=options.reverse, basenode=options.base)
|
|
elif options.groupcount:
|
|
grouped.generate_byoutput()
|
|
print(len(grouped.byoutput))
|
|
else:
|
|
grouped.print_all(skipmodal=options.skipcommon,
|
|
count=options.count,
|
|
reverse=options.reverse)
|
|
sys.stdout.flush()
|
|
|
|
fullline = sys.stdin.readline()
|
|
printpending = True
|
|
clearpending = False
|
|
holdoff = 0
|
|
padded = None
|
|
while fullline:
|
|
for line in fullline.split('\n'):
|
|
if not line:
|
|
continue
|
|
if ':' not in line:
|
|
line = 'UNKNOWN: ' + line
|
|
if options.log:
|
|
node, output = line.split(':', 1)
|
|
if padded is None:
|
|
if output.startswith(' '):
|
|
padded = True
|
|
else:
|
|
padded = False
|
|
if padded:
|
|
output = re.sub(r'^ ', '', output)
|
|
currlog = options.log.format(node=node, nodename=node)
|
|
with open(currlog, mode='a') as log:
|
|
log.write(output + '\n')
|
|
continue
|
|
node, output = line.split(':', 1)
|
|
grouped.add_line(node, output)
|
|
if options.watch:
|
|
if not holdoff:
|
|
holdoff = os.times()[4] + 0.250
|
|
if (holdoff < os.times()[4] or
|
|
not select.select((sys.stdin,), (), (), 0.250)[0]):
|
|
# print now, nothing pending
|
|
holdoff = 0
|
|
sys.stdout.write('\x1b[2J\x1b[;H') # clear screen
|
|
print_current()
|
|
printpending = False
|
|
clearpending = True
|
|
else:
|
|
printpending = True
|
|
fullline = sys.stdin.readline()
|
|
|
|
if printpending:
|
|
if clearpending:
|
|
sys.stdout.write('\x1b[2J\x1b[;H') # clear screen
|
|
print_current()
|
|
|