From 0d8690d5b7993eff78b13b10a8636dc85f8a265b Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 9 Dec 2014 11:50:23 -0500 Subject: [PATCH] archApp: archiver appliance monitoring --- archApp/Makefile | 13 ++++ archApp/applmetrics.db | 119 ++++++++++++++++++++++++++++++++ archApp/bplreport.py | 151 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 283 insertions(+) create mode 100644 archApp/Makefile create mode 100644 archApp/applmetrics.db create mode 100644 archApp/bplreport.py diff --git a/archApp/Makefile b/archApp/Makefile new file mode 100644 index 0000000..36838b9 --- /dev/null +++ b/archApp/Makefile @@ -0,0 +1,13 @@ +TOP=.. +include $(TOP)/configure/CONFIG +include $(TOP)/configure/CONFIG_PY +#---------------------------------------- +# ADD MACRO DEFINITIONS AFTER THIS LINE + +PY += bplreport.py +DB += applmetrics.db + +include $(TOP)/configure/RULES +include $(TOP)/configure/RULES_PY +#---------------------------------------- +# ADD RULES AFTER THIS LINE diff --git a/archApp/applmetrics.db b/archApp/applmetrics.db new file mode 100644 index 0000000..6fed235 --- /dev/null +++ b/archApp/applmetrics.db @@ -0,0 +1,119 @@ +record(ai, "$(P)Rate:Store-I") { + field(DTYP, "Python Device") + field(INP , "@bplreport fetch_float metrics.0.dataRateGBPerDay") + field(SCAN, "I/O Intr") + field(PREC, "2") + field(EGU , "GB/day") + field(TSE , "-2") + field(HOPR, "50") + field(LOPR, "0") + field(HIHI, "15") + field(HIGH, "11") + field(LOW , "9") + field(LOLO, "0.1") + field(HHSV, "MAJOR") + field(HSV , "MINOR") + field(LSV , "MINOR") + field(LLSV, "INVALID") + info("autosaveFields_pass0", "HOPR LOPR HIHI HIGH LOW LOLO") +} + +record(ai, "$(P)Rate:Event-I") { + field(DTYP, "Python Device") + field(INP , "@bplreport fetch_float metrics.0.eventRate") + field(SCAN, "I/O Intr") + field(PREC, "2") + field(EGU , "evt/s") + field(TSE , "-2") + field(HOPR, "50000") + field(LOPR, "0") + field(HIHI, "10000") + field(HIGH, "7000") + field(LOW , "5000") + field(LOLO, "1") + field(HHSV, "MAJOR") + field(HSV , "MINOR") + field(LSV , "MINOR") + field(LLSV, "INVALID") + info("autosaveFields_pass0", "HOPR LOPR HIHI HIGH LOW LOLO") +} + +record(ai, "$(P)Time:Write-I") { + field(DESC, "Engine write thread") + field(DTYP, "Python Device") + field(INP , "@bplreport fetch_float metrics.0.secondsConsumedByWritter") + field(SCAN, "I/O Intr") + field(PREC, "2") + field(EGU , "s") + field(TSE , "-2") + field(HOPR, "10") + field(LOPR, "0") + field(HIHI, "5") + field(HIGH, "2") + field(LOW , "0.2") + field(LOLO, "0.1") + field(HHSV, "MAJOR") + field(HSV , "MINOR") + field(LSV , "MINOR") + field(LLSV, "INVALID") + info("autosaveFields_pass0", "HOPR LOPR HIHI HIGH LOW LOLO") +} + +record(longin, "$(P)Cnt:Conn-I") { + field(DTYP, "Python Device") + field(INP , "@bplreport fetch_int metrics.0.connectedPVCount") + field(SCAN, "I/O Intr") + field(TSE , "-2") +} + +record(longin, "$(P)Cnt:Disconn-I") { + field(DTYP, "Python Device") + field(INP , "@bplreport fetch_int metrics.0.disconnectedPVCount") + field(SCAN, "I/O Intr") + field(TSE , "-2") + field(HOPR, "10000") + field(LOPR, "0") + field(HIHI, "10") + field(HIGH, "1") + field(LOW , "0") + field(HHSV, "MAJOR") + field(HSV , "MINOR") + info("autosaveFields_pass0", "HOPR LOPR HIHI HIGH") +} + +record(stringin, "$(P)Status-I") { + field(DTYP, "Python Device") + field(INP , "@bplreport fetch_string metrics.0.status") + field(SCAN, "I/O Intr") + field(TSE , "-2") +} + +record(longin, "$(P)Cnt:Type-I") { + field(DTYP, "Python Device") + field(INP , "@bplreport fetch_length typechange.0.") + field(SCAN, "I/O Intr") + field(TSE , "-2") + field(HOPR, "10000") + field(LOPR, "0") + field(HIHI, "10") + field(HIGH, "1") + field(LOW , "0") + field(HHSV, "MAJOR") + field(HSV , "MINOR") + info("autosaveFields_pass0", "HOPR LOPR HIHI HIGH") +} + +record(longin, "$(P)Cnt:Never-I") { + field(DTYP, "Python Device") + field(INP , "@bplreport fetch_length neverconn.0.") + field(SCAN, "I/O Intr") + field(TSE , "-2") + field(HOPR, "10000") + field(LOPR, "0") + field(HIHI, "10") + field(HIGH, "1") + field(LOW , "0") + field(HHSV, "MAJOR") + field(HSV , "MINOR") + info("autosaveFields_pass0", "HOPR LOPR HIHI HIGH") +} diff --git a/archApp/bplreport.py b/archApp/bplreport.py new file mode 100644 index 0000000..ac0d86e --- /dev/null +++ b/archApp/bplreport.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- + +import time, sched, urllib2, json +from devsup.db import IOScanListBlock +from devsup.hooks import initHook +from devsup.util import StoppableThread + +class BPLReport(object): + reports = {} + + def __init__(self, name, url, period): + self.name = name + self.url, self.period = url, period + self.result = None + self.reports[name] = self + self.scan = IOScanListBlock() + + def fail(self): + self.result = None + + def process(self): + self.result = None + R = urllib2.urlopen(self.url, timeout=3) + try: + if R.getcode()!=200: + print 'Fail',R.getcode(), self.url + self.result = None + return + self.result = json.load(R) + except: + print 'Error fetching',self.url + import traceback + traceback.print_exc() + finally: + R.close() + self.result_time = time.time() + self.scan.interrupt(reason = self.result) + +add = BPLReport + +class ReportRunner(StoppableThread): + class _Done(Exception): + pass + + def _sleep(self, time): + if not self.sleep(time): + raise self._Done() + + def _proc(self, R): + self._S.enter(R.period, 0, self._proc, (R,)) + try: + R.process() + except: + print 'Error in processing',R.url + import traceback + traceback.print_exc() + R.fail() + + def run(self): + self._S = S = sched.scheduler(time.time, self._sleep) + + for R in BPLReport.reports.itervalues(): + S.enter(0, 0, self._proc, (R,)) + + try: + S.run() + except self._Done: + print 'BPL worker exit' + except: + print 'Error in scheduler' + import traceback + traceback.print_exc() + +_worker = ReportRunner() + +@initHook("AfterIocRunning") +def _startWorker(): + _worker.start() + print 'BPL worker started' + +@initHook("AtIocExit") +def _stopWorker(): + print 'BPL worker stopping' + _worker.join() + print 'BPL worker stopped' + +class ReportItem(object): + raw = True + def __init__(self, rec, args): + # " .. " + opname, src = args.split(None,2)[:2] + self.report, self.idx, self.attrib = src.split('.',2) + self.idx = int(self.idx) + self.R = BPLReport.reports[self.report] + + self.allowScan = self.R.scan.add + self.process = getattr(self, 'process_'+opname) + + def detach(self, rec): + pass + + def process_fetch_float(self, rec, reason=None): + R = self.R.result + invalid = True + if R is not None and len(R)>self.idx: + try: + rec.VAL = float(str(R[self.idx][self.attrib]).translate(None,',')) + except KeyError: + pass + else: + invalid = False + + rec.UDF = invalid + rec.setTime(self.R.result_time) + + def process_fetch_int(self, rec, reason=None): + R = self.R.result + invalid = True + if R is not None and len(R)>self.idx: + try: + rec.VAL = int(R[self.idx][self.attrib]) + except KeyError: + pass + else: + invalid = False + + rec.UDF = invalid + rec.setTime(self.R.result_time) + + def process_fetch_string(self, rec, reason=None): + R = self.R.result + invalid = True + if R is not None and len(R)>self.idx: + try: + rec.VAL = R[self.idx][self.attrib].encode('ascii') + except KeyError: + pass + else: + invalid = False + + if invalid: + rec.setSevr() # default is INVALID_ALARM + rec.setTime(self.R.result_time) + + def process_fetch_length(self, rec, reason=None): + if self.R.result is not None: + rec.VAL = len(self.R.result) + rec.UDF = self.R.result is None + rec.setTime(self.R.result_time) + +build = ReportItem