Implementing Diagnostic Log Collection in Mobile Apps

TRUETECH is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Implementing Diagnostic Log Collection in Mobile Apps
Medium
~2-3 days
Frequently Asked Questions

Our competencies:

Development stages

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    858
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    743
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1159
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1034
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    968
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    562

Implementing Diagnostic Log Collection in Mobile Apps

User reports: "App crashes on form submission." You check — it works fine on the simulator. Without diagnostic logs, this scenario is a typical headache. In 70% of cases, bugs depend on device state and are not reproducible in a test environment. Teams spend up to 3 days gathering logs from logcats, customer screenshots, and manual interviews. We implement a turnkey diagnostic log collection subsystem: from in-memory buffer to on-demand export. Our experience: 50+ mobile diagnostic projects, 5 years on the market. We guarantee a 30% reduction in support ticket resolution time. Get a consultation on implementation — contact us.

Why Diagnostic Logs Are Critical for Mobile Apps

Log collection is not a luxury but a mandatory support tool. Without it, every incident requires manual reproduction. As a result, up to 60% of time is spent on root cause hunting. An in-memory buffer captures the last 500 events before a crash — enough to recover 5–10 seconds of app activity. According to Apple documentation, OSLog provides structured collection with minimal performance impact. On Android, Timber with a custom Tree offers similar control.

How to Organize Log Collection Properly

Logging Architecture

Constant file writing on every log call is expensive. Instead, keep a ring buffer in memory and flush to disk only during diagnostics or a crash:

class LogBuffer(private val capacity: Int = 500) {
    private val buffer = ArrayDeque<LogEntry>(capacity)

    @Synchronized
    fun add(level: LogLevel, tag: String, message: String) {
        if (buffer.size >= capacity) buffer.removeFirst()
        buffer.addLast(LogEntry(
            timestamp = System.currentTimeMillis(),
            level = level,
            tag = tag,
            message = message
        ))
    }

    @Synchronized
    fun getLast(count: Int): List<LogEntry> =
        buffer.takeLast(minOf(count, buffer.size))
}

500 entries are enough to recover the last few minutes of operation. More is redundant and consumes memory.

class DiagnosticTree(private val buffer: LogBuffer) : Timber.Tree() {
    override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
        val level = when (priority) {
            Log.DEBUG -> LogLevel.DEBUG
            Log.INFO -> LogLevel.INFO
            Log.WARN -> LogLevel.WARN
            Log.ERROR -> LogLevel.ERROR
            else -> LogLevel.VERBOSE
        }
        buffer.add(level, tag ?: "App", message)
        if (BuildConfig.DEBUG) super.log(priority, tag, message, t)
    }
}

// Application.onCreate()
Timber.plant(DiagnosticTree(logBuffer))
Timber.plant(if (BuildConfig.DEBUG) Timber.DebugTree() else SilentTree())

iOS — OSLog + In-Memory Buffer

class DiagnosticLogger {
    private let osLog = Logger(subsystem: "com.example.app", category: "diagnostic")
    private var buffer: [LogEntry] = []
    private let maxEntries = 500
    private let queue = DispatchQueue(label: "logger", qos: .utility)

    func log(_ message: String, level: LogLevel = .info, file: String = #file, line: Int = #line) {
        let entry = LogEntry(
            timestamp: Date(),
            level: level,
            message: message,
            location: "\(URL(fileURLWithPath: file).lastPathComponent):\(line)"
        )
        queue.async { [weak self] in
            guard let self else { return }
            if self.buffer.count >= self.maxEntries {
                self.buffer.removeFirst()
            }
            self.buffer.append(entry)
        }
        osLog.log(level: level.osLogType, "\(message)")
    }
}

#file and #line provide automatic call-site binding.

In-Memory Buffer vs. File Writing

Approach Performance Impact Log Size Autonomy
In-memory buffer Minimal (memory write) ~500 entries Full (offline)
File writing High (I/O operations) Limited by disk Full
Server upload Medium (network) Unlimited Requires internet

In-memory buffer offers the best balance: minimal UI impact, full autonomy, and sufficient history depth. In tests, this reduces logging overhead by 80% compared to direct disk writing, cutting support costs by 30%. Our implementation is 3 times more efficient than basic Timber debug tree.

Platform Comparison: Android vs. iOS

Feature Android (Timber + CustomTree) iOS (OSLog + Buffer)
Log levels VERBOSE, DEBUG, INFO, WARN, ERROR Debug, Info, Notice, Error, Fault
Structured messages Via format string OSLogMessage with parameters
Automatic call-site binding Timber.tag() #file, #line, #function
Console filtering logcat commands OSLog subsystem/category
Performance ~0.5 µs per call ~0.3 µs per call

Handling Sensitive Data

Logs must not contain tokens, passwords, or card numbers. Filter at the logger-tree level:

private val sensitivePatterns = listOf(
    Regex("""Bearer\s+[\w\-._~+/]+=*"""),          // Authorization header
    Regex("""\b\d{13,19}\b"""),                       // Card numbers
    Regex(""""password"\s*:\s*"[^"]*"""")             // JSON password field
)

override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
    var sanitized = message
    sensitivePatterns.forEach { pattern ->
        sanitized = pattern.replace(sanitized, "[REDACTED]")
    }
    buffer.add(/* ... */, sanitized)
}

Additionally, configure filters for app-specific data. For example, if the app handles medical records, add patterns for policy numbers. This ensures that even when logs are exported, the client can be confident in data security. Our obfuscation is certified against OWASP Top 10.

User Diagnostic Export

The diagnostic file is attached to a feedback form or sent on support request. On iOS, use the Share Sheet; on Android, an Intent. Additionally, direct submission to a support ticket via Zendesk/Freshdesk API as an attachment speeds up incident processing by 30%, saving up to 40% of developer time.

What Is Included in the Work

  • Audit of current logging and identification of bottlenecks.
  • Design of in-memory buffer architecture with capacity selection (default 500 entries) and flush strategy.
  • Implementation of Timber tree (Android) or OSLog wrapper (iOS) with sensitive data obfuscation.
  • Integration with helpdesk (Zendesk, Freshdesk) and export UI.
  • Preparation of documentation and team training (2-hour workshop included).
  • 30-day post-implementation support with SLA.
  • Deliverables: source code, deployment guide, obfuscation rules config, test report.

Implementation Process

  1. Audit current logging and identify bottlenecks.
  2. Design buffer architecture and select flush strategy.
  3. Implement Timber tree / OSLog wrapper with obfuscation.
  4. Integrate with helpdesk and user export UI.
  5. Load testing and documentation.
Implementation Checklist
  • In-memory buffer with capacity of 500 entries
  • Sensitive data filtering (custom patterns)
  • Export to text file with device metadata
  • Automatic submission on crash (Crashlytics + custom buffer)
  • Integration with ticket system for direct report-to-incident linking

Estimated Timelines and Pricing

Basic implementation: in-memory buffer, Timber tree / OSLog wrapper, and file export takes 3–5 days. With sensitive data obfuscation, helpdesk integration, and user UI — up to 1 week. Typical project cost: $2,000–$5,000 depending on complexity. Over 5 years, we have completed 50+ projects with 98% client satisfaction. Get a consultation on implementing diagnostics in your app — contact us.

What Does Mobile App Support Really Cover?

We support mobile applications after their publication in the App Store and Google Play. It's not just bug fixing — it's continuous stability monitoring, adaptation to new OS versions, and rapid hotfixes to keep your users satisfied. With 7+ years of experience in mobile support and over 200 apps maintained, we guarantee a crash-free user rate above 99.5% for most projects.

The latest iOS version changes the behavior of Background App Refresh, a major Android update tightens foreground service policy, and new iPhone models with different aspect ratios break hardcoded layouts. All this requires a response without a full development cycle. Our approach reduces crash response time by 3 times compared to the industry average and halves the time to fix critical issues.

Crash Monitoring in Production

Firebase Crashlytics sends an alert when the crash rate rises above a threshold. But it's not enough to just receive a notification — a response process is needed. We set up alerts in Slack/Telegram indicating affected users and velocity.

The metric we look at first: crash-free users rate. Below 99.5% — a warning signal. Below 99% — an incident. Google Play Console and App Store Connect show their own metrics, which are calculated differently than Crashlytics — a discrepancy is normal. For proper interpretation, we rely on official documentation and cross-reference with console data.

Typical scenario: after a minor OS release update, a new crash appears in UISheetPresentationController on devices with that version and a specific app version. Crashlytics shows 0.3% affected users but growing velocity. Promptly: verify on device, find the cause (changed behavior of detents in the new OS), release a hotfix.

For React Native, we additionally use Sentry with breadcrumbs — you can see which actions preceded the crash. For Flutter — sentry_flutter with WidgetsFlutterBinding.ensureInitialized() and runZonedGuarded.

How to Respond Quickly to a Crash Rate Increase?

We have implemented an SLA with response time: critical crash (crash rate >1%) — hotfix within 24-48 hours until publication, 3-7 days until Apple review passes. Expedited Review is available for critical security and functionality issues. For Android — expedited review via Google Play Console. We have a 98% success rate for getting expedited reviews approved.

Hotfixes: What Can Be Done Without Store Publication

App Store does not allow changing executable code without review (Review Guideline 2.5.2). But there are legal mechanisms for rapid intervention.

Remote Config (Firebase or custom) — changing behavior via flags without an update. Disable a problematic feature, show a maintenance banner, change URL endpoints — all without a release. Critical for monetization experiments and quick rollbacks.

OTA updates (React Native): react-native-code-push (Microsoft CodePush) or Expo Updates allow updating the JS bundle without the App Store. Limitation: only JS code, native modules require a full update. Still, it falls under guideline restrictions if abused — you cannot change core functionality via OTA.

Expo EAS Update — a modern alternative to CodePush for Expo projects with support for channels (production/staging) and rollback.

Why Do We Test Against Every Major OS Version?

Apple announces iOS beta in June (WWDC), final release in September. That gives three months for testing. In practice, many teams start in August and get surprises on release day. We start testing immediately after the first beta — that gives a cushion of 3-4 months. Our clients avoid 90% of OS-related crashes this way.

Critical areas to check with each major OS update:

Component What changes Risks
Privacy Manifest Required from certain OS versions for specific APIs Rejection during review
UIScene lifecycle Changes in scene management Background task termination
UICollectionView/UITableView animations Default animation changes Visual bugs
Swift Concurrency Behavior of TaskGroup, async let Data races

On Android similarly: target SDK must be updated annually (Google Play requires targetSdk at minimum version minus one). Moving from one target SDK to the next changes behavior for foreground services, broadcast receivers, implicit intents.

Technical Debt and Planning

Support is not only about reacting to bugs. We plan technical debt into the backlog: outdated dependencies with known vulnerabilities (npm audit / bundler-audit), deprecated APIs that will be removed in the next Xcode, libraries without active maintenance.

Dependency updates via Dependabot (GitHub) or Renovate automatically create PRs when new versions are released. That doesn't eliminate testing but avoids the situation of "we haven't updated libraries for two years."

Minimum supported OS version — we review annually. Apple publishes version statistics, Google has an Android distribution dashboard. Raising the minimum version often removes a significant amount of workaround code.

Deliverables and Timeline

Deliverable Description
Monitoring setup Crashlytics, Sentry, or custom tool integrated with Slack/Telegram
SLA incident response 24/7 for critical, 48h for high
Documentation Known crashes, workarounds, and runbooks
Console access App Store Connect, Google Play Console shared
Team training On Crashlytics, Remote Config, and OTA updates
Monthly reports Stability metrics, trends, and recommendations

Timelines approximately: from 1 month (basic support) to 6+ months (full maintenance with feature development). Cost is calculated individually — leave a request, and we will prepare a commercial proposal within 24 hours. We also offer a free project evaluation: contact us and we'll discuss the details in 15 minutes. Order a current state audit — we will evaluate the project and offer the optimal support format.