I fell into another rabbit hole: logging.  Here's my trip report.

We have:

* util/error-report.c

  - To stderr (or current monitor, but that's not relevant here)

  - Format:
        [TIME ][GUEST-NAME ]PROGNAME:LOCATION: (|warning: |info: )MESSAGE
    where the optional parts are controlled by -msg

  - Maintained: see MAINTAINERS "Error reporting"

* util/log.c

  - Control:

    · Some logging is always on

    · Some logging is off by default, enabled per "log item" with -d

    · Some can additionally be limited to address ranges with -dfilter

  - To the file given by -D (default stderr), or with -d tid to files
    with names derived from the pattern given by -D (%d is replaced by
    the thread ID)

  - Format:
        [TIME ]MESSAGE
    where the optional part is controlled by -msg timestamp (-msg
    guest-name has no effect here)

  - Not covered by MAINTAINERS

* Tracing

  - Control: off by default, enabled with -trace per trace point (and
    also -d trace: --- I find that duplication bizarre)

  - Run time control with HMP commands trace-event, trace-file, QMP
    commands trace-event-get-state, trace-event-set-state

  - To whatever backends are compiled in:

    · "log" wraps around util/log.c's always-on logging

    · "simple" logs to a binary file given by -trace file=

    · "syslog" logs to POSIX syslog

    · "ftrace", "dtrace", "ust" integrate with Linux ftrace, DTrace /
      SystemTap, and LTTng userspace tracing, respectively

  - Maintained: see MAINTAINERS "Traicing"

* Unstructured ad hoc printing to stdout or stderr

I think that's it.

Observations:

* Mixing logs with different formats in one destination makes them
  needlessly hard to read and parse.

  Daniel's "util: sync error_report & qemu_log output more closely"
  series makes util/error-report.c and util/log.c use a common message
  prefix

      [TIME ][GUEST-NAME ]PROGNAME\(THREAD-NAME\):...

  where the optional parts are controlled by -msg.  Continues prior work
  in that direction: commit 012842c0755 (log: make '-msg timestamp=on'
  apply to all qemu_log usage).

* Spreading logs over multiple destinations can make the order hard to
  determine.

  -D splits util/log.c from util/error-report.c.

  -d tid further splits per thread.

  Splitting per thread feels fairly redundant once the prefix includes
  the thread name.  Thread names is easier to make sense of than numeric
  thread IDs in the split filenames.

  To keep the complete log in one place, avoid -D, and enable trace
  backend "log".

* In my view, util/log.c consists of three layers.  Form bottom to top:

  * Logging messages: qemu_log()

  * Control of what to log ("log items"): qemu_log_mask()

  * Address filtering: qemu_log_in_addr_range()

  The bottom layer is also used by trace backend "log".

* Tracing vs. "log items"

  Tracing and "log items" both provide opt-in logging.

  Why do we have two?  Feels like an accident to me.

  When to use which?  I guess people pick whatever they're familiar
  with.

  Would we be better off with just one?  I wish...

  Which one?  Clearly tracing, because tracing backends provide plenty
  of useful functionality "log items" lack.

  "Log items" support per-thread log files.  With tracing, you could
  instead split by thread names once Daniel's series is in.

  Address range filtering is only used with "log items".  It could just
  as easily be used with tracing.

Thoughts?


Reply via email to