1LogObservers
2============
3
4.. py:module:: buildbot.process.logobserver
5
6.. py:class:: LogObserver
7
8    This is a base class for objects which receive logs from worker commands as they are produced.
9    It does not provide an interface for reading logs - such access should occur directly through the Data API.
10
11    See :ref:`Adding-LogObservers` for help creating and using a custom log observer.
12
13    The three methods that subclasses may override follow.
14    None of these methods may return a Deferred.
15    It is up to the callee to handle any asynchronous operations.
16    Subclasses may also override the constructor, with no need to call :py:class:`LogObserver`'s constructor.
17
18    .. py:method:: outReceived(data):
19
20        :param unicode data: received data
21
22        This method is invoked when a "chunk" of data arrives in the log.
23        The chunk contains one or more newline-terminated unicode lines.
24        For stream logs (e.g., ``stdio``), output to stderr generates a call to :py:meth:`errReceived`, instead.
25
26    .. py:method:: errReceived(data):
27
28        :param unicode data: received data
29
30        This method is similar to :py:meth:`outReceived`, but is called for output to stderr.
31
32    .. py:method:: headerReceived(data):
33
34        :param unicode data: received data
35
36        This method is similar to :py:meth:`outReceived`, but is called for header output.
37
38    .. py:method:: finishReceived()
39
40        This method is invoked when the observed log is finished.
41
42.. py:class:: LogLineObserver
43
44    This subclass of :py:class:`LogObserver` calls its subclass methods once for each line, instead of once per chunk.
45
46    .. py:method:: outLineReceived(line):
47
48        :param unicode line: received line, without newline
49
50        Like :py:meth:`~LogObserver.outReceived`, this is called once for each line of output received.
51        The argument does not contain the trailing newline character.
52
53    .. py:method:: errLineReceived(line):
54
55        :param unicode line: received line, without newline
56
57        Similar to :py:meth:`~LogLineObserver.outLineReceived`, but for stderr.
58
59    .. py:method:: headerLineReceived(line):
60
61        :param unicode line: received line, without newline
62
63        Similar to :py:meth:`~LogLineObserver.outLineReceived`, but for header output.
64
65    .. py:method:: finishReceived()
66
67        This method, inherited from :py:class:`LogObserver`, is invoked when the observed log is finished.
68
69.. py:class:: LineConsumerLogObserver
70
71    This subclass of :py:class:`LogObserver` takes a generator function and "sends" each line to that function.
72    This allows consumers to be written as stateful Python functions, e.g., ::
73
74        def logConsumer(self):
75            while True:
76                stream, line = yield
77                if stream == 'o' and line.startswith('W'):
78                    self.warnings.append(line[1:])
79
80        def __init__(self):
81            ...
82            self.warnings = []
83            self.addLogObserver('stdio', logobserver.LineConsumerLogObserver(self.logConsumer))
84
85    Each ``yield`` expression evaluates to a tuple of (stream, line), where the stream is one of 'o', 'e', or 'h' for stdout, stderr, and header, respectively.
86    As with any generator function, the ``yield`` expression will raise a ``GeneratorExit`` exception when the generator is complete.
87    To do something after the log is finished, just catch this exception (but then re-raise it or return). ::
88
89        def logConsumer(self):
90            while True:
91                try:
92                    stream, line = yield
93                    if stream == 'o' and line.startswith('W'):
94                        self.warnings.append(line[1:])
95                except GeneratorExit:
96                    self.warnings.sort()
97                    return
98
99    .. warning::
100
101        This use of generator functions is a simple Python idiom first described in `PEP 342 <https://www.python.org/dev/peps/pep-0342/>`__.
102        It is unrelated to the generators used in ``inlineCallbacks``.
103        In fact, consumers of this type are incompatible with asynchronous programming, as each line must be processed immediately.
104
105.. py:class:: BufferLogObserver(wantStdout=True, wantStderr=False)
106
107    :param boolean wantStdout: true if stdout should be buffered
108    :param boolean wantStderr: true if stderr should be buffered
109
110    This subclass of :py:class:`LogObserver` buffers stdout and/or stderr for analysis after the step is complete.
111    This can cause excessive memory consumption if the output is large.
112
113    .. py:method:: getStdout()
114
115        :returns: unicode string
116
117        Return the accumulated stdout.
118
119    .. py:method:: getStderr()
120
121        :returns: unicode string
122
123        Return the accumulated stderr.
124