Logging/Debugging
=================

Weston's printf
---------------

Logging in weston takes place through :func:`weston_log()` function, which
calls a log handler (:var:`log_handler`) that has to be installed before
actually calling :func:`weston_log()`.  In weston, the log handler makes use of
the logging framework which is (mostly) comprised of :ref:`log scopes` (produces
of data) and :ref:`subscribers`.

Logging context
---------------

Management of the logging framework in weston happens under the
:type:`weston_log_context` object and is entirely separated from the main
compositor instance (:type:`weston_compositor`). The compositor
instance can be brought up much more later, but in the same time logging can
take place much earlier without the need of a compositor instance.

Instantiation of the :type:`weston_log_context` object takes place using
:func:`weston_log_ctx_create()` and clean-up/destroy with
:func:`weston_log_ctx_destroy()` or :func:`weston_log_ctx_compositor_destroy()`.

Log scopes
----------

A scope represents a source for a data stream (i.e., a producer). You'll
require one as a way to generate data. Creating a log scope is done using
:func:`weston_log_ctx_add_log_scope()` or
:func:`weston_compositor_add_log_scope()`. You can customize the scope
behaviour and you'll require at least a name and a description for the scope.

.. note::

   A scope **name** identifies that scope. Scope retrieval from the
   :type:`weston_log_context` is done using the scope name. The name is
   important for the subscription part, detailed bit later.

Log scopes are managed **explicitly**, and destroying the scope is done using
:func:`weston_log_scope_destroy`.

Available scopes in weston
~~~~~~~~~~~~~~~~~~~~~~~~~~

Weston has a few scopes worth mentioning:

- **log** - a debug scope for generic logging, upon which :func:`weston_log`
  re-routes its data.
- **proto** - debug scope that displays the protocol communication. It is
  similar to WAYLAND_DEBUG=server environmental variable but has the ability to
  distinguish multiple clients.
- **scene-graph** - an one-shot debug scope which describes the current scene
  graph comprising of layers (containers of views), views (which represent a
  window), their surfaces, sub-surfaces, buffer type and format, both in
  :samp:`DRM_FOURCC` type and human-friendly form.
- **drm-backend** - Weston uses DRM (Direct Rendering Manager) as one of its
  backends and this debug scope display information related to that: details
  the transitions of a view as it takes before being assigned to a hardware
  plane or to a renderer, current assignments of views, the compositing mode
  Weston is using for rendering the scene-graph, describes the current hardware
  plane properties like CRTC_ID, FB_ID, FORMAT when doing a commit or a
  page-flip. It incorporates the scene-graph scope as well.
- **xwm-wm-x11** - a scope for the X11 window manager in Weston for supporting
  Xwayland, printing some X11 protocol actions.
- **content-protection-debug** - scope for debugging HDCP issues.
- **timeline** - see more at :ref:`timeline points`

.. note::

   Besides 'log' scope, which is a generic scope, intended for usage through
   :func:`weston_log`, all the others scopes listed above could suffer various
   modifications and might not represent a current list on which one should
   rely upon.


Subscribers
-----------

Besides creating a creating a scope, a subscriber (:type:`weston_log_subscriber`)
object needs to be created. The subscriber object is an opaque
object (private) and allows customization of the back-end side of libweston.
The subscriber object can define its own methods. Users wanting to define
a new data stream should extend this :type:`weston_log_subscriber`.

For example libweston make uses of several type of subscribers, specific to the
data streams they will be generating:

- a **'logger'** type created by :func:`weston_log_subscriber_create_log()`
- a **'flight-recoder'** type created by :func:`weston_log_subscriber_destroy_flight_rec()`
- for the **'weston-debug'** protocol, which is private/hidden created whenever a
  client connects

Like log scopes, the subscribers are also manged **explicitly** and both of the
subscriber types above have their destroy counter-parts. `weston-debug`
protocol is a bit special in this regard as the destroying part is handled
implicitly using wayland protocol specifics.

Once the subscriber has been created there needs to be a subscription process
in which we establish a relationship between the subscriber and the scope.

To create a subscription we use :func:`weston_log_subscribe` which uses the
subscriber created previously and the scope name. If the scope was not created
at the time, the subscription will be (at least for a time) a *pending
subscription*. Once the scope is created the *pending subscription* is
destroyed, not before creating a new subscription to accommodate the
initial/original one.

.. note::

   The subscription process is (an) internal API and is managed implicitly.

When a scope is being destroyed the subscriptions for this scope will be
destroyed as well.

Logger
~~~~~~

weston uses a logger type of a subscriber for logging everything in the code
(through the help of :func:`weston_log()`).  The subscriber method
(:func:`weston_log_subscriber_create_log()`) takes an :samp:`FILE *` as an
argument in case the std :samp:`stdout` file-descriptor is not where the data
should be sent to.

Additionally, specifying which scopes to subscribe to can be done using
:samp:`--logger-scopes` command line option. As log scopes are already created
in the code, this merely subscribes to them. Default, the 'log' scope is being
subscribr to the logger subscriber.

Flight recorder
~~~~~~~~~~~~~~~

The flight recorder acts like a black box found in airplanes: it accumulates
data until the user wants to display its contents. The backed up storage is a
simple ring-buffer of a compiled-time fixed size value, and the memory is
forcibly-mapped such that we make sure the kernel allocated storage for it.

The user can use the debug keybinding :samp:`KEY_D` (shift+mod+space-d) to
force the contents to be printed on :samp:`stdout` file-descriptor.
The user has first to specify which log scope to subscribe to.

Specifying which scopes to subscribe for the flight-recorder can be done using
:samp:`-f|--flight-rec-scopes`. By default, only the 'log' scope is subscribed
to. See :ref:`debugging flight recorder` on how retrieve the contents of the
flight recorder in case Weston dies/crashes unexpectedly.

weston-debug protocol
~~~~~~~~~~~~~~~~~~~~~

Weston-debug protocol is only present in the weston compositor (i.e., a weston
specific compositor). It make uses of the the logging framework presented
above, with the exception that the subscription happens automatically rather
than manually with :func:`weston_log_subscribe()` in case of the other two
types of subscribers.  Also the subscriber is created once the client has
connected and requested data from a log scope.  This means that each time a
client connects a new subscriber will be created.  For each stream subscribed a
subscription will be created.  Enabling the debug-protocol happens using the
:samp:`--debug` command line.

Timeline points
---------------

A special log scope is the 'timeline' scope which, together with
`wesgr <https://github.com/ppaalanen/wesgr>`_ tool, helps diagnose latency issues.
Timeline points write to this 'timeline' scope in different parts of the
compositor, including the GL renderer.

As with all other scopes this scope is available over the debug protocol, or by
using the others :ref:`subscribers`. By far the easiest way to get data out
of this scope would be to use the debug protocol.
Then use `wesgr <https://github.com/ppaalanen/wesgr>`_ to process the data which
will transform it into a SVG that can be rendered by any web browser.

The following illustrates how to use it:

.. code-block:: console

   ./weston-debug timeline > log.json
   ./wesgr -i log.json -o log.svg

Weston has experimental support for `Perfetto <https://perfetto.dev>`_ for
performance profiling. It can be enabled by using `-Dperfetto=true` during
the meson invocation to configure the build.

If Perfetto support is built in, timeline points are added to Perfetto tracks
when Perfetto is running, even when the 'timeline' scope is not enabled.

For capturing a trace you can use the supplied
`out of process trace <https://gitlab.freedesktop.org/wayland/weston/-/tree/main/doc/perfetto/perfetto_out_of_process_trace.cfg>`_.
config file.

Inserting timeline points
~~~~~~~~~~~~~~~~~~~~~~~~~

Timline points can be inserted using :c:macro:`TL_POINT` macro. The macro will
take the :type:`weston_compositor` instance, followed by the name of the
timeline point. What follows next is a variable number of arguments, which
**must** end with the macro :c:macro:`TLP_END`.

Adding Perfetto trace points
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In addition to timeline points, Perfetto can also display timing information
for individual functions. The easiest way to add profiling data for a function
is to insert the :c:macro:`WESTON_TRACE_FUNC` at the top of the function.

Debug protocol API
------------------

.. doxygengroup:: debug-protocol
   :content-only:

Weston Log API
--------------

.. doxygengroup:: wlog
   :content-only:

Logging API
-----------

.. doxygengroup:: log
   :content-only:

Internal logging API
--------------------

.. note::

   The following is mean to be internal API and aren't exposed in libweston!

.. doxygengroup:: internal-log
   :content-only:
