How to create a custom sensor (and graph) that monitors a continuously updated log file?
Using PRTG’s custom sensor API, and a little bit of python, I was able to create a beautiful custom sensor and map object. The python script (which had to be turned into an exe in order for prtg to run it) reads some continuously updated log output from one of our applications, and parses it into PRTG-readable xml. Then all I had to do was set the channel thresholds and ta-da! I thought I’d pass on the python script in case anyone wanted to use / improve it.
First an example: Here's how the log looks on it's own:
08/01/2011, 11:39:04.2, Data Engine 1 OK 08/01/2011, 11:39:04.3, Client Status OK 08/01/2011, 11:39:04.4, Document Generation OK 08/01/2011, 11:39:04.5, Importer Engine OK 08/01/2011, 11:39:04.5, Data Engine 2 OK 08/01/2011, 11:39:08.0, Data Engine 3 Error
And here's the python script. It grabs lines, and based on whether the line contains "OK" or "Error" generates XML with appropriate values. (0 or 1 respectively)
import sys def main(): stat = '' logfile = open(***location of log file***) log = logfile.readlines() log = log[-6:] # Logfile is continuously updated by another process, so only last 6 entries of log are read logfile.close() # Start output 'page' --> PRTG readable XML page = '<prtg>' + '\n' tab = '\t' # Parse log into 'page' for line in log: line = line.split(',') if 'OK' in line[-1]: stat = '0' stat_index = line[-1].index('OK') else: stat_index = line[-1].index('Error') stat = '1' component = line[-1][2:stat_index -1] page += '\t<result>\n\t\t<channel>' + component + \ '</channel>'+'\n\t\t<Value>' + stat + '</Value>\n\t</result>\n' page += '</prtg>' return page if __name__ == '__main__': sys.stdout.write(main())
Here's the output generated from the example above.
<prtg> <result> <channel>Data Engine 1</channel> <Value>0</Value> </result> <result> <channel>Client Status</channel> <Value>0</Value> </result> <result> <channel>Document Generation</channel> <Value>0</Value> </result> <result> <channel>Importer Engine</channel> <Value>0</Value> </result> <result> <channel>Data Engine 2</channel> <Value>0</Value> </result> <result> <channel>Data Engine 3</channel> <Value>1</Value> </result> </prtg>
After that, just set the sensor to raise an error if the value is 1, and you're all set.