Skip to content

transport/pico: PicoQuicXLogSink — route picoquic internal logs through folly XLOG#256

Draft
gmarzot wants to merge 1 commit into
mainfrom
feature/picoquic-xlog-bridge
Draft

transport/pico: PicoQuicXLogSink — route picoquic internal logs through folly XLOG#256
gmarzot wants to merge 1 commit into
mainfrom
feature/picoquic-xlog-bridge

Conversation

@gmarzot

@gmarzot gmarzot commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

PoC bringing picoquic's internal C-side logging into the unified folly XLOG story (openmoq/moqx#339), so the picoquic stack participates on equal footing with mvfst once the rest of the normalization lands.

The C++ wrapper at moxygen/openmoq/transport/pico/ already uses XLOG(...) natively. What was missing was a route for picoquic's internal C-side events (per-packet, per-cnx lifecycle, drops, losses, CC, ALPN, etc.) — those flow through picoquic's picoquic_unified_logging_t abstraction and currently can only be written to text/bin/qlog files, separate from the operator's --logging= knob.

This PR adds a 4th implementation of that struct that emits XLOG(...) instead of writing to a file, plus an opt-in installer.

How it plugs in

Picoquic stores three pointers (text_log_fns, bin_log_fns, qlog_fns) in picoquic_quic_t, one per output mode. Existing setters wire them up via direct assignment, e.g. from loglib/qlog_fns.c:

int picoquic_set_qlog(picoquic_quic_t* quic, char const* qlog_dir) {
    quic->qlog_fns = &qlog_fns;
    ...
}

PicoQuicXLogSink mirrors that exactly:

void installPicoQuicXLogSink(picoquic_quic_t* quic) {
    quic->text_log_fns = const_cast<picoquic_unified_logging_t*>(&kXLogBackend);
}

kXLogBackend is a process-lifetime constant struct whose 14 fields point at extern "C" callbacks defined in the file. Each formats its event into a XLOG(...) line with the appropriate severity.

Severity mapping

event class level
log_app_message / log_quic_app_message INFO
log_new_connection / log_close_connection / log_negotiated_alpn DBG1
log_dropped_packet / log_buffered_packet / log_packet_lost DBG1
log_transport_extension / log_picotls_ticket / log_cc_dump DBG2
log_pdu / log_packet / log_outgoing_packet (per-packet) DBG3
log_quic_close no emit (just cleanup)

Operator UX:

  • --logging=quic.picoquic=INFO → lifecycle + app messages
  • --logging=quic.picoquic=DBG1 → adds drops, losses, buffered events
  • --logging=quic.picoquic=DBG3 → opens the per-packet firehose

(Category root depends on where Alan lands the quic.{mvfst,picoquic} discussion in #339; this PR doesn't pick it — categories derive from __FILE__ per the standard FOLLY_XLOG_STRIP_PREFIXES mechanism.)

Internal-header dependency

Reaches into picoquic_internal.h to write the text_log_fns slot — the same access pattern picoquic's own qlog backend uses. The CMake target gets ${picoquic_SOURCE_DIR}/picoquic on its include path via the BUILD_INTERFACE trick already used for picohttp.

If reviewers prefer a public picoquic API, follow-up could add picoquic_set_unified_log(quic, fns) to openmoq/picoquic — small patch.

Interaction with qlog/binlog

  • Mutually exclusive with picoquic_set_textlog — same slot (text_log_fns). Users running an XLog sink should not call picoquic_set_textlog.
  • qlog and binlog are independent — different slots; can be enabled in parallel via picoquic_set_qlog(quic, dir) / picoquic_set_binlog(quic, dir). The intended split:
    • daily ops / dev debugging → XLog (--logging=quic.picoquic=DBG2)
    • deep packet analysis → qlog (separate --qlog-dir flag, consumed by qvis)

Opt-in only

Nothing in the existing transport/server init paths is changed. Consumers (MoQPicoQuicServer, MoQPicoQuicEventBaseServer, etc.) that want the sink call installPicoQuicXLogSink(quic) after creating their picoquic context. Default behavior is unchanged.

Test plan

  • Standalone build (-DBUILD_PICOQUIC=ON) compiles the new openmoq_pico_xlog_sink target.
  • Wire up an experimental call site (e.g. in a sample) and verify events flow:
    • --logging=.=INFO shows connection-establish and ALPN lines
    • --logging=quic.picoquic=DBG3 shows per-packet output
    • --logging=quic.picoquic=WARN is quiet during steady state
  • Run alongside picoquic_set_qlog(quic, "/tmp/qlogs") — confirm qlog files still written; XLog sink output also appears in stderr.
  • Throughput: perf-test with XLog sink installed at DBG1 — no regression vs sink-not-installed baseline (async folly LoggerDB should absorb).

Refs

  • Design doc: notes/picoquic-logging-bridge.md (in openmoq/notes/)
  • Test plan: notes/logging-test-plan.md (Gate 2 covers quic.picoquic.*)
  • Master spec: Normalize logging infra moqx#339

This change is Reviewable

…rough folly XLOG

Adds a 4th picoquic_unified_logging_t implementation alongside textlog/
binlog/qlog. The struct's 14 callbacks emit XLOG(...) at appropriate
severities so picoquic's internal events become operator-controllable
via the standard --logging=quic.picoquic=... config under the unified
logging story (openmoq/moqx#339).

Installation is opt-in: callers do
  moxygen::openmoq::pico::installPicoQuicXLogSink(quic);
which assigns the static kXLogBackend struct to quic->text_log_fns,
mirroring exactly what picoquic_set_qlog does for its slot. Mutually
exclusive with picoquic_set_textlog (same slot); qlog and binlog remain
available in parallel.

Severity mapping:
  INFO  app_message hooks (deliberate app-level logs)
  DBG1  connection lifecycle, ALPN, drops, losses
  DBG2  transport params, TLS ticket, CC dump
  DBG3  per-packet (pdu in/out, decrypted/outgoing packet)

The implementation reaches into picoquic_internal.h to write the
text_log_fns slot directly (same pattern qlog_fns.c uses). CMake target
gets ${picoquic_SOURCE_DIR}/picoquic on its include path via the
BUILD_INTERFACE trick already used for picohttp.

PoC scope:
- 14 callbacks all emit minimal informative lines (cid + key fields)
- log_cc_dump emits a placeholder; richer CC snapshot can come once we
  pick stable picoquic accessors for rtt/cwnd/ssthresh.

Refs: openmoq/moxygen notes/picoquic-logging-bridge.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant