From 52aa46621a5431d15685c8c65b849246412c3206 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 10 Dec 2013 17:06:36 -0500 Subject: [PATCH] better caputlog output --- iocBoot/ioccaputlog/st.cmd | 2 +- logApp/Db/logwatch.db | 1 + logApp/src/Makefile | 3 +- .../src/{logwatch.py => logwatch/__init__.py} | 35 +++++++++--- logApp/src/logwatch/caputlog.py | 55 +++++++++++++++++++ 5 files changed, 85 insertions(+), 11 deletions(-) rename logApp/src/{logwatch.py => logwatch/__init__.py} (77%) create mode 100644 logApp/src/logwatch/caputlog.py diff --git a/iocBoot/ioccaputlog/st.cmd b/iocBoot/ioccaputlog/st.cmd index 7bfd59a..afcc4ea 100755 --- a/iocBoot/ioccaputlog/st.cmd +++ b/iocBoot/ioccaputlog/st.cmd @@ -5,7 +5,7 @@ dbLoadDatabase("../../dbd/softIocPy.dbd",0,0) softIocPy_registerRecordDeviceDriver(pdbbase) -dbLoadRecords("../../db/logwatch.db","N=logrec,FNAME=/tmp/testlog") +dbLoadRecords("../../db/logwatch.db","N=ACC-CT{}Log-I,FNAME=/var/log/epics/epics.log,FILTER=logwatch.caputlog") iocInit() diff --git a/logApp/Db/logwatch.db b/logApp/Db/logwatch.db index 4da6ac7..cb82fe0 100644 --- a/logApp/Db/logwatch.db +++ b/logApp/Db/logwatch.db @@ -5,5 +5,6 @@ record(waveform, "$(N)") { field(SCAN, "I/O Intr") field(FTVL, "CHAR") field(NELM, "$(NELM=200)") + field(TSE , "-2") info("logfilter","$(FILTER=)") } diff --git a/logApp/src/Makefile b/logApp/src/Makefile index a376db1..98ba1ce 100644 --- a/logApp/src/Makefile +++ b/logApp/src/Makefile @@ -14,7 +14,8 @@ LOADABLE_LIBRARY_HOST = _inotifyy _inotifyy_SRCS += inotify_wrap.c PY += inotifyy.py -PY += logwatch.py +PY += logwatch/__init__.py +PY += logwatch/caputlog.py #=========================== diff --git a/logApp/src/logwatch.py b/logApp/src/logwatch/__init__.py similarity index 77% rename from logApp/src/logwatch.py rename to logApp/src/logwatch/__init__.py index 8652e73..fadaaca 100644 --- a/logApp/src/logwatch.py +++ b/logApp/src/logwatch/__init__.py @@ -1,14 +1,14 @@ # -*- coding: utf-8 -*- from __future__ import print_function -import os.path, errno +import os.path, errno, time import numpy as np import inotifyy as inot from devsup.hooks import addHook -from devsup.util import StoppableThread +from devsup.util import importmod, StoppableThread from devsup.db import IOScanListThread mask=inot.IN_CREATE|inot.IN_DELETE|inot.IN_MOVED_FROM|inot.IN_MODIFY @@ -34,7 +34,14 @@ class LogWatcher(StoppableThread): self.arr = rec.field('VAL').getarray() self.fd = None + filt = rec.info('logfilter',"") + if filt: + filt = importmod(filt) + filt = filt.filter(self.fname) + self.filt = filt + print(rec, 'will watch', self.fname) + print(rec, 'filtered with',self.filt) def detach(self, rec): pass @@ -42,11 +49,17 @@ class LogWatcher(StoppableThread): def process(self, rec, reason=None): if reason is None: return + ts, reason = reason buf = np.frombuffer(reason, dtype=self.arr.dtype) buf = buf[:rec.NELM-1] self.arr[:buf.size] = buf self.arr[buf.size] = 0 rec.NORD = buf.size+1 + + if ts: + rec.setTime(ts) + else: + rec.setTime(time.time()) def join(self): print("Stopping logger for",self.fname) @@ -82,6 +95,7 @@ class LogWatcher(StoppableThread): self.closefile() try: self.fd = open(self.fname, 'r') + self.pos = self.fd.tell() except IOError, e: if e.errno==errno.ENOENT: return @@ -95,14 +109,12 @@ class LogWatcher(StoppableThread): def catfile(self): if not self.fd: return - op = self.fd.tell() self.fd.seek(0,2) # Seek end end = self.fd.tell() - if end < op: - self.log("File size decreased, assuming truncation") - self.buf = None - op = 0 - self.fd.seek(op,0) + if end < self.pos: + self.log("File size decreased from %d to %d, assuming truncation"%(self.pos,end)) + self.pos, self.buf = 0, None + self.fd.seek(self.pos) for L in self.fd.readlines(): if L[-1]!='\n': @@ -115,7 +127,12 @@ class LogWatcher(StoppableThread): L, self.buf = self.buf+L, None self.log(L[:-1]) # Skip newline + self.pos = self.fd.tell() + def log(self, msg): - self.scan.interrupt(reason=msg) + ts = None + if self.filt: + ts, msg = self.filt.apply(msg) + self.scan.interrupt(reason=(ts, msg)) build = LogWatcher diff --git a/logApp/src/logwatch/caputlog.py b/logApp/src/logwatch/caputlog.py new file mode 100644 index 0000000..42e09a2 --- /dev/null +++ b/logApp/src/logwatch/caputlog.py @@ -0,0 +1,55 @@ +""" +linacioc01.cs.nsls2.local:39907 Mon Dec 9 07:07:53 2013 09-Dec-13 07:07:48 diagioc-spc softioc LN-DG{SCR:6}In-Cmd.VAL new=0 old=0 + +Input format is + iochost:port DoW Mon day H:M:S Year D-M-Y H:M:S userhost user PV msg +""" + +import re, time + +R = re.compile(r""" +# iochost:port + (\S+)\s +# date 1 (in logger host TZ) + (?P\S+\s\S+\s+\S+\s\S+\s\S+)\s +# date 2 (in IOC TZ) + (\S+\s\S+)\s +# userhost + (?P\S+)\s +# username + (?P\S+)\s +# PV + (?P\S+)\s +# message + (?P\S.*) +""", re.VERBOSE) + +class CAPutLogFilter(object): + def __init__(self, fname): + self.fname = fname + self.noise = False + + def __str__(self): + return '%s(%s)'%(str(type(self)), self.fname) + __repr__ = __str__ + + def apply(self, line): + M = R.match(line) + if not M: + # lines not matching the caputlog format + # are passed through verbatim + return None, line + D = M.groupdict() + try: + ts = time.mktime(time.strptime(D['ts'],'%a %b %d %H:%M:%S %Y')) + self.noise = False + except ValueError: + if not self.noise: + print("Failed to parse time",D['ts']) + self.noise = True + ts = None + raise + msg = "%(user)s %(host)s %(pv)s %(msg)s"%D + return ts, msg + +filter = CAPutLogFilter