diff options
Diffstat (limited to 'plugins/impstats/statslog-graph.py')
-rwxr-xr-x | plugins/impstats/statslog-graph.py | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/plugins/impstats/statslog-graph.py b/plugins/impstats/statslog-graph.py new file mode 100755 index 00000000..a154d4b9 --- /dev/null +++ b/plugins/impstats/statslog-graph.py @@ -0,0 +1,245 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# * Copyright (C) 2013 Adiscon GmbH. +# * This file is part of RSyslog +# * +# * This script processes csv stats logfiles created by statslog-splitter.py and creates graphs +# * Dependecies: - python pip -> Needed to install python packages +# * - python cairosvg -> Needed for PNG converting support! +# * - Install python packages using this command: +# * pip install CairoSVG tinycss cssselect pygal +# * + +import sys +import datetime +import time +import os +import pygal + +# Set default variables +szInput = "" +szOutputFile = "" +bHelpOutput = False +nMaxDataCount = 25 +bUseDateTime = True +bLineChart = True +bBarChart = False +bConvertPng = False +bLogarithmicChart = False +bFilledLineChart = False +bChartCalcDelta = False + +# Init variables +aFields = [] +aData = {} +aMajorXData = [] + +# Helper variables +nDataRecordCound = 0 +nLineCount = 0 +iStartSeconds = 0 + + +# Process Arguments +for arg in sys.argv: # [-4:]: + if arg.find("--input=") != -1: + szInput = arg[8:] + elif arg.find("--outputfile=") != -1: + szOutputFile = arg[13:] + elif arg.find("--maxdataxlabel=") != -1: + nMaxDataCount = int(arg[16:]) + elif arg.find("--xlabeldatetime") != -1: + bUseDateTime = True + elif arg.find("--xlabelseconds") != -1: + bUseDateTime = False + elif arg.find("--convertpng") != -1: + bConvertPng = True + elif arg.find("--linechart") != -1: + bLineChart = True + bBarChart = False + elif arg.find("--barchart") != -1: + bLineChart = False + bBarChart = True + elif arg.find("--logarithmic") != -1: + bLogarithmicChart = True + elif arg.find("--filledlinechart") != -1: + bFilledLineChart = True + elif arg.find("--chartscalcdelta") != -1: + bChartCalcDelta = True + elif arg.find("--h") != -1 or arg.find("-h") != -1 or arg.find("--help") != -1: + bHelpOutput = True + +if bHelpOutput == True: + print "\n\nStatslog-graph command line options:" + print "=======================================" + print " --input=<filename> Contains the path and filename of your impstats logfile. " + print " Default is 'rsyslog-stats.log' \n" + print " --outputfile=<dir> Output directory and file to be used. " + print " Default is '" + szOutputFile + "'. " + print " --maxdataxlabel=<num> Max Number of data shown on the x-label." + print " Default is 25 label entries." + print " --xlabeldatetime Use Readable Datetime for x label data. (Cannot be used with --xlabelseconds)" + print " Default is enabled." + print " --xlabelseconds Use seconds instead of datetime, starting at 0. (Cannot be used with --xlabeldatetime)" + print " Default is disabled." + print " --linechart Generates a Linechart (Default chart mode) (Cannot be used with --barchart)" + print " --barchart Generates a Barchart (Cannot be used with --linechart)" + print " --logarithmic Uses Logarithmic to scale the Y Axis, maybe useful in some cases. Default is OFF" + print " --filledlinechart Use filled lines on Linechart, maybe useful in some cases. Default is OFF" + print " --chartscalcdelta If set, charts will use calculated delta values instead of cumulative values." + print " --convertpng Generate PNG Output rather than SVG. " + print " Default is SVG output." + print " --h / -h / --help Displays this help message. \n" + print "\n Sampleline: ./statslog-graph.py --input=imuxsock.csv --outputfile=/home/user/csvgraphs/imuxsock.svg" +else: + # Generate output filename + if len(szInput) > 0: + # Only set output filename if not specified + if len(szOutputFile) == 0: + if szInput.rfind(".") == -1: + szOutputFile += szInput + ".svg" + else: + szOutputFile += szInput[:-4] + ".svg" + else: + print "Error, no input file specified!" + sys.exit(0) + + # Process inputfile + inputfile = open(szInput, 'r') + aLineDataPrev = [] # Helper variable for previous line! + for line in inputfile.readlines(): + if nLineCount == 0: + aFields = line.strip().split(";") + # remove last item if empty + if len(aFields[len(aFields)-1]) == 0: + aFields.pop() + #print aFields + #sys.exit(0) + + #Init data arrays + for field in aFields: + aData[field] = [] + else: + aLineData = line.strip().split(";") + # remove last item if empty + if len(aLineData[len(aLineData)-1]) == 0: + aLineData.pop() + + # Loop Through line data + iFieldNum = 0 + for field in aFields: + if iFieldNum == 0: + if bUseDateTime: + aData[field].append( datetime.datetime.strptime(aLineData[iFieldNum],"%Y/%b/%d %H:%M:%S") ) + else: + # Convert Time String into UNIX Timestamp + myDateTime = datetime.datetime.strptime(aLineData[iFieldNum],"%Y/%b/%d %H:%M:%S") + iTimeStamp = int(time.mktime(myDateTime.timetuple())) + + # Init Start Seconds + if iStartSeconds == 0: + iStartSeconds = iTimeStamp + + # Set data field + aData[field].append( iTimeStamp - iStartSeconds ) + elif iFieldNum > 2: + # Check if we need to calculate Deltas! + if bChartCalcDelta and len(aLineDataPrev) > 0: + iPreviousVal = int(aLineDataPrev[iFieldNum]) + iCurrentVal = int(aLineData[iFieldNum]) + if iCurrentVal != 0: # Calc DELTA + aData[field].append(iCurrentVal - iPreviousVal) + else: # Don't Calc delta value! + aData[field].append( iCurrentVal ) + else: + aData[field].append( int(aLineData[iFieldNum]) ) + else: + aData[field].append( aLineData[iFieldNum] ) + + iFieldNum += 1 + # print aData[field[nLineCount]] + + # Increment counter + nDataRecordCound += 1 + + # in case deltas need to be calculated, Store current line into previous line + if bChartCalcDelta: + aLineDataPrev = aLineData + + # Increment counter + nLineCount += 1 + +# if nLineCount > 25: +# break + +# if nMaxDataCount > 0: +# # Check if we need to reduce the data amount +# nTotalDataCount = len( aData[aFields[0]] ) +# nDataStepCount = nTotalDataCount / (nMaxDataCount) +# if nTotalDataCount > nMaxDataCount: +# for iDataNum in reversed(range(0, nTotalDataCount)): +# # Remove all entries who +# if iDataNum % nDataStepCount == 0: +# aMajorXData.append( aData[aFields[0]][iDataNum] ) + + # Import Style +# from pygal.style import LightSolarizedStyle + + # Create Config object + from pygal import Config + chartCfg = Config() + chartCfg.show_legend = True + chartCfg.human_readable = True + chartCfg.pretty_print=True + if bFilledLineChart: + chartCfg.fill = True + else: + chartCfg.fill = False + chartCfg.x_scale = 1 + chartCfg.y_scale = 1 + chartCfg.x_label_rotation = 45 + chartCfg.include_x_axis = True + chartCfg.show_dots=False + if nMaxDataCount > 0: + chartCfg.show_minor_x_labels=False + chartCfg.x_labels_major_count=nMaxDataCount + chartCfg.js = [ 'svg.jquery.js','pygal-tooltips.js' ] # Use script from local +# chartCfg.style = LightSolarizedStyle + chartCfg.print_values = False + chartCfg.print_zeroes = True + chartCfg.no_data_text = "All values are 0" + if bLogarithmicChart: + chartCfg.logarithmic=True # Makes chart Y-Axis data more readable + + # Create Linechart + if bLineChart: + myChart = pygal.Line(chartCfg) + myChart.title = 'Line Chart of "' + szInput + '"' + myChart.x_title = "Time elasped in seconds" + myChart.x_labels = map(str, aData[aFields[0]] ) +# myChart.x_labels_major = map(str, aMajorXData ) + for iChartNum in range(3, len(aFields) ): + myChart.add(aFields[iChartNum], aData[ aFields[iChartNum] ]) # Add some values + # Create BarChart + elif bBarChart: + myChart = pygal.Bar(chartCfg) + myChart.title = 'Bar Chart of "' + szInput + '"' + myChart.x_title = "Time elasped in seconds" + myChart.x_labels = map(str, aData[aFields[0]] ) +# myChart.x_labels_major = map(str, aMajorXData ) + for iChartNum in range(3, len(aFields) ): + myChart.add(aFields[iChartNum], aData[ aFields[iChartNum] ]) # Add some values + + # Render Chart now and output to file! + myChart.render_to_file(szOutputFile) + + # Convert to PNG and remove SVG + if bConvertPng: + szPngFileName = szOutputFile[:-4] + ".png" + iReturn = os.system("cairosvg " + szOutputFile + " -f png -o " + szPngFileName) + print "File SVG converted to PNG: '" + szPngFileName + "', return value of cairosvg: " + str(iReturn) + os.remove(szOutputFile) + + # Finished + sys.exit(0) |