Table of Contents
- 1. Why Xcode Organizer Is Not Enough
- 2. Installing the Logtrics iOS SDK via Swift Package Manager
- 3. Initializing Logtrics in AppDelegate or SwiftUI App
- 4. dSYM Files: What They Are and How to Upload Them
- 5. Automating dSYM Upload in CI
- 6. Capturing Non-Fatal Errors
- 7. Setting User Context
- 8. Screen Tracking
- 9. Remote Logging in Swift
- 10. Configuring Real-Time Alerts
- 11. Best Practices
- 12. FAQ
1. Why Xcode Organizer Is Not Enough
Every iOS developer knows Xcode Organizer's Crashes section. It seems like the obvious place to look for production crashes. But Xcode Organizer has fundamental limitations that make it unsuitable as your sole crash reporting solution.
Only opt-in users are included
Xcode Organizer only receives crash reports from users who have opted in to sharing diagnostics with developers. Studies suggest fewer than 30% of iOS users have this enabled. This means you are seeing a fraction of your actual crashes, and the subset may not be representative of your user base.
Hours of delay
Crashes appear in Xcode Organizer with a multi-hour delay — often 6 to 12 hours after they occur. For a high-volume production app, this means a critical crash can affect thousands of users before you even know it exists. Real-time crash reporting with Logtrics sends you an alert within seconds of the first occurrence.
No pre-crash log context
Xcode Organizer shows only the crash stack trace. It has no concept of what the user was doing, what API calls were made, or what state the app was in. Without this context, determining root cause requires guesswork and hours of code review.
No custom error capture
You cannot record non-fatal errors, custom events, or structured context in Xcode Organizer. If a payment fails, a data migration throws, or a critical feature path encounters an unexpected condition — none of that is visible unless it results in a hard crash.
No alerting
There is no way to receive a Slack or email notification when a new crash occurs. You must manually open Xcode Organizer, check the Crashes tab, and notice the new issue yourself.
2. Installing the Logtrics iOS SDK via Swift Package Manager
The Logtrics iOS SDK is distributed via Swift Package Manager. No CocoaPods or Carthage configuration is required.
Option A: Xcode UI
- 1 Open your project in Xcode
- 2 Go to File → Add Package Dependencies
- 3 Enter the Logtrics package URL in the search bar
- 4 Select your target and click Add Package
// Package URL
https://github.com/logtrics/logtrics-ios-sdk
Option B: Package.swift
// Package.swift
dependencies: [
.package(
url: "https://github.com/logtrics/logtrics-ios-sdk",
from: "2.0.0"
)
],
targets: [
.target(
name: "YourApp",
dependencies: ["Logtrics"]
)
]
3. Initializing Logtrics in AppDelegate or SwiftUI App
Initialize Logtrics as early as possible in your app's lifecycle. For UIKit apps, this is in AppDelegate.application(_:didFinishLaunchingWithOptions:). For SwiftUI apps, it is in your @main App struct init.
UIKit — AppDelegate.swift
import
UIKit
import
Logtrics
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Initialize Logtrics — first line in didFinishLaunching
Logtrics.configure(apiKey: "YOUR_API_KEY")
return true
}
}
SwiftUI — MyApp.swift
import
SwiftUI
import
Logtrics
@main
struct MyApp: App {
init() {
// Initialize before any views render
Logtrics.configure(apiKey: "YOUR_API_KEY")
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Security note: Never commit your API key directly to source control. Use Xcode build settings (Info.plist with a build setting reference), a secrets manager, or environment variables passed at build time in CI. Retrieve it at runtime with Bundle.main.object(forInfoDictionaryKey: "LOGTRICS_API_KEY") as? String.
4. dSYM Files: What They Are and How to Upload Them
A dSYM (debug symbol file) is the key to readable iOS crash reports. When Xcode builds your app for release, it compiles Swift to machine code and strips the debug information from the binary to reduce size. The debug information — including your file names, function names, and line numbers — is stored separately in a .dSYM bundle.
Enabling dSYM generation
Ensure your Release build configuration generates dSYMs. In Xcode Build Settings, search for "Debug Information Format" and set the Release configuration to "DWARF with dSYM File".
// Xcode Build Setting
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
Manual upload via Xcode Build Phase
Add a Run Script phase to your target that fires after each archive build. This automatically uploads the dSYM every time you create an archive for TestFlight or App Store distribution.
In Xcode, go to your target → Build Phases → + → New Run Script Phase. Add it after the "Copy Bundle Resources" step:
#!/bin/bash
# Upload dSYM to Logtrics after archive
if [ "${CONFIGURATION}" == "Release" ]; then
logtrics-cli upload-dsym \
--api-key "${LOGTRICS_API_KEY}" \
--bundle-id "${PRODUCT_BUNDLE_IDENTIFIER}" \
--version "${MARKETING_VERSION}" \
--build "${CURRENT_PROJECT_VERSION}" \
--path "${DWARF_DSYM_FOLDER_PATH}"
fi
5. Automating dSYM Upload in CI
For teams using CI/CD pipelines (GitHub Actions, Bitrise, CircleCI, Fastlane), automating dSYM upload ensures no release ever ships without symbolication configured.
GitHub Actions Example
# .github/workflows/release.yml
- name: Upload dSYMs to Logtrics
env:
LOGTRICS_API_KEY: ${{ secrets.LOGTRICS_API_KEY }}
run: |
logtrics-cli upload-dsym \
--api-key "$LOGTRICS_API_KEY" \
--path ./build/MyApp.xcarchive/dSYMs
Fastlane Lane
# Fastfile
lane :upload_symbols do
sh(
"logtrics-cli upload-dsym",
"--api-key #{ENV['LOGTRICS_API_KEY']}",
"--path #{lane_context[SharedValues::DSYM_OUTPUT_PATH]}"
)
end
Install the CLI: brew install logtrics-cli on macOS, or via the npm package npm install -g @logtrics/cli for CI environments.
6. Capturing Non-Fatal Errors
Fatal crashes are only part of the picture. Non-fatal errors — conditions your app recovers from gracefully but that indicate something went wrong — are equally important to track. Use Logtrics.recordError() to capture them.
Recording a non-fatal error
// Catching a network error without crashing
do {
let userData = try await apiClient.fetchUser(id: userId)
updateUI(with: userData)
} catch {
// App recovers by showing a fallback UI
showErrorState()
// But we still want to know about this
Logtrics.recordError(
error,
userInfo: [
"userId": userId,
"endpoint": "/api/user",
"statusCode": (error as? APIError)?.statusCode ?? 0
]
)
}
Common non-fatal error scenarios to track
- → API calls that return unexpected status codes (404, 500)
- → Core Data migrations that encounter unexpected schema
- → JSONDecoding failures for server-returned data
- → In-app purchases that fail at the transaction level
- → Push notification registration failures
- → Feature flags that cannot be fetched
7. Setting User Context
Attaching user identity to crashes lets you understand which users are affected, contact them proactively, and correlate crashes with specific account types or subscription tiers.
Setting the current user
// Call this after successful authentication
func didSignIn(user: User) {
Logtrics.setUser(
id: user.id,
email: user.email, // optional
name: user.displayName // optional
)
// Add custom attributes for additional context
Logtrics.setUserAttribute("plan", value: user.subscriptionPlan)
Logtrics.setUserAttribute("accountAge", value: user.daysSinceSignup)
}
// Clear on sign out
func didSignOut() {
Logtrics.clearUser()
}
8. Screen Tracking
Tracking which screen the user was on when a crash occurred is invaluable context. Logtrics can auto-track screen names, or you can set them manually for more precise control.
Manual screen tracking in UIKit
class
CheckoutViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
Logtrics.trackScreen("Checkout")
}
}
SwiftUI View tracking with onAppear
struct CheckoutView: View {
var body: some View {
VStack {
// ... view content
}
.onAppear {
Logtrics.trackScreen("Checkout")
}
}
}
9. Remote Logging in Swift
Remote logging is one of the most powerful features of Logtrics. Log statements added throughout your app are captured and stored alongside crash data, giving you the full context of what happened before a crash.
Logging levels and examples
// Debug — detailed tracing for development insight
Logtrics.log(.debug, "Loading product catalog: \(categoryId)")
// Info — significant user actions and state changes
Logtrics.log(.info, "User added item to cart: \(productId)")
// Warn — unexpected but recoverable situations
Logtrics.log(.warn, "Payment API slow: \(latencyMs)ms, threshold: 3000ms")
// Error — failures that impact functionality
Logtrics.log(.error, "Payment declined: \(declineCode)")
Tip: You do not need to log everything — focus on the key decision points and state transitions in your critical user flows: authentication, payments, onboarding, and core feature actions. These are the logs that will explain 90% of your crashes.
10. Configuring Real-Time Alerts
Once your SDK is integrated and crashes are being captured, configure alerts so your team is notified immediately when a new crash occurs in production.
Slack alerts
In the Logtrics dashboard, go to Settings → Integrations → Slack. Add your Slack webhook URL. Each new crash issue sends a message with the crash title, affected user count, device model, OS version, and a link to the crash details page.
Email alerts
Go to Settings → Alerts → Email. Add team member email addresses. Configure whether to alert on every new crash type, or only when a threshold is crossed (e.g., 10 occurrences in 5 minutes).
Webhook (PagerDuty, custom)
Go to Settings → Integrations → Webhooks. Add your endpoint URL. Logtrics sends a JSON payload with the crash details on each new crash. Use this to integrate with PagerDuty, Opsgenie, or a custom alerting system.
11. Best Practices
Initialize as early as possible
Place Logtrics.configure() as the very first line of your app delegate or App struct init. Any crash that occurs before initialization cannot be captured.
Upload dSYMs on every release build
If you skip a dSYM upload for a version that goes to production, every crash from that version will have unreadable stack traces. Automate it in CI to guarantee it never gets missed.
Use log levels consistently
Reserve .error for actual failures that affect functionality. Use .warn for things that are unexpected but handled. This makes it easy to quickly filter the log timeline when investigating a crash.
Set user context before the first meaningful action
Call Logtrics.setUser() immediately after authentication completes. This ensures every subsequent crash is tied to a specific user ID, making it possible to identify affected accounts and reach out proactively.
Track your critical user flows with screen names
Add screen tracking at least for your checkout, authentication, onboarding, and settings flows. Knowing which screen the user was on narrows down investigation scope enormously.
Do not log PII or sensitive data
Never log credit card numbers, passwords, full names, or government IDs. Log user IDs (internal, non-PII identifiers) and anonymized context instead. Follow your app's data retention and privacy policy.
FAQ
Why is Xcode Organizer not enough for production iOS crash reporting?
Xcode Organizer only shows crashes from users who have opted into sharing diagnostics with Apple, which is a fraction of your total user base. It has a multi-hour delay before crashes appear, provides no real-time alerts, shows no pre-crash log context, and does not support custom error capture or non-fatal error recording. For production apps, you need a dedicated crash reporter like Logtrics that captures all crashes in real time, supports custom context, and sends instant Slack or email alerts.
What is a dSYM file and why does it matter for iOS crash reporting?
A dSYM (debug symbol file) is generated by Xcode when you build your app in release configuration with debug symbols enabled. It maps the raw memory addresses in a crash report back to your original Swift source file names and line numbers. Without the dSYM, a crash stack trace shows raw hex addresses like 0x00001000a3f0 instead of MyViewController.swift:84. Every iOS crash reporter requires dSYM upload to make crash reports readable.
How do I automate dSYM upload to Logtrics in CI?
After building your app in CI (GitHub Actions, Bitrise, CircleCI, etc.), add a step that runs the Logtrics CLI dSYM upload command. The CLI takes your API key and the path to the .dSYM files generated by Xcode. The dSYMs are typically found in the build directory or exported as part of an .xcarchive. You can also use the Xcode build phase script approach to upload dSYMs automatically as part of every archive build.
What is the difference between a fatal crash and a non-fatal error in iOS?
A fatal crash terminates the app process — the user sees the app close unexpectedly. These are captured automatically by crash reporters. A non-fatal error is an unexpected condition your app handles gracefully (catches and recovers from) but that still indicates something went wrong — a failed network request, a failed data migration, an unexpected nil. Non-fatal errors must be captured manually using Logtrics.recordError(), and they are just as important to track because they indicate problems your users are hitting without you knowing.
Add iOS Crash Reporting in Minutes
Start with 10,000 events per month — free, no credit card required. One Swift Package Manager install, one line of initialization code, and your app is reporting crashes in real time with AI root cause analysis and Slack alerts.