summaryrefslogtreecommitdiffstats
path: root/plugins/impstats/statslog-graph.py
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/impstats/statslog-graph.py')
-rwxr-xr-xplugins/impstats/statslog-graph.py245
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)