Skip to main content

Logging

The SDK logs for itself. Every line goes to its log file on the device — always, down to debug — and the lines at or above Log.level are also printed to the console through os.Logger (subsystem com.thenoughtyfox.noughtytours), prefixed so they are yours to spot and to grep:

[NoughtyToursSDK] floor upload failed: network unavailable

One knob, and it is the whole API:

// Needs no NoughtyTours instance, so `didFinishLaunchingWithOptions` is a good place.
Log.level = .info // .debug .info .notice (default) .error .off
There is deliberately no log stream to subscribe to

A host that forwarded the SDK's lines into its own logger printed every one of them twice — once from the SDK, once from the host — which is worse than either alone. Set the level; if you need the lines as data, take the log file.

The log file

Documents/Logs/capture-runtime.log, one line per entry, ignoring Log.level entirely:

ts=1761134502.184 | sync.upload | ERROR | [bg-4f1a] floor upload failed: network unavailable

Timestamp, category, level, thread, message. It is the SDK's postmortem — attach it to a bug report and the trace is complete even if the console was quiet.

The SDK appends to it and never rotates it, so a host that keeps long-lived installs should delete it once it has collected one.

Categories

The category is the os.Logger category — so it is what you filter on in Console.app — and the second column in the log file.

LogCategoryWhat it covers
captureFlowCapture sessions starting, finishing, tearing down
captureStructureStructure capture — the floor plan being built
captureRelocalizationRelocalizing against a floor captured earlier
captureMediaCamera, video recording, motion data
syncUploadSync and background uploads — start here when a capture never arrives
authApp Attest attestation, assertion, the org-scoped bearer

Worth knowing

  • Set it before you build the SDK. The level is process-wide and needs no NoughtyTours, which is the point: uploads continue after your app is suspended and iOS may relaunch the process to finish them, so the most interesting lines are emitted before start() has returned.
  • level filters the console only. The log file always gets every line, so lowering the level costs you nothing in a bug report. .off silences the console and leaves the file untouched.
  • Writable at any time, from any thread. A change applies to the next line the SDK emits.
  • Messages are diagnostics, not API. Their wording changes between versions — never parse them, exactly as with NoughtyToursError's reason strings.
  • The capture engine keeps its own low-level output. Frame and mesh internals go straight to os.Logger and do not pass through Log; Console.app still sees them.