[CalendarServer-changes] [12774] CalendarServer/trunk/calendarserver/webadmin/logs.py

source_changes at macosforge.org source_changes at macosforge.org
Thu Feb 27 16:24:11 PST 2014


Revision: 12774
          http://trac.calendarserver.org//changeset/12774
Author:   wsanchez at apple.com
Date:     2014-02-27 16:24:11 -0800 (Thu, 27 Feb 2014)
Log Message:
-----------
Use new eventsource module.

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/webadmin/logs.py

Modified: CalendarServer/trunk/calendarserver/webadmin/logs.py
===================================================================
--- CalendarServer/trunk/calendarserver/webadmin/logs.py	2014-02-28 00:23:44 UTC (rev 12773)
+++ CalendarServer/trunk/calendarserver/webadmin/logs.py	2014-02-28 00:24:11 UTC (rev 12774)
@@ -26,20 +26,13 @@
     "LogEventsResource",
 ]
 
-from collections import deque
-
 from zope.interface import implementer
 
 from twisted.python.log import FileLogObserver
-from twisted.internet.defer import succeed
 
-from txweb2.stream import IByteStream, fallbackSplit
-from txweb2.resource import Resource
-from txweb2.http_headers import MimeType
-from txweb2.http import Response
-
 from calendarserver.accesslog import CommonAccessLoggingObserverExtensions
 
+from .eventsource import EventSourceResource, IEventDecoder
 from .resource import PageElement, TemplateResource
 
 
@@ -75,132 +68,64 @@
 
 
 
-class LogEventsResource(Resource):
+ at implementer(IEventDecoder)
+class EventDecoder(object):
     """
-    Log event vending resource.
+    Decodes logging events.
     """
 
-    addSlash = False
+    @staticmethod
+    def idForEvent(event):
+        observer, eventClass, logEvent = event
+        return id(logEvent)
 
 
-    def __init__(self):
-        Resource.__init__(self)
+    @staticmethod
+    def classForEvent(event):
+        observer, eventClass, logEvent = event
+        return eventClass
 
-        events = deque(maxlen=400)
 
-        observers = (
-            AccessLogObserver(events),
-            ServerLogObserver(events),
-        )
+    @staticmethod
+    def textForEvent(event):
+        observer, eventClass, logEvent = event
 
-        for observer in observers:
-            observer.start()
+        try:
+            if eventClass == u"access":
+                text = logEvent[u"log-format"] % logEvent
+            else:
+                text = observer.formatEvent(logEvent)
+                if text is None:
+                    text = u""
+        except:
+            text = u"*** Error while formatting event ***"
 
-        self.events = events
-        self.observers = observers
+        return text
 
 
-    def render(self, request):
-        start = request.headers.getRawHeaders(u"last-event-id")
 
-        if start is not None:
-            try:
-                start = int(start[0])
-            except ValueError:
-                start = None
-
-        response = Response()
-        response.stream = LogEventStream(self, start=start)
-        response.headers.setHeader(
-            b"content-type", MimeType.fromString(b"text/event-stream")
-        )
-        return response
-
-
-
- at implementer(IByteStream)
-class LogEventStream(object):
+class LogEventsResource(EventSourceResource):
     """
-    L{IByteStream} that streams log events out as HTML5 EventSource events.
+    Log event vending resource.
     """
 
-    length = None
+    def __init__(self):
+        EventSourceResource.__init__(self, EventDecoder)
 
+        self.observers = (
+            AccessLogObserver(self),
+            ServerLogObserver(self),
+        )
 
-    def __init__(self, source, start):
-        object.__init__(self)
+        for observer in self.observers:
+            observer.start()
 
-        self._source = source
-        self._start = start
-        self._closed = False
 
 
-    def read(self):
-        if self._closed:
-            return None
-
-        start = self._start
-        messageID = None
-
-        for observer, eventClass, event in tuple(self._source.events):
-            messageID = id(event)
-
-            # If we have a start point, skip messages up to and including the
-            # one at the start point.
-            if start is not None:
-                if messageID == start:
-                    messageID = None
-                    start = None
-
-                continue
-
-            self._start = messageID
-
-            if eventClass == u"access":
-                message = event[u"log-format"] % event
-            else:
-                message = observer.formatEvent(event)
-                if message is None:
-                    continue
-
-            eventText = textAsEvent(
-                message, eventID=messageID, eventClass=eventClass
-            )
-
-            return succeed(eventText)
-
-        if messageID is not None:
-            # We just scanned all the messages, and none are the last one the
-            # client saw.
-            self._start = None
-
-            marker = "-"
-
-            return succeed(
-                textAsEvent(marker, eventID=0, eventClass=u"access") +
-                textAsEvent(marker, eventID=0, eventClass=u"server")
-            )
-
-        return succeed(None)
-
-        # from twisted.internet.task import deferLater
-        # from twisted.internet import reactor
-
-        # return deferLater(reactor, 1.0, self.read)
-
-
-    def split(self, point):
-        return fallbackSplit(self, point)
-
-
-    def close(self):
-        self._closed = True
-
-
-
 class ServerLogObserver(FileLogObserver):
     """
-    Log observer that captures events in a buffer instead of writing to a file.
+    Log observer that sends events to an L{EventSourceResource} instead of
+    writing to a file.
 
     @note: L{ServerLogObserver} is an old-style log observer, as it inherits
         from L{FileLogObserver}.
@@ -209,7 +134,7 @@
     timeFormat = None
 
 
-    def __init__(self, buffer):
+    def __init__(self, resource):
         class FooIO(object):
             def write(_, s):
                 self._lastMessage = s
@@ -220,18 +145,13 @@
         FileLogObserver.__init__(self, FooIO())
 
         self.lastMessage = None
-        self._buffer = buffer
-        self._waiting = []
+        self._resource = resource
 
 
     def emit(self, event):
-        self._buffer.append((self, u"server", event))
+        self._resource.addEvents(((self, u"server", event),))
 
-        while self._waiting:
-            d = self._waiting.pop(0)
-            d.callback(None)
 
-
     def formatEvent(self, event):
         self._lastMessage = None
         FileLogObserver.emit(self, event)
@@ -248,10 +168,10 @@
         ultimately inherits from L{txweb2.log.BaseCommonAccessLoggingObserver}.
     """
 
-    def __init__(self, buffer):
+    def __init__(self, resource):
         CommonAccessLoggingObserverExtensions.__init__(self)
 
-        self._buffer = buffer
+        self._resource = resource
 
 
     def logStats(self, event):
@@ -259,21 +179,4 @@
         if event[u"type"] != u"access-log":
             return
 
-        self._buffer.append((self, u"access", event))
-
-
-
-def textAsEvent(text, eventID=None, eventClass=None):
-    event = []
-
-    if eventID is not None:
-        event.append(u"id: {0}".format(eventID))
-
-    if eventClass is not None:
-        event.append(u"event: {0}".format(eventClass))
-
-    event.extend(
-        u"data: {0}".format(l) for l in text.split("\n")
-    )
-
-    return u"\n".join(event).encode(u"utf-8") + "\n\n"
+        self._resource.addEvents(((self, u"access", event),))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140227/376a5dd2/attachment-0001.html>


More information about the calendarserver-changes mailing list