Реализация Remote Logging для отладки мобильного приложения в продакшене

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация Remote Logging для отладки мобильного приложения в продакшене
Сложная
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация Remote Logging для отладки мобильного приложения в продакшене

Баг воспроизводится только на конкретном устройстве конкретного пользователя — и только в продакшене. Подключить debugger невозможно. Crashlytics показывает крэш, но стектрейс без контекста не объясняет, как приложение дошло до этого состояния. Remote logging решает именно эту проблему: детальные логи с устройств пользователей поступают на сервер в реальном времени или по запросу.

Архитектура

Remote logging — это не «отправлять все логи с каждого устройства на сервер». Это дорого по трафику, хранению и влияет на производительность. Правильная архитектура предполагает несколько режимов.

Пассивный режим (по умолчанию): логи пишутся в локальный кольцевой буфер. На сервер ничего не уходит.

Активный режим: включается по триггеру — крэш, конкретный user ID, флаг из Remote Config. Буфер сбрасывается на сервер.

Debug-сессия для конкретного пользователя: по запросу поддержки включается расширенное логирование для конкретного userId через Firebase Remote Config или feature flag.

Firebase Remote Config для динамического управления логированием

// Android: проверка флагов логирования при старте
val remoteConfig = Firebase.remoteConfig
remoteConfig.fetchAndActivate().addOnCompleteListener {
    val logLevel = remoteConfig.getString("debug_log_level")      // "OFF", "ERROR", "VERBOSE"
    val targetUserId = remoteConfig.getString("debug_user_id")     // пустая строка = все
    RemoteLogger.configure(
        level = LogLevel.fromString(logLevel),
        targetUserId = targetUserId
    )
}

Включить подробное логирование для конкретного пользователя без релиза: меняем Remote Config → через 30 минут устройство подтянет новый конфиг → следующая сессия пишет verbose-логи.

Транспорт логов

Батчевая отправка

Не отправляем каждый лог-вызов как отдельный HTTP-запрос — накапливаем в очереди и отправляем пачками:

class RemoteLogTransport(
    private val apiService: LogApiService,
    private val batchSize: Int = 100,
    private val flushIntervalMs: Long = 30_000
) {
    private val pendingLogs = ConcurrentLinkedQueue<LogEntry>()

    fun enqueue(entry: LogEntry) {
        pendingLogs.add(entry)
        if (pendingLogs.size >= batchSize) {
            flush()
        }
    }

    private fun flush() {
        val batch = mutableListOf<LogEntry>()
        repeat(batchSize) {
            pendingLogs.poll()?.let { batch.add(it) } ?: return@repeat
        }
        if (batch.isNotEmpty()) {
            scope.launch {
                runCatching {
                    apiService.sendLogs(LogBatch(
                        sessionId = sessionId,
                        deviceInfo = deviceInfo,
                        logs = batch
                    ))
                }
            }
        }
    }
}

WorkManager для гарантированной доставки при восстановлении сети:

val logUploadWork = OneTimeWorkRequestBuilder<LogUploadWorker>()
    .setConstraints(Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .build())
    .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
    .build()
WorkManager.getInstance(context).enqueue(logUploadWork)

iOS — комбинация OSLog и remote transport

// OSLog для системного логирования + remote transport
actor RemoteLogger {
    private var buffer: [LogEntry] = []
    private var isRemoteEnabled = false
    private let transport: LogTransport

    func log(_ message: String, level: LogLevel) async {
        let entry = LogEntry(timestamp: Date(), level: level, message: message)
        buffer.append(entry)
        if buffer.count > 500 { buffer.removeFirst() }

        if isRemoteEnabled {
            await transport.enqueue(entry)
        }
    }

    func enableRemote(for userId: String) async {
        isRemoteEnabled = true
        // Отправляем буфер накопленных логов
        let bufferedLogs = buffer
        await transport.sendBatch(bufferedLogs)
    }
}

actor обеспечивает thread safety без explicit locking — правильный подход в Swift 5.5+.

Backend для хранения логов

Стандартные решения:

Хранилище Подходит для Особенности
Elasticsearch + Kibana Полнотекстовый поиск по логам Ресурсоёмкий, но мощный
Loki + Grafana Структурированные логи, мало ресурсов Дешевле Elastic
Datadog SaaS, без инфраструктуры Дорогой при большом объёме
Sentry Уже используется для крэшей Breadcrumbs + remote logs в одном месте

Sentry Breadcrumbs — часто недооценённая функция. Кастомные breadcrumbs прикрепляются к каждому Event (крэшу или ошибке) и показывают, что происходило до проблемы:

SentrySDK.configureScope { scope in
    scope.addBreadcrumb(Breadcrumb(
        level: .info,
        category: "navigation",
        message: "User opened PaymentScreen",
        data: ["orderId": orderId]
    ))
}

Когда случается крэш, в Sentry видны последние 100 breadcrumbs — фактически готовый лог пользовательского пути.

Безопасность и соответствие GDPR/CCPA

Remote логи потенциально содержат персональные данные. Обязательно:

  • Логи не содержат полных имён, email, номеров карт — только userId для корреляции
  • Данные логов хранятся не дольше 30 дней (настраивается TTL в хранилище)
  • Пользователь может отказаться от сбора диагностики в настройках приложения — флаг сохраняется в UserDefaults / SharedPreferences, проверяется перед каждой отправкой
  • В Privacy Policy описан сбор диагностических данных

Оперативная отладка без релиза

Сценарий: продакшен падает у 0.3% пользователей на конкретном устройстве. Последовательность без remote logging:

  1. Попросить пользователя включить developer mode → маловероятно
  2. Ждать воспроизведения → неизвестно когда

С remote logging:

  1. Включить verbose-режим через Remote Config для конкретного userId
  2. Пользователь воспроизводит проблему в следующей сессии
  3. Через 30 минут в Kibana/Grafana видны подробные логи сессии
  4. Находим место → hotfix → выключаем verbose-режим

Ориентиры по срокам

Базовая система remote logging с батчевой отправкой, Remote Config управлением и интеграцией с Sentry — 1–2 недели. Полная инфраструктура с Elasticsearch, Kibana-дашбордами, GDPR-механизмами и iOS+Android — 3–4 недели. Стоимость рассчитывается индивидуально после аудита текущей инфраструктуры.