changeset 265:78c542f03030

Limit log
author Matt Johnston <matt@ucc.asn.au>
date Sat, 13 Jun 2015 22:49:14 +0800
parents 205809a8872f
children 20c89630be6c
files py/configwaiter.py py/uploader.py py/utils.py
diffstat 3 files changed, 54 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/py/configwaiter.py	Sat Jun 13 21:56:51 2015 +0800
+++ b/py/configwaiter.py	Sat Jun 13 22:49:14 2015 +0800
@@ -1,4 +1,6 @@
 import asyncio
+import datetime
+
 import aiohttp
 
 import utils
@@ -12,6 +14,7 @@
         self.server = server
         self.epoch_tag = None
         self.http_session = aiohttp.ClientSession()
+        self.limitlog = utils.NotTooOften(datetime.timedelta(minutes=15))
 
     @asyncio.coroutine
     def run(self):
@@ -49,14 +52,13 @@
                 pass
             else:
                 # longer timeout to avoid spinning
+                text = yield from asyncio.wait_for(r.text(), 600)
+                D("Bad server response. %d %s" % (r.status, text))
                 yield from asyncio.sleep(30)
 
-        except asyncio.TimeoutError:
-            D("configwaiter http timed out")
-            pass
+        except aiohttp.errors.ClientError as e:
+            self.limitlog.log("Error with configwaiter: %s" % str(e))
+        except asyncio.TimeoutError as e:
+            self.limitlog.log("configwaiter http timed out: %s" % str(e))
         except Exception as e:
             EX("Error watching config: %s" % str(e))
-
-
-
-
--- a/py/uploader.py	Sat Jun 13 21:56:51 2015 +0800
+++ b/py/uploader.py	Sat Jun 13 22:49:14 2015 +0800
@@ -15,6 +15,7 @@
 class Uploader(object):
     def __init__(self, server):
         self.server = server
+        self.limitlog = utils.NotTooOften(600)
 
     @asyncio.coroutine
     def run(self):
@@ -43,6 +44,9 @@
 
         return tosend
 
+    class BadServerResponse(Exception):
+        pass
+
     @asyncio.coroutine
     def send(self, tosend):
         js = json.dumps(tosend)
@@ -55,7 +59,7 @@
         r = yield from asyncio.wait_for(aiohttp.request('post', config.UPDATE_URL, data=send_data), 60)
         result = yield from asyncio.wait_for(r.text(), 60)
         if r.status == 200 and result != 'OK':
-            raise Exception("Server returned %s" % result)
+            raise BadServerResponse("Server returned %s" % result)
 
     @asyncio.coroutine
     def do(self):
@@ -67,6 +71,12 @@
             yield from self.send(tosend)
             readings = None
             D("Sent updated %d readings" % nreadings)
+        except aiohttp.errors.ClientError as e:
+            self.limitlog.log("Error with uploader: %s" % str(e))
+        except asyncio.TimeoutError as e:
+            self.limitlog.log("uploader http timed out: %s" % str(e))
+        except self.BadServerResponse as e:
+            self.limitlog.log("Bad reply with uploader: %s" % str(e))
         except Exception as e:
             EX("Error in uploader: %s" % str(e))
         finally:
--- a/py/utils.py	Sat Jun 13 21:56:51 2015 +0800
+++ b/py/utils.py	Sat Jun 13 22:49:14 2015 +0800
@@ -1,11 +1,12 @@
 import os
 import sys
-#import ctypes
+import ctypes
 import time
 import select
 import logging
 import binascii
 import json
+import datetime
 
 D = logging.debug
 L = logging.info
@@ -138,3 +139,35 @@
 
 def json_load_round_float(s, **args):
     return json.loads(s,parse_float = lambda f: round(float(f), 2), **args)
+
+class NotTooOften(object):
+    """ prevents things happening more than once per limit.
+    Isn't monotonic, good enough for logging. eg
+    self.logfailure = NotTooOften(180) # 3 minutes
+    ...
+    if self.logfailure():
+        L("blah")
+    """
+    def __init__(self, limit):
+        """ limit is a delay in seconds or TimeDelta """
+        if type(limit) is datetime.timedelta:
+            self.limit = limit
+        else:
+            self.limit = datetime.timedelta(seconds=limit)
+
+        # must be positive
+        assert self.limit > datetime.timedelta(0)
+        self.last = datetime.datetime(10, 1, 1)
+
+    def __call__(self):
+        if datetime.datetime.now() - self.last > self.limit:
+            self.last = datetime.datetime.now()
+            return True
+
+    def log(self, msg):
+        """ calls L(msg) if it isn't too often, otherwise D(msg)
+        """
+        if self():
+            L(msg + " (log interval %s)" % str(self.limit))
+        else:
+            D(msg)