Daniel P. Berrangé <berra...@redhat.com> writes:

> Currently the tracing 'log' back emits special code to add timestamps
> to trace points sent via qemu_log(). This current impl is a bad design
> for a number of reasons.
>
>  * It changes the QEMU headers, such that 'error-report.h' content
>    is visible to all files using tracing, but only when the 'log'
>    backend is enabled. This has led to build failure bugs as devs
>    rarely test without the (default) 'log' backend enabled, and
>    CI can't cover every scenario for every trace backend.
>
>  * It bloats the trace points definitions which are inlined into
>    every probe location due to repeated inlining of timestamp
>    formatting code, adding MBs of overhead to QEMU.
>
>  * The tracing subsystem should not be treated any differently
>    from other users of qemu_log. They all would benefit from
>    having timestamps present.
>
>  * The timestamp emitted with the tracepoints is in a needlessly
>    different format to that used by error_report() in response
>    to '-msg timestamp=on'.
>
> This fixes all these issues simply by moving timestamp formatting
> into qemu_log, using the same approach as for error_report.
>
> The code before:
>
>   static inline void _nocheck__trace_qcrypto_tls_creds_get_path(void * creds, 
> const char * filename, const char * path)
>   {
>       if (trace_event_get_state(TRACE_QCRYPTO_TLS_CREDS_GET_PATH) && 
> qemu_loglevel_mask(LOG_TRACE)) {
>           if (message_with_timestamp) {
>               struct timeval _now;
>               gettimeofday(&_now, NULL);
>               qemu_log("%d@%zu.%06zu:qcrypto_tls_creds_get_path " "TLS creds 
> path creds=%p filename=%s path=%s" "\n",
>                        qemu_get_thread_id(),
>                        (size_t)_now.tv_sec, (size_t)_now.tv_usec
>                        , creds, filename, path);
>           } else {
>               qemu_log("qcrypto_tls_creds_get_path " "TLS creds path creds=%p 
> filename=%s path=%s" "\n", creds, filename, path);
>           }
>       }
>   }
>
> and after:
>
>   static inline void _nocheck__trace_qcrypto_tls_creds_get_path(void * creds, 
> const char * filename, const char * path)
>   {
>       if (trace_event_get_state(TRACE_QCRYPTO_TLS_CREDS_GET_PATH) && 
> qemu_loglevel_mask(LOG_TRACE)) {
>           qemu_log("qcrypto_tls_creds_get_path " "TLS creds path creds=%p 
> filename=%s path=%s" "\n", creds, filename, path);
>       }
>   }
>
> The log and error messages before:
>
>   $ qemu-system-x86_64 -trace qcrypto* -object 
> tls-creds-x509,id=tls0,dir=$HOME/tls -msg timestamp=on
>   2986097@1753122905.917608:qcrypto_tls_creds_x509_load TLS creds x509 load 
> creds=0x55d925bd9490 dir=/var/home/berrange/tls
>   2986097@1753122905.917621:qcrypto_tls_creds_get_path TLS creds path 
> creds=0x55d925bd9490 filename=ca-cert.pem path=<none>
>   2025-07-21T18:35:05.917626Z qemu-system-x86_64: Unable to access 
> credentials /var/home/berrange/tls/ca-cert.pem: No such file or directory
>
> and after:
>
>   $ qemu-system-x86_64 -trace qcrypto* -object 
> tls-creds-x509,id=tls0,dir=$HOME/tls -msg timestamp=on
>   2025-07-21T18:43:28.089797Z qcrypto_tls_creds_x509_load TLS creds x509 load 
> creds=0x55bf5bf12380 dir=/var/home/berrange/tls
>   2025-07-21T18:43:28.089815Z qcrypto_tls_creds_get_path TLS creds path 
> creds=0x55bf5bf12380 filename=ca-cert.pem path=<none>
>   2025-07-21T18:43:28.089819Z qemu-system-x86_64: Unable to access 
> credentials /var/home/berrange/tls/ca-cert.pem: No such file or directory
>
> The binary size before:
>
>   $ ls -alh qemu-system-x86_64
>   -rwxr-xr-x. 1 berrange berrange 87M Jul 21 19:39 qemu-system-x86_64
>   $ strip qemu-system-x86_64
>   $ ls -alh qemu-system-x86_64
>   -rwxr-xr-x. 1 berrange berrange 30M Jul 21 19:39 qemu-system-x86_64
>
> and after:
>
>   $ ls -alh qemu-system-x86_64
>   -rwxr-xr-x. 1 berrange berrange 85M Jul 21 19:41 qemu-system-x86_64
>   $ strip qemu-system-x86_64
>   $ ls -alh qemu-system-x86_64
>   -rwxr-xr-x. 1 berrange berrange 29M Jul 21 19:41 qemu-system-x86_64
>
> Signed-off-by: Daniel P. Berrangé <berra...@redhat.com>
> ---
>  scripts/tracetool/backend/log.py | 14 +-------------
>  util/log.c                       | 20 +++++++++++++++++++-
>  2 files changed, 20 insertions(+), 14 deletions(-)
>
> diff --git a/scripts/tracetool/backend/log.py 
> b/scripts/tracetool/backend/log.py
> index 17ba1cd90e..bd6739ae41 100644
> --- a/scripts/tracetool/backend/log.py
> +++ b/scripts/tracetool/backend/log.py
> @@ -20,7 +20,6 @@
>  
>  def generate_h_begin(events, group):
>      out('#include "qemu/log-for-trace.h"',
> -        '#include "qemu/error-report.h"',
>          '')
>  
>  
> @@ -36,20 +35,9 @@ def generate_h(event, group):
>          cond = "trace_event_get_state(%s)" % ("TRACE_" + event.name.upper())
>  
>      out('    if (%(cond)s && qemu_loglevel_mask(LOG_TRACE)) {',
> -        '        if (message_with_timestamp) {',
> -        '            struct timeval _now;',
> -        '            gettimeofday(&_now, NULL);',
>          '#line %(event_lineno)d "%(event_filename)s"',
> -        '            qemu_log("%%d@%%zu.%%06zu:%(name)s " %(fmt)s "\\n",',
> -        '                     qemu_get_thread_id(),',
> -        '                     (size_t)_now.tv_sec, (size_t)_now.tv_usec',
> -        '                     %(argnames)s);',
> +        '        qemu_log("%(name)s " %(fmt)s "\\n"%(argnames)s);',
>          '#line %(out_next_lineno)d "%(out_filename)s"',
> -        '        } else {',
> -        '#line %(event_lineno)d "%(event_filename)s"',
> -        '            qemu_log("%(name)s " %(fmt)s "\\n"%(argnames)s);',
> -        '#line %(out_next_lineno)d "%(out_filename)s"',
> -        '        }',
>          '    }',
>          cond=cond,
>          event_lineno=event.lineno,
> diff --git a/util/log.c b/util/log.c
> index 58d24de48a..abdcb6b311 100644
> --- a/util/log.c
> +++ b/util/log.c
> @@ -145,10 +145,28 @@ void qemu_log_unlock(FILE *logfile)
>  
>  void qemu_log(const char *fmt, ...)
>  {
> -    FILE *f = qemu_log_trylock();
> +    FILE *f;
> +    g_autofree const char *timestr = NULL;
> +
> +    /*
> +     * Prepare the timestamp *outside* the logging
> +     * lock so it better reflects when the message
> +     * was emitted if we are delayed acquiring the
> +     * mutex
> +     */
> +    if (message_with_timestamp) {
> +        g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
> +        timestr = g_date_time_format_iso8601(dt);
> +    }

Duplicates real_time_iso8601() from error-report.c.  Tolerable.

> +
> +    f = qemu_log_trylock();
>      if (f) {
>          va_list ap;
>  
> +        if (timestr) {
> +            fprintf(f, "%s ", timestr);
> +        }
> +
>          va_start(ap, fmt);
>          vfprintf(f, fmt, ap);
>          va_end(ap);

Reviewed-by: Markus Armbruster <arm...@redhat.com>


Reply via email to