Language Page

ktrace for Swift

This page is assembled from markdown in ktools-swift. GitHub links point to the workspace repo and the relevant source files or directories.

1 markdown sections
QM-Code/ktools-swift primary repo
HTML static output

Karma Trace Logging SDK

ktools-swift/ktrace/README.md

Trace logging SDK with:

  • namespaced channel tracing via TraceLogger.trace(...)
  • always-visible operational logging via TraceLogger.info/warn/error(...)
  • a library-facing TraceLogger source object
  • an executable-facing Logger registry, filter, formatter, and output sink

Quick Start

import Kcli
import Ktrace

let logger = Logger()
let trace = try TraceLogger("core")

try trace.addChannel("app", color: try TraceColors.color("BrightCyan"))
try logger.addTraceLogger(trace)
try logger.enableChannel(trace, ".app")

let parser = Parser()
try parser.addInlineParser(logger.makeInlineParser(trace))
try parser.parseOrThrow(CommandLine.arguments)

try trace.trace("app", "core initialized")

Build SDK

Workspace-style build:

kbuild --build-latest

Direct SwiftPM flow:

cd src
swift test
swift run ktrace-demo-core --trace '*.*'

Demos

Demo directories mirror the C++ layout even though the executable products live in the SwiftPM package:

Trace CLI examples:

cd src
swift run ktrace-demo-core --trace
swift run ktrace-demo-core --trace '.*'
swift run ktrace-demo-omega --trace '*.*'
swift run ktrace-demo-omega --trace '*.*.*.*'
swift run ktrace-demo-omega --trace '*.{net,io}'
swift run ktrace-demo-omega --trace-examples
swift run ktrace-demo-omega --trace-namespaces
swift run ktrace-demo-omega --trace-channels
swift run ktrace-demo-omega --trace-colors
swift run ktrace-demo-omega --trace-files
swift run ktrace-demo-omega --trace-functions
swift run ktrace-demo-omega --trace-timestamps

API Model

TraceLogger is the namespace-bearing source object. Construct it with an explicit namespace and declare channels on it:

let trace = try TraceLogger("alpha")
try trace.addChannel("net", color: try TraceColors.color("DeepSkyBlue1"))
try trace.addChannel("cache", color: try TraceColors.color("Gold3"))

SDKs should usually expose a shared logger handle from a factory or static accessor:

enum AlphaSdk {
    static func getTraceLogger() throws -> TraceLogger {
        let trace = try TraceLogger("alpha")
        try trace.addChannel("net", color: try TraceColors.color("DeepSkyBlue1"))
        try trace.addChannel("cache", color: try TraceColors.color("Gold3"))
        return trace
    }
}

Logger is the executable-facing runtime. It imports one or more TraceLoggers, maintains the central channel registry, and owns filtering, formatting, and final output:

let logger = Logger()
let appTrace = try TraceLogger("core")

try appTrace.addChannel("app", color: try TraceColors.color("BrightCyan"))
try appTrace.addChannel("startup", color: try TraceColors.color("BrightYellow"))

try logger.addTraceLogger(appTrace)

Logging APIs

Channel-based trace output:

try trace.trace("channel", "message {}", value)
try trace.traceChanged("channel", key, "message {}", value)

Always-visible operational logging:

try trace.info("message")
try trace.warn("configuration file '{}' was not found", path)
try trace.error("fatal startup failure")

Operational logging is independent of channel enablement. It is still namespaced and uses the same formatting options as trace output.

Message formatting supports sequential {} placeholders and escaped braces {{ and }}.

CLI Integration

The inline parser is logger-bound rather than global. Pass the executable's local TraceLogger so leading-dot selectors resolve against the right namespace:

let logger = Logger()
let appTrace = try TraceLogger("core")

try appTrace.addChannel("app", color: try TraceColors.color("BrightCyan"))
try logger.addTraceLogger(appTrace)

let parser = Parser()
try parser.addInlineParser(logger.makeInlineParser(appTrace))

Channel Expression Forms

Single-selector APIs on Logger:

  • .channel[.sub[.sub]] for a local channel in the provided local namespace
  • namespace.channel[.sub[.sub]] for an explicit namespace

List APIs on Logger:

  • enableChannels(...)
  • disableChannels(...)
  • list APIs accept selector patterns such as *, {}, and CSV
  • list APIs resolve selectors against the channels currently registered at call time
  • leading-dot selectors in list APIs resolve against the provided local namespace
  • empty or whitespace selector lists are rejected
  • unregistered channels remain disabled and do not emit, even if a selector pattern would otherwise match

Examples:

  • try logger.enableChannel(appTrace, ".app")
  • try logger.enableChannel("alpha.net")
  • try logger.enableChannels("alpha.*,{beta,gamma}.net.*")
  • try logger.enableChannels(appTrace, ".net.*,otherapp.scheduler.tick")

Formatting options:

  • --trace-files
  • --trace-functions
  • --trace-timestamps

These affect both trace(...) output and info/warn/error(...) output.

Informational options:

  • --trace-examples
  • --trace-namespaces
  • --trace-channels
  • --trace-colors

Logger also registers an internal ktrace namespace for logger/runtime diagnostics, so calls such as getNamespaces() include ktrace once a Logger has been constructed.