Skip to content

Default logs: consolidated audio sink / sample-rate summary for troubleshooting #2971

Description

@jensenpat

Summary

Add a low-noise, default-on audio troubleshooting summary to the normal log so support bundles reliably capture the actual sink/source negotiation story behind recurring audio and CW issues.

Today, many of the useful details already exist in code, but they are split across aether.audio qCDebug / qCInfo lines and therefore are not present in the default log settings. The result is that clusters of recurring reports arrive with the same missing context:

  • Which output sink actually opened?
  • Which input source actually opened?
  • What sample rate and channel count were negotiated?
  • Was resampling active?
  • Which CW sidetone backend/device/rate was used?
  • Did we fall back from one sink/backend to another?
  • Were auxiliary local sinks (e.g. Quindar / monitor playback) instantiated, and on what format?

This issue is to add that information in a way that is immediately useful for troubleshooting without making the default log noisy.

Problem

The current default log policy enables aether.discovery, aether.connection, and aether.protocol, but does not enable aether.audio info/debug logging.

That means the default log usually captures:

  • warning/error paths for audio fallback or outright failure
  • but not the normal successful sink/source negotiation path

This is a poor fit for real-world support, because many of the bugs we keep seeing are not hard failures. They are:

  • wrong sink/backend chosen
  • telephony/Bluetooth route picked unexpectedly
  • 24 kHz vs 48 kHz mismatch
  • hidden resampler path differences
  • CW sidetone on the wrong output
  • auxiliary sink using a different output profile than RX audio

In those cases, the existing default log is often missing the exact information we need.

Proposed approach

Do not simply make all existing aether.audio qCInfo(...) lines default-on.

Instead, add a consolidated summary log block that emits only at key lifecycle moments and only when the material audio-routing state changes.

Design goals

  • Default-on in the normal log
  • Low noise
  • High signal for support bundles
  • One consolidated block instead of many scattered lines
  • Covers the happy path, not only warnings/failures
  • Reuses existing diagnostics logic where practical so we have one consistent description of audio state

What to log

1. Startup / environment summary

At application startup, log a one-shot summary of the selected/default audio devices and route intentions.

Example fields:

  • selected output device description
  • default output device description
  • selected input device description
  • default input device description
  • whether the saved device is present
  • whether PC Audio is enabled
  • whether TX mic source is PC / radio / DAX

This is the static context block.

2. RX sink summary

When the RX sink is actually started, emit a summary with:

  • actual output device used
  • sink format
  • actual sample rate
  • channel count
  • sample format
  • whether resampling is enabled
  • whether we fell back from 48 kHz to 24 kHz, or substituted a sibling/default output

This captures the real PC-audio playback path.

3. TX source summary

When the TX mic source is actually started, emit a summary with:

  • actual input device used
  • negotiated sample rate
  • channel count
  • mono/stereo
  • whether resampling to radio-native 24 kHz is enabled
  • whether a fallback input format/rate was required

This captures the real TX capture path.

4. CW sidetone summary

When CW sidetone starts, emit a summary with:

  • backend (PortAudio vs QAudioSink)
  • actual output device / backend-selected device
  • actual sample rate
  • whether fallback occurred
  • any backend substitution (e.g. PortAudio failed -> Qt sink)

This is especially important because CW issue clusters frequently come down to sidetone sink choice and output routing.

5. Auxiliary local sink summary

When any auxiliary local sink actually starts, emit its own compact summary.

Examples:

  • Quindar local sink
  • any Aetherial/monitor playback sink that owns its own QAudioSink

Log only for sinks that are really instantiated at runtime.

6. Re-log only on material change

If output/input device selection changes, or a sink restarts with materially different state, emit a new summary.

Otherwise do not repeat the block.

Suggested implementation shape

Dedicated summary category

Add a dedicated logging category such as:

  • aether.audio.summary

with default severity suitable for normal logs, e.g. QtInfoMsg.

This keeps the existing aether.audio category as the detailed opt-in category while making the new summary path explicitly part of the default troubleshooting signal.

Consolidated structured message

Prefer a compact multi-line or structured one-block summary over scattered individual lines.

Example:

[INF] aether.audio.summary: Audio summary:
  output selected="USB Audio CODEC" default="MacBook Pro Speakers" rxSink=started rate=48000 format=Float resample=24k->48k fallback=no
  input selected="2-USB PnP Audio Device" default="MacBook Mic" txSource=started rate=48000 channels=2 resample=48k->24k fallback=no
  sidetone backend=QAudioSink rate=48000 fallback=no
  quindar running=no
  puduMonitor running=no

Deduping / noise control

Compute a compact canonical summary string or JSON object, hash it, and only emit when it changes.

This keeps the log readable while still surfacing the important transitions.

Reuse existing snapshot logic

DeviceDiagnostics::buildAudioDevicesSnapshot(...) already knows a lot about:

  • selected/default devices
  • supported rates/formats
  • route intentions
  • device availability

The implementation should reuse or extend this logic instead of inventing a second independent description of audio state.

Non-goals

  • Do not make the full detailed aether.audio info/debug stream default-on
  • Do not emit per-buffer or per-callback audio logs
  • Do not create a repeated heartbeat log
  • Do not duplicate support-dialog JSON snapshots verbatim on every startup if a smaller human-readable summary is sufficient

Acceptance criteria

  • The default log includes a one-shot audio routing summary at startup
  • The default log includes a consolidated RX sink summary when PC audio playback becomes active
  • The default log includes a consolidated TX source summary when PC mic capture becomes active
  • The default log includes a consolidated CW sidetone summary when the sidetone sink/backend is started
  • Auxiliary local sinks that own their own audio sink emit a concise startup summary when they are instantiated
  • Repeated summaries are suppressed unless material audio-routing state changes
  • The implementation reuses existing device diagnostics/snapshot logic where practical
  • The resulting default log is materially more useful for support bundles without becoming noisy

Likely touch points

  • src/core/LogManager.h/.cpp
  • src/core/AudioEngine.cpp
  • src/core/CwSidetoneQAudioSink.cpp
  • src/core/CwSidetonePortAudioSink.cpp
  • src/core/QuindarLocalSink.cpp
  • src/core/ClientPuduMonitor.cpp
  • src/core/DeviceDiagnostics.h/.cpp
  • possibly src/core/SupportBundle.cpp only if any category/default handling needs adjustment

Suggested labels

  • enhancement
  • audio
  • CW
  • supportability

73

Metadata

Metadata

Assignees

Labels

CWCW keying, decode, and operationaudioAudio engine and streamingenhancementImprovement to existing featuremaintainer-reviewRequires maintainer review before any action is takenpriority: mediumMedium priority

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions