Releases: MoElnaggar14/SwiftMoLogger
Release list
SwiftMoLogger 4.4.0
#log accepts per-value privacy, and the async LogContext.with and TraceContext.run no longer warn on Swift 6.4. Additive; no API changes for existing callers.
Added
#logaccepts per-value privacy.#log(logger, "Signed in \(email, privacy: .private)")logsSigned in <private>, and#log(logger, message)takes aLogMessagevalue. A second#logdeclaration takes aLogMessage; both expand to the samelogger.log(…)call, so theMoLoggeroverloads build the message exactly as a direct call does. Plain literals,Stringvalues and messages typed from context still resolve to theStringform. (#45)
Fixed
- Swift 6.4 no longer warns that
LogContext.withuses a deprecatedTaskLocal.withValueoverload. With Swift 6.4, the asyncLogContext.with(_:operation:)andTraceContext.run(_:)arenonisolated(nonsending): the operation runs on the caller's executor, so a main-actor caller stays on the main actor inside the scope. Older toolchains are unchanged. (#44)
Install
.package(url: "https://github.com/MoElnaggar14/SwiftMoLogger.git", from: "4.4.0")SwiftMoLogger 4.3.0
Per-value privacy in log messages, opt-in network bodies with Copy as cURL, and MetricKit metric payloads with every diagnostic kind. Additive; no API changes.
Added
- Per-value privacy. Mark one value in a message instead of hiding the whole message, as with
os.Logger:log.info("Signed in \(email, privacy: .private)")logsSigned in <private>.LogPrivacyhas.public,.private,.sensitive(never revealed) and a.hashmask for a stable<hash:…>. Values are replaced before theLogEntryis created, so no engine sees them;registry.revealsPrivateValues = trueshows.privatevalues in DEBUG builds. TheLogMessageoverloads sit alongside theStringones, so existing call sites are unchanged, and filtered calls still don't build the message. (#21) - Network bodies and cURL export.
NetworkLogger(…, bodies: .debugOnly(maxBytes:))captures request bodies (fromhttpBody) and response bodies (fromurlSession(_:dataTask:didReceive:)) intoNetworkEvent.requestBody/responseBody. Capture is off by default,.debugOnlycaptures nothing in release builds, and.always(maxBytes:)is the explicit opt-in for every build. Bodies go through aRedactor, are cut atmaxBytesand marked as truncated, are kept only for text content types, and never go into log entries.NetworkEvent.requestHeadersrecords the redacted headers, andNetworkEvent.curlCommandbuilds a shell-quotedcurlcommand from the redacted URL, headers and body. The Hub's request detail shows headers and bodies and has a Copy as cURL button where the platform has a pasteboard.NetworkLoggeris now aURLSessionDataDelegate; with capture off, the new callback returns at once. (#13) - MetricKit metric payloads. On iOS,
MetricKitCrashReporternow logs each dailyMXMetricPayloadas one.infoentry tagged.performance: time to first draw (plus prewarmed launches), resume time and hang time as count, average, p50 and p95 from MetricKit's histograms, peak and average suspended memory, disk writes, CPU time, memory-limit and jetsam exits, the app version and the period the payload covers. (#17) - More diagnostics. CPU exceptions, disk-write exceptions and app-launch diagnostics (iOS 16 / macOS 13) are logged as
.warningentries tagged.performance, next to crashes and hangs. Crash entries add the exception and signal names, the termination reason, an uncaught Objective-C exception's name and message (iOS 17), a hint and the binaries on the crashing thread. (#17) MetricPayloadSummaryandDiagnosticPayloadSummaryparse a payload'sjsonRepresentation(), andMetricKitPayloadLoggerlogs them, so payloads recorded on a device can be replayed in tests without buildingMXobjects. Durations are in milliseconds and sizes in bytes. (#17)MetricPayloadSource, the port the reporter reads payloads from.MXMetricManagerPayloadSourceis the default;MetricKitCrashReporter(logger:source:)takes any other, such as a replay of recorded JSON. (#17)
Changed
- Crash pattern hints and the binaries on the crashing thread are now metadata (
hint,binaries) on the crash entry, instead of separate log entries. Binaries come from the attributed thread's whole call stack, not just its root frames. (#17) - With a custom source,
crashReportDelegateandhangReportDelegatearen't called, because they take MetricKit objects that a JSON source doesn't have. The default source calls them as before.
Notes
- The iOS 27
MetricManagerAPI isn't adopted yet. The reporter doesn't use the async API yet: its exact Swift shape couldn't be checked against the iOS 27 SDK, and a guessed signature would break the Xcode 27 build. It will be added as anotherMetricPayloadSource, behind#if compiler(>=6.4)and@available(iOS 27, *), so the reporter, the summaries and the logged entries stay the same.MXMetricManagerremains the source until then.
Install
.package(url: "https://github.com/MoElnaggar14/SwiftMoLogger.git", from: "4.3.0")SwiftMoLogger 4.2.0
Runtime control and better evidence: per-tag log levels you can drive from remote config, Swift task names on every entry, the system log in bug reports, and recorded logs attached to failing Swift Testing tests. Additive; no API changes.
Added
- Task names.
LogEntry.taskNamerecords the name of the Swift task that logged the entry (Task(name:), SE-0469; Swift 6.2 with iOS 26 / macOS 26 and later). The console, the Hub andswiftmologger-inspectorshow it next to the thread, OTLP sendsswift.task.nameand Datadogtask. It's optional, so files written by 4.0 still decode, and Swift 6.1 builds leave itnil. (#15) - Per-tag minimum levels.
registry.setMinimumLevel(.trace, for: .Data.database)turns on verbose logs for one area, and.errorquiets a noisy one, without changing the level everywhere. Overrides match a tag domain and everything below it, the most specific wins, andregistry.levelOverrides = LevelOverrides(levels)replaces them all at once, for example from remote config (LogLevel(name:)parses level names). Filtered calls still return before the message is built. (#18) - System log in bug reports.
BugReporter(…, systemLog: SystemLogOptions(window: 600))adds the app's recent unified-log entries (os_logandLogger, where Apple frameworks and SDKs log) assystem-log.txt. Entries go through the redactor, the file keeps the newest entries within 1 MB, and an unreadable log is noted instead of failing the report.SystemLogSourcelets tests inject entries. (#20) - Recorded logs as test attachments.
RecordingLogEngine.attach(named:)adds the recorded entries to the current Swift Testing test as a text file, one line per entry with time, level, tag, metadata and source location. Call it in adefer, and a failing test's report shows what was logged. Requires Swift 6.2 or later; the package still builds with Swift 6.1, without the method. (#14)
Fixed
- Two bug reports generated in the same second no longer share a directory, where one could overwrite or delete the other's files. Report directories now end in a short unique suffix.
Install
.package(url: "https://github.com/MoElnaggar14/SwiftMoLogger.git", from: "4.2.0")SwiftMoLogger 4.1.0
Agents, OpenTelemetry and crash reporters: an MCP server that lets AI coding agents read a running app's logs, an OTLP exporter with trace correlation, a forwarding engine for Crashlytics and other SDKs, and data protection for log files. Additive; no API changes.
Added
swiftmologger-mcp, an MCP server inTools/swiftmologger-mcp, lets AI coding agents (Claude Code, Codex, Cursor) read the live logs of debug builds runningLiveSinkon the local network. Five read-only tools:list_devices,search_logs,get_entry,wait_forandnetwork_requests. Entries are redacted before the agent sees them, andSWIFTMOLOGGER_MCP_APPSlimits which apps it reads. It's a separate package, so apps never resolve the MCP SDK.OTLPLogEngineinSwiftMoLoggerRemoteexports to any OpenTelemetry logs endpoint over OTLP/HTTP JSON (Collector, Grafana, Honeycomb, Datadog, New Relic). Levels map to OpenTelemetry severity numbers; metadata, the tag, the source location and the thread name become attributes; entries logged inside aTraceContextcarry itstraceIdandspanId. No protobuf dependency. (#16)- File protection.
FileLogEngine(…, protection:)sets a data-protection class on every log file it creates, including rotated files and a file left by an earlier version. The default,.completeUntilFirstUserAuthentication, keeps background logging working;.completeUnlessOpenmakes logs unreadable while the device is locked without stopping writes. Ignored on macOS. (#19) ForwardingLogEnginehands entries to a closure, with an optional level, filter and flush hook. It's the bridge to SDKs the package doesn't depend on: Firebase Crashlytics, Bugsnag, Embrace, or an analytics SDK for selected events. The README has recipes and explains why vendor SDKs stay out of the package.
Fixed
- Release notes on GitHub link to
MIGRATION.mdand other repository files at the released tag, instead of relative links that didn't resolve.
Documentation
- Article 5 covers
flush(): why buffered engines lose their last batch when iOS terminates a suspended app, and flushing the registry onscenePhase == .background.
Install
.package(url: "https://github.com/MoElnaggar14/SwiftMoLogger.git", from: "4.1.0")SwiftMoLogger 4.0.0
Dependency injection everywhere: SwiftMoLogger no longer has any singletons or
global state. See MIGRATION.md for the full API map.
Breaking
- Safe by default, crash-free on bad input.
SystemLoggerdefaults toprivacy: .privateInRelease(messages show as<private>in release builds' unified log).TraceContext(traceID:spanID:),SentryLogEngine(dsn:)andWebSocketTailEngine(url:)are failable instead of trapping on malformed input, which often comes from headers or remote config. - Swift 6. Library targets compile in the Swift 6 language mode, with full data-race checking. Requires Xcode 16 or later (swift-tools-version 6.0).
- Removed the static
SwiftMoLogger.*facade and every.sharedinstance (EngineRegistry,MoLogger,BreadcrumbStore,NetworkEventStore,SignpostEventStore,VitalsHistoryStore,LogStream,CombineLogPublisher,AppVitalsMonitor). LogSignpostreplaced by the injectableSignposter;LogTaggedreplaced byMoLogger.with(tag:).- Network capture is now
NetworkLogger, aURLSessionTaskDelegateyou inject. TheURLProtocol-based capture is gone because the system instantiates those objects and they can't receive dependencies. - Components take their collaborators in their initializers:
FlightRecorder,MetricKitCrashReporter,AppVitalsMonitor,BugReporter,LiveSink,HubViewModel/DiagnosticsHubView,LogConsoleViewModel/LogConsoleView,SwiftMoLogHandler. - Macros take their dependency explicitly:
#log(logger, …),#measure(signposter, …).@AutoLoguses the type'sloggerproperty.
Added
- LiveSink line protocol version 2. The 4.0 entry format differs from 3.x (
tagis an object, timestamps have fractional seconds), but the banner still said version 1. The first line is now a"kind": "hello"message withversion: 2,app_version,osandconnected_at. Lines with akindare control messages that clients skip when unknown, so later versions can add message types without breaking anything. The inspector warns when a device speaks a different version.LiveSink.protocolVersionexposes the version. flush()on every engine andEngineRegistry.flush().FileLogEngineand the remote shippers write or send what they buffer, and decorators forward the call. The protocol requirement has a do-nothing default, so existing engines still compile. Call it when the app moves to the background; the example app does.- visionOS 1+ is a supported platform, and CI builds for it.
- The README compares SwiftMoLogger with Pulse: Pulse wins on network request and response bodies.
SwiftMoLoggerTestingre-exportsSwiftMoLogger, soimport SwiftMoLoggerTestingis enough in a test file.- Agent skill for Claude Code (installable as a plugin) and Codex:
plugin/skills/swiftmologger. It teaches AI coding agents the 4.0 setup, which engines belong in debug and which in release, redaction, debug-onlyLiveSink, testing and the 3.x migration. It includesaudit_logging.py, which lists 3.x calls and release-safety issues and also runs in CI.AGENTS.mdcovers contributors. - Swift Testing support.
RecordingLogEnginegainsentries(…),contains(…)andcount(…)queries (filter by level, substring, tag domain and metadata key) that work with#expectas well as XCTest. The XCTest assertions now use them. URLRedactionforNetworkLogger: URLs in log entries, breadcrumbs and network events dropuser:password@and redact secret query values (token,code,api_key,signature, …) by default..withoutQueryand.fullare also available.LogEnvironment: the composition root (registry, bound logger, live stream, diagnostics stores, signposter).LogContext.with(_:operation:)andTraceContext.run(_:)for task-local scoping.URLRequest.addTraceparentHeader().LogEnvironment.recording()/MoLogger.recording()for isolated, parallel-safe tests.FlightRecorder(redactor:): redacts entries before they're persisted, so the crash file never holds raw secrets or PII.FlightRecorder(defaults:)/recoverLastSession(from:defaults:), so tests and app groups can supply their ownUserDefaults.- Diagnostics Hub accessibility. The timeline, network waterfall, flame graph and vitals charts have VoiceOver labels and values (the timeline is adjustable), fixed font sizes are replaced with Dynamic Type text styles, and failed requests and slow spans get a warning symbol so status isn't shown by colour alone; see ACCESSIBILITY.md.
Fixed (found in review of the 4.0 changes)
AppVitalsMonitorleaked and drained battery. Its display link retained the monitor (so it lived untilstop()), ran at 120 Hz on ProMotion screens, and switched on app-wide battery monitoring for good. It now uses a weak proxy, caps the link at 60 Hz (FPS is measured against 60), restores the battery-monitoring setting after each read, and cleans up on release.LiveSinkcould ship.start()does nothing in non-DEBUG builds unless you passallowInRelease: true, because it streams every log line unencrypted to the local network.- Metadata literals with a repeated key keep the last value instead of trapping, and
MemoryLogEngine.recent(_:)with a negative count returns nothing instead of trapping. - The article series used the 3.x API. All five articles are rewritten for 4.0 and checked against the source.
- Network failures logged the full failing URL. The error description was
String(describing:)of theURLError, whose userInfo holds the unredacted URL. - Requests weren't logged on the per-task delegate path. With
session.data(for:delegate:), the request was never logged; it's now logged together with the outcome. FlightRecorder(redactor:)only redacted entries. It now also redacts breadcrumbs and network-event errors, and drops URL query strings.registry.reset()disconnectedLogEnvironment.stream. The stream is now a persistent engine (EngineRegistry.addPersistentEngine(_:)), so it survives a reset.
Changed
SwiftMoLogHandlerimplements swift-log'slog(event:)(swift-log 1.12+), and errors passed to swift-log becomeerror_type/errormetadata.- CI builds the example app.
HTTPLogShipperuses its own ephemeralURLSessionby default (no cookies or cache; never observed by aNetworkLogger).
Install
.package(url: "https://github.com/MoElnaggar14/SwiftMoLogger.git", from: "4.0.0")SwiftMoLogger 3.0.0
SwiftMoLogger 3.0.0 — complete rewrite around structured LogEntry, Swift Concurrency, and a multi-product architecture.
Re-issued from a fresh
3.0.0commit onmainthat bundles the v3.0.0 feature set with a few library fixes surfaced while wiring the end-to-end example app.
✨ Highlights
- Structured
LogEntryeverywhere — level, tag, metadata, source location, timestamp. - Multi-engine fan-out: Memory + System + File + Remote + custom.
SamplingLogEngine+RateLimitingLogEnginedecorators for field-device sanity.RedactingLogEngine— regex PII scrubber on emails, tokens, card numbers.ErrorGroupingEngine— identical-shape errors collapse into a fingerprinted group.- Sentry-compatible breadcrumbs ring buffer.
LogSignpost.measurespans +#log/#measure/@AutoLogmacros viaSwiftMoLoggerSugar.- W3C distributed tracing —
TraceContext+traceparentinjection throughSwiftMoLoggerNetwork. DiagnosticsHubView— live SwiftUI hub: timeline, network waterfall, signpost flame graph, vitals charts, breadcrumbs.FlightRecorder— rolling 2-minute black box for post-crash forensics.AppVitalsMonitor— periodic memory / CPU / FPS / thermal / battery.BugReporter— one-call bundle of logs + breadcrumbs + vitals + device info, ready forShareLink.LiveSink+swiftmologger-inspectorCLI — Bonjour log tail for DEBUG builds.MetricKitCrashReporter— mirror MetricKit crash + hang payloads into the pipeline.- Remote shippers: Sentry envelopes, Datadog logs API, Grafana Loki push.
- Testing helpers:
XCTAssertLogged+RecordingLogEngine. - Ships
PrivacyInfo.xcprivacy.
🔧 Library fixes folded into this 3.0.0 cut
FlightRecorder.defaultFileURLis nowpublic(was internal but referenced as a public default arg — caused a compile error on adopters).FlightRecorder.start()always registers its own memory engine instead of silently skipping when anyMemoryLogEnginewas already in the registry.MetricKitCrashReporterupdated for iOS 17+ SDK whereMXHangDiagnostic.hangDurationis now aMeasurement<UnitDuration>.LogConsoleViewModel.entriesrelaxed tointernal(set)so@testableconsumers can seed entries.FlightRecorderTestsreset global state insetUp.Package.swiftplatforms now declare iOS 16 / macOS 13 / tvOS 16 / watchOS 9 (the UI module already used iOS-16-only APIs unguarded).
📦 Products
SwiftMoLogger— core API + enginesSwiftMoLoggerUI— Console + Diagnostics HubSwiftMoLoggerNetwork— auto URLSession captureSwiftMoLoggerDiagnostics— vitals, bug report, LiveSink, WebSocket tailSwiftMoLoggerSugar—#log/#measure/@AutoLogmacrosSwiftMoLoggerRemote— Sentry / Datadog / Loki shippersSwiftMoLoggerTesting— XCTest helpersswiftmologger-inspector— macOS CLI Bonjour log tail
📱 End-to-end showcase
ExampleApp/SwiftMoLoggerExample now exercises every product in 6 tabs (Demo / Console / Hub / Network / Diagnostics / About). Open the project, ⌘R, and you'll see the entire v3 surface in motion.
📥 Install
.package(url: "https://github.com/MoElnaggar14/SwiftMoLogger.git", from: "3.0.0")
⚠️ Note for adopters who already pinned3.0.0: the tag was rewritten to point at this fresh commit. Runswift package resolve(or File → Packages → Reset Package Caches in Xcode) to pick up the new hash.
SwiftMoLogger v2.0.0: Complete iOS Integration & Advanced Multi-Engine Architecture
🎉 Major Release - Production-Ready iOS Logging Solution
This major release transforms SwiftMoLogger into a comprehensive iOS development solution with advanced multi-engine architecture and production-ready features.
🆕 What's New in Version 2.0
📱 Complete iOS SwiftUI Example App
- Ready-to-Run Xcode Project: Complete
.xcodeprojwith pre-configured SwiftMoLogger dependency - Native SwiftUI Interface: Professional design with modern SwiftUI patterns
- Interactive Logging Demos: Buttons to test all engine features and scenarios
- Real-Time Analytics Dashboard: Live engine statistics and logging metrics
- iOS 15+ Compatibility: Version-specific optimizations and features
🏗️ Advanced Multi-Engine Architecture
- 6 Production Engines: Console, File, Network, Analytics, Debug, Memory
- Production Configurations: Proper DEBUG/RELEASE patterns demonstrated
- Thread-Safe Operations: Concurrent queue with barrier writes
- Background Processing: Optimal performance without UI blocking
- Intelligent Batching: Smart network logging with retry logic
📄 Native Document Viewer
- iOS-Optimized Viewer: SwiftUI implementation with native feel
- Smart Share Functionality: ShareLink (iOS 16+) with UIActivityViewController fallback
- Memory Efficient: Shows last 100 lines for large log files
- Error Handling: Proper loading states and user feedback
- Monospaced Font: Better log readability and formatting
🛠️ Technical Improvements
iOS Integration Excellence
- Complete Xcode project structure with proper organization
- Asset catalogs and app icons pre-configured
- Helper scripts for easy project setup (
open_project.sh) - Professional SwiftUI view components
- State management with ObservableObject patterns
DocumentViewer Enhancements
- Replaced deprecated
UIApplication.shared.windowsusage - Native SwiftUI implementation replacing
UIDocumentInteractionController - Proper iOS version compatibility handling
- Enhanced error handling and user feedback
- Native navigation patterns and UI consistency
Architecture Improvements
- Advanced engine implementations with production features
- JSON logging with structured data format
- Automatic file rotation and cleanup (1MB threshold)
- Network batching with app metadata
- Real-time analytics and metrics collection
📚 Quick Start
Zero-Friction Setup
# Clone and run in 3 commands!
git clone https://github.com/MoElnaggar14/SwiftMoLogger.git
cd SwiftMoLogger
open ExampleApp/SwiftMoLoggerExample.xcodeprojSwift Package Manager
dependencies: [
.package(url: "https://github.com/MoElnaggar14/SwiftMoLogger.git", from: "2.0.0")
]Basic Usage
import SwiftMoLogger
// Works immediately with SystemLogger
SwiftMoLogger.info("🚀 App started successfully")
SwiftMoLogger.warn("⚠️ Low memory warning", tag: .system)
SwiftMoLogger.error("❌ Network error", tag: .network)
// Add advanced engines for production
SwiftMoLogger.addEngine(FileLogEngine())
SwiftMoLogger.addEngine(NetworkLogEngine())
SwiftMoLogger.addEngine(AnalyticsLogEngine())
// Now logs go to all engines automatically
SwiftMoLogger.info("This goes everywhere!") // Console + File + Network + Analytics🎯 Impact
This release transforms SwiftMoLogger from a solid logging framework into a complete iOS development solution with:
✅ Production-ready examples in real iOS context
✅ Advanced architecture patterns for scalable logging
✅ Native iOS integration with modern SwiftUI
✅ Comprehensive documentation for immediate adoption
✅ Zero-friction setup for instant evaluation
Ready for production iOS applications with comprehensive logging capabilities! 🚀
SwiftMoLogger v1.0.0 🎉
We're excited to announce the first major release of SwiftMoLogger - a comprehensive, scalable logging framework for iOS applications with built-in crash reporting using Apple's MetricKit.
✨ Key Features
🪵 Comprehensive Logging System
- Multi-level logging: Info, Warning, Error with emoji indicators
- 40+ organized tags: Structured by domain (Network, UI, Security, etc.)
- Protocol-based logging: Automatic context with
LogTagged - Namespace organization: IDE-friendly tag discovery
- Debug logging: Development-only logs
🔍 MetricKit Integration
- System-level crash reporting: Captures crashes traditional reporters miss
- Detailed crash analysis: Signal interpretation and pattern detection
- Call stack analysis: Focus on user/third-party code
- Automatic categorization: Common crash patterns identified
- iOS version optimized: Immediate delivery on iOS 15+
🏗️ Developer Experience
- Zero dependencies: Lightweight and fast
- Modern Swift: iOS 15+ with clean APIs
- Extensible architecture: Pluggable logging engines
- Comprehensive documentation: Examples and best practices
- 99% SwiftLint compliant: High code quality
🚀 Quick Start
// Add to Package.swift
dependencies: [
.package(url: "https://github.com/MoElnaggar14/SwiftMoLogger.git", from: "1.0.0")
]
// Basic usage
import SwiftMoLogger
SwiftMoLogger.info(message: "App started successfully")
SwiftMoLogger.warn(message: "Low memory warning")
SwiftMoLogger.error(message: "Failed to load data")
// Tagged logging
SwiftMoLogger.info(message: "API request started", tag: LogTag.Network.api)
SwiftMoLogger.error(message: "Database error", tag: LogTag.Data.database)📋 Requirements
- iOS 15.0+ / macOS 12.0+ / tvOS 15.0+ / watchOS 8.0+
- Swift 5.7+
- Xcode 14.0+
🎯 What's Included
- ✅ 99% SwiftLint compliant (92/93 violations fixed)
- ✅ Comprehensive CI/CD pipeline with GitHub Actions
- ✅ Full test coverage (8/8 tests passing)
- ✅ Detailed documentation with examples
- ✅ MetricKit crash reporting integration
- ✅ Production-ready code quality
👨💻 Created By
Mohammed Elnaggar (@MoElnaggar14)
⭐ *Please star this repo if you find it helpfulauth refresh -s repo ⭐