testing/mozbase/docs/mozlog_structured.rst

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/testing/mozbase/docs/mozlog_structured.rst	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,274 @@
     1.4 +:mod:`mozlog.structured` --- Structured logging for test output
     1.5 +===============================================================
     1.6 +
     1.7 +``mozlog.structured`` is a library designed for logging the execution
     1.8 +and results of test harnesses. The canonical output format is JSON,
     1.9 +with one line of JSON per log entry. It is *not* based on the stdlib
    1.10 +logging module, although it shares several concepts with this module.
    1.11 +
    1.12 +One notable difference between this module and the standard logging
    1.13 +module is the way that loggers are created. The structured logging
    1.14 +module does not require that loggers with a specific name are
    1.15 +singleton objects accessed through a factory function. Instead the
    1.16 +``StructuredLogger`` constructor may be used directly. However all
    1.17 +loggers with the same name share the same internal state (the "Borg"
    1.18 +pattern). In particular the list of handlers functions is the same for
    1.19 +all loggers with the same name.
    1.20 +
    1.21 +Logging is threadsafe, with access to handlers protected by a
    1.22 +``threading.Lock``. However it is `not` process-safe. This means that
    1.23 +applications using multiple processes, e.g. via the
    1.24 +``multiprocessing`` module, should arrange for all logging to happen in
    1.25 +a single process.
    1.26 +
    1.27 +Data Format
    1.28 +-----------
    1.29 +
    1.30 +Structured loggers produce messages in a simple format designed to be
    1.31 +compatible with the JSON data model. Each message is a single object,
    1.32 +with the type of message indicated by the ``action`` key. It is
    1.33 +intended that the set of ``action`` values be closed; where there are
    1.34 +use cases for additional values they should be integrated into this
    1.35 +module rather than extended in an ad-hoc way. The set of keys present
    1.36 +on on all messages is:
    1.37 +
    1.38 +``action``
    1.39 +  The type of the message (string).
    1.40 +
    1.41 +``time``
    1.42 +  The timestamp of the message in ms since the epoch (int).
    1.43 +
    1.44 +``thread``
    1.45 +  The name of the thread emitting the message (string).
    1.46 +
    1.47 +``pid``
    1.48 +  The pid of the process creating the message (int).
    1.49 +
    1.50 +``source``
    1.51 +  Name of the logger creating the message (string).
    1.52 +
    1.53 +For each ``action`` there are is a further set of specific fields
    1.54 +describing the details of the event that caused the message to be
    1.55 +emitted:
    1.56 +
    1.57 +``suite_start``
    1.58 +  Emitted when the testsuite starts running.
    1.59 +
    1.60 +  ``tests``
    1.61 +    A list of test_ids (list).
    1.62 +
    1.63 +  ``run_info``
    1.64 +    An optional dictionary describing the properties of the
    1.65 +    build and test environment. This contains the information provided
    1.66 +    by :doc:`mozinfo <mozinfo>`, plus a boolean ``debug`` field indicating
    1.67 +    whether the build under test is a debug build.
    1.68 +
    1.69 +``suite_end``
    1.70 +  Emitted when the testsuite is finished and no more results will be produced.
    1.71 +
    1.72 +``test_start``
    1.73 +  Emitted when a test is being started.
    1.74 +
    1.75 +  ``test``
    1.76 +    A unique id for the test (string or list of strings).
    1.77 +
    1.78 +``test_status``
    1.79 +  Emitted for a test which has subtests to record the result of a
    1.80 +  single subtest
    1.81 +
    1.82 +  ``test``
    1.83 +    The same unique id for the test as in the ``test_start`` message.
    1.84 +
    1.85 +  ``subtest``
    1.86 +    Name of the subtest (string).
    1.87 +
    1.88 +  ``status``
    1.89 +    Result of the test (string enum; ``PASS``, ``FAIL``, ``TIMEOUT``,
    1.90 +    ``NOTRUN``)
    1.91 +
    1.92 +  ``expected``
    1.93 +    Expected result of the test. Omitted if the expected result is the
    1.94 +    same as the actual result (string enum, same as ``status``).
    1.95 +
    1.96 +``test_end``
    1.97 +  Emitted to give the result of a test with no subtests, or the status
    1.98 +  of the overall file when there are subtests.
    1.99 +
   1.100 +  ``test``
   1.101 +    The same unique id for the test as in the ``test_start`` message.
   1.102 +
   1.103 +  ``status``
   1.104 +    Either result of the test (if there are no subtests) in which case
   1.105 +    (string enum ``PASS``, ``FAIL``, ``TIMEOUT``, ``CRASH``,
   1.106 +    ``ASSERT``, ``SKIP``) or the status of the overall file where
   1.107 +    there are subtests (string enum ``OK``, ``ERROR``, ``TIMEOUT``,
   1.108 +    ``CRASH``, ``ASSERT``, ``SKIP``).
   1.109 +
   1.110 +  ``expected``
   1.111 +    The expected status, or emitted if the expected status matches the
   1.112 +    actual status (string enum, same as ``status``).
   1.113 +
   1.114 +``process_output``
   1.115 +  Output from a managed subprocess.
   1.116 +
   1.117 +  ``process``
   1.118 +  pid of the subprocess.
   1.119 +
   1.120 +  ``command``
   1.121 +  Command used to launch the subprocess.
   1.122 +
   1.123 +  ``data``
   1.124 +  Data output by the subprocess.
   1.125 +
   1.126 +``log``
   1.127 +  General human-readable logging message, used to debug the harnesses
   1.128 +  themselves rather than to provide input to other tools.
   1.129 +
   1.130 +  ``level``
   1.131 +    Level of the log message (string enum ``CRITICAL``, ``ERROR``,
   1.132 +    ``WARNING``, ``INFO``, ``DEBUG``).
   1.133 +
   1.134 +  ``message``
   1.135 +    Text of the log message.
   1.136 +
   1.137 +StructuredLogger Objects
   1.138 +------------------------
   1.139 +
   1.140 +.. automodule:: mozlog.structured.structuredlog
   1.141 +
   1.142 +.. autoclass:: StructuredLogger
   1.143 +   :members: add_handler, remove_handler, handlers, suite_start,
   1.144 +             suite_end, test_start, test_status, test_end,
   1.145 +             process_output, critical, error, warning, info, debug
   1.146 +
   1.147 +.. autoclass:: StructuredLogFileLike
   1.148 +  :members:
   1.149 +
   1.150 +Handlers
   1.151 +--------
   1.152 +
   1.153 +A handler is a callable that is called for each log message produced
   1.154 +and is responsible for handling the processing of that
   1.155 +message. The typical example of this is a ``StreamHandler`` which takes
   1.156 +a log message, invokes a formatter which converts the log to a string,
   1.157 +and writes it to a file.
   1.158 +
   1.159 +.. automodule:: mozlog.structured.handlers
   1.160 +
   1.161 +.. autoclass:: StreamHandler
   1.162 +  :members:
   1.163 +
   1.164 +.. autoclass:: LogLevelFilter
   1.165 +  :members:
   1.166 +
   1.167 +Formatters
   1.168 +----------
   1.169 +
   1.170 +Formatters are callables that take a log message, and return either a
   1.171 +string representation of that message, or ``None`` if that message
   1.172 +should not appear in the output. This allows formatters to both
   1.173 +exclude certain items and create internal buffers of the output so
   1.174 +that, for example, a single string might be returned for a
   1.175 +``test_end`` message indicating the overall result of the test,
   1.176 +including data provided in the ``test_status`` messages.
   1.177 +
   1.178 +Formatter modules are written so that they can take raw input on stdin
   1.179 +and write formatted output on stdout. This allows the formatters to be
   1.180 +invoked as part of a command line for post-processing raw log files.
   1.181 +
   1.182 +.. automodule:: mozlog.structured.formatters.base
   1.183 +
   1.184 +.. autoclass:: BaseFormatter
   1.185 +  :members:
   1.186 +
   1.187 +.. automodule:: mozlog.structured.formatters.unittest
   1.188 +
   1.189 +.. autoclass:: UnittestFormatter
   1.190 +  :members:
   1.191 +
   1.192 +.. automodule:: mozlog.structured.formatters.xunit
   1.193 +
   1.194 +.. autoclass:: XUnitFormatter
   1.195 +  :members:
   1.196 +
   1.197 +.. automodule:: mozlog.structured.formatters.html
   1.198 +
   1.199 +.. autoclass:: HTMLFormatter
   1.200 +  :members:
   1.201 +
   1.202 +.. automodule:: mozlog.structured.formatters.machformatter
   1.203 +
   1.204 +.. autoclass:: MachFormatter
   1.205 +  :members:
   1.206 +
   1.207 +.. autoclass:: MachTerminalFormatter
   1.208 +  :members:
   1.209 +
   1.210 +Processing Log Files
   1.211 +--------------------
   1.212 +
   1.213 +The ``mozlog.structured.reader`` module provides utilities for working
   1.214 +with structured log files.
   1.215 +
   1.216 +.. automodule:: mozlog.structured.reader
   1.217 +  :members:
   1.218 +
   1.219 +Integration with argparse
   1.220 +-------------------------
   1.221 +
   1.222 +The `mozlog.structured.commandline` module provides integration with
   1.223 +the `argparse` module to provide uniform logging-related command line
   1.224 +arguments to programs using `mozlog.structured`. Each known formatter
   1.225 +gets a command line argument of the form ``--log-{name}``, which takes
   1.226 +the name of a file to log to with that format of `-` to indicate stdout.
   1.227 +
   1.228 +.. automodule:: mozlog.structured.commandline
   1.229 +  :members:
   1.230 +
   1.231 +Examples
   1.232 +--------
   1.233 +
   1.234 +Log to stdout::
   1.235 +
   1.236 +    from mozlog.structured import structuredlog
   1.237 +    from mozlog.structured import handlers, formatters
   1.238 +    logger = structuredlog.StructuredLogger("my-test-suite")
   1.239 +    logger.add_handler(handlers.StreamHandler(sys.stdout,
   1.240 +                                              formatters.JSONFormatter()))
   1.241 +    logger.suite_start(["test-id-1"])
   1.242 +    logger.test_start("test-id-1")
   1.243 +    logger.info("This is a message with action='LOG' and level='INFO'")
   1.244 +    logger.test_status("test-id-1", "subtest-1", "PASS")
   1.245 +    logger.test_end("test-id-1", "OK")
   1.246 +    logger.suite_end()
   1.247 +
   1.248 +
   1.249 +Populate an ``argparse.ArgumentParser`` with logging options, and
   1.250 +create a logger based on the value of those options, defaulting to
   1.251 +JSON output on stdout if nothing else is supplied::
   1.252 +
   1.253 +   import argparse
   1.254 +   from mozlog.structured import commandline
   1.255 +
   1.256 +   parser = argparse.ArgumentParser()
   1.257 +   # Here one would populate the parser with other options
   1.258 +   commandline.add_logging_group(parser)
   1.259 +
   1.260 +   args = parser.parse_args()
   1.261 +   logger = commandline.setup_logging("testsuite-name", args, {"raw": sys.stdout})
   1.262 +
   1.263 +Count the number of tests that timed out in a testsuite::
   1.264 +
   1.265 +   from mozlog.structured import reader
   1.266 +
   1.267 +   count = 0;
   1.268 +
   1.269 +   def handle_test_end(data):
   1.270 +       global count
   1.271 +       if data["status"] == "TIMEOUT":
   1.272 +           count += 1
   1.273 +
   1.274 +   reader.each_log(reader.read("my_test_run.log"),
   1.275 +                   {"test_end": handle_test_end})
   1.276 +
   1.277 +   print count

mercurial