How to Enable and Utilize qlog for Debugging XQUIC Connections

XQUIC provides a built-in qlog subsystem that records QUIC protocol events in JSON format; enable it via runtime flags or API configuration, then convert logs using the provided Python parser for visualization.

The qlog framework in alibaba/xquic allows developers to capture detailed, timestamped traces of QUIC connections for offline analysis. Because the subsystem is compiled into the library by default, you only need to configure the importance level and output destination at runtime to start debugging XQUIC connections with qlog.

Understanding XQUIC's qlog Architecture

The qlog implementation centers on a central logger object that filters events by importance before dispatching them to user-defined callbacks.

Core Components

Component Role Source File
xqc_log_t Central logger holding the Source Connection ID (SCID), importance threshold, and callback pointers. src/common/xqc_log.c
xqc_qlog_implement() Formats events, applies importance filtering, and routes output to either the generic error log or the qlog-specific callback. src/common/xqc_log.c
xqc_log_event_callback.c Defines per-event callbacks (e.g., connection start, packet sent, stream state change) that invoke xqc_qlog_implement. src/common/xqc_log_event_callback.c
Engine configuration Stores cfg_qlog_importance; default is EVENT_IMPORTANCE_EXTRA. src/transport/xqc_engine.c

Event Importance Levels

XQUIC uses a character-based scheme to control verbosity. The filter is applied inside xqc_qlog_implement() (lines 38-46 of xqc_log.c), where events below the configured threshold are discarded.

Character Macro Description
s EVENT_IMPORTANCE_SELECTED Only user-selected events.
c EVENT_IMPORTANCE_CORE Core protocol events (handshake, loss detection).
b EVENT_IMPORTANCE_BASE Base lifecycle events (connection open/close).
e EVENT_IMPORTANCE_EXTRA Extra diagnostics (buffer states, stream flow control).
r EVENT_IMPOTANCE_REMOVED All possible events (no filtering).

Enabling qlog via Command Line

The test binaries (test_client and test_server) provide command-line switches to control qlog output without modifying source code.

Server Configuration

Start the server with an importance level to capture connection traces:

./tests/test_server \
    -a 0.0.0.0 \
    -p 4433 \
    --qlog_importance c

By default, the server writes to ./clog (configured in tests/test_server.c at line 4140). The file contains both human-readable logs and raw qlog lines.

Client Configuration

Similarly, enable qlog on the client to trace the outgoing connection:

./tests/test_client \
    -a 127.0.0.1 \
    -p 4433 \
    --qlog_importance e

Disabling qlog

To completely suppress qlog output, use the disable flag:

./tests/test_client --qlog_disable

This sets the global log_disable flag (defined in src/common/xqc_log.c line 12) to XQC_TRUE, causing xqc_qlog_implement() to return early before any formatting occurs.

Enabling qlog Programmatically via API

For production integrations, configure qlog through the engine API before creating connections.

#include <xquic/xquic.h>

/* 1. Obtain default configuration */
xqc_config_t cfg;
xqc_engine_get_default_config(&cfg, XQC_ENGINE_CLIENT);

/* 2. Set importance level (core events only) */
cfg.cfg_qlog_importance = EVENT_IMPORTANCE_CORE;
cfg.cfg_log_event = 1;  /* Enable event logging */

/* 3. Create engine with config */
xqc_engine_t *engine;
xqc_engine_create(&engine, XQC_ENGINE_CLIENT, &cfg, ...);

/* 4. Register a custom qlog writer callback */
static ssize_t my_qlog_writer(qlog_event_importance_t imp,
                              const void *buf, size_t count, 
                              void *user_data)
{
    int fd = *(int *)user_data;
    return write(fd, buf, count);
}

/* Assign callback and user data (file descriptor) */
engine->log->log_callbacks->xqc_qlog_event_write = my_qlog_writer;
int qlog_fd = open("./my_qlog.txt", O_WRONLY|O_CREAT|O_APPEND, 0644);
engine->log->log_callbacks->user_data = &qlog_fd;

With this setup, every qlog event passing the importance filter is streamed to my_qlog.txt in real-time.

Converting and Visualizing qlog Output

Raw qlog data written by XQUIC is not immediately valid JSON; it must be converted using the provided parser.

Converting Raw Logs to JSON

Use the Python script located in the repository:

python3 scripts/qlog_parser.py ./clog > qlog.json

The parser (scripts/qlog_parser.py) reads the text-based log format and produces a standards-compliant qlog JSON object suitable for external tools.

Viewing qlog Files

Once converted, open qlog.json in a compatible viewer:

  • Chrome: Navigate to chrome://net-internals/#qlog and click "Load" to select the file.
  • Mozilla Firefox: Use about:debugging and load the qlog for analysis.
  • Third-party tools: Import into Wireshark with qlog plugins or other QUIC visualization utilities.

Summary

  • qlog is built-in: The subsystem is always compiled in src/common/xqc_log.c and requires only runtime activation.
  • Control verbosity: Set cfg_qlog_importance to s, c, b, e, or r to filter events by importance level.
  • Command-line usage: Use --qlog_importance <level> with test_client or test_server; disable with --qlog_disable.
  • API integration: Configure xqc_config_t before xqc_engine_create() and register a custom xqc_qlog_event_write callback.
  • Post-processing: Convert raw logs to JSON using scripts/qlog_parser.py before viewing in Chrome or Firefox developer tools.

Frequently Asked Questions

What is the default qlog importance level in XQUIC?

By default, XQUIC initializes cfg_qlog_importance to EVENT_IMPORTANCE_EXTRA (character e). This setting captures extra diagnostic information including packet buffer states and stream flow control updates, providing a balance between verbosity and performance.

Can I enable qlog without modifying source code?

Yes. The test binaries (test_client and test_server) support the --qlog_importance command-line flag to set the importance level at runtime. You can also disable qlog entirely using --qlog_disable. These options are parsed in tests/test_client.c (around line 4625) and tests/test_server.c (around line 2620).

How do I convert XQUIC qlog output to a viewable format?

XQUIC writes qlog data as plain text lines interleaved with other logs. To convert this to standards-compliant JSON, run the provided Python script: python3 scripts/qlog_parser.py ./clog > output.json. The resulting JSON file can be loaded into Chrome's chrome://net-internals/#qlog or Firefox's debugging tools for visualization.

Is there a performance penalty for enabling qlog?

Yes, but it is controllable. The xqc_qlog_implement() function in src/common/xqc_log.c filters events by importance before formatting, so events below the configured threshold return early with minimal overhead. However, high-importance levels like r (all events) or e (extra) will incur CPU and I/O costs from formatting and writing to disk. For production environments, use c (core) or s (selected) importance levels.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →