Log Level у розробці додатків: визначення, типи рівнів та конфігурація

Автор: IT Sectr Опубліковано: 2026-05-28 Час читання: 8 хв

Log Level — класифікація повідомлень логування за ступенем критичності, що дозволяє розробникам контролювати обсяг інформації, що виводиться на різних етапах роботи додатку. За даними Google Android Developers, 2024, правильний вибір рівня логування зменшує обсяг логів у production на 85–95% та прискорює діагностику помилок. Кожен рівень вирішує своє завдання — від налагодження на етапі розробки до моніторингу критичних збоїв у продакшені.

Головне

  • Log Level — стандартизована шкала критичності від Verbose (детальне налагодження) до Error (критичні збої)
  • Verbose та Debug — рівні для розробки, що відключаються в production-збірках для продуктивності
  • Info — інформаційні повідомлення про ключові події: запуск, авторизація, навігація
  • Warn — попередження про потенційні проблеми, що не призводять до збою негайно
  • Error — критичні помилки, що вимагають негайної уваги та аналізу розробником

Що таке Log Level?

Log Level — це атрибут кожного лог-повідомлення, що визначає його важливість та терміновість обробки. Сучасні платформи iOS та Android підтримують єдину шкалу з 6–7 рівнів: від максимально детального (Verbose/Trace) до критичного (Error/Assert). Вибір рівня визначає, чи буде повідомлення записане в лог при поточній конфігурації додатку.

Концепція Log Level заснована на принципі піраміди критичності: чим вищий рівень, тим менше повідомлень на ньому виводиться. За даними Semaphore CI, 2024, у production-додатку розподіл виглядає так: Info — 60% повідомлень, Warn — 25%, Error — 10%, Debug — 5%. Verbose-повідомлення повинні бути повністю відключені в production.

Кожна платформа реалізує Log Level через власний API. Android використовує android.util.Log з методами v(), d(), i(), w(), e(). Apple — OSLog з рівнями default, info, debug, error, fault. Бібліотеки на кшталт Timber та CocoaLumberjack надбудовують додаткову функціональність поверх цих стандартних API.

За даними Google I/O 2023, неправильний вибір Log Level — причина 40% проблем з продуктивністю в production. Розробники залишають Debug-логи в релізній збірці, що призводить до надмірного запису на диск та прискореного розряду батареї.

Типи рівнів логування: від Verbose до Assert

Verbose (TRACE) — найдетальніший рівень, призначений виключно для розробки. На цьому рівні виводяться всі проміжні обчислення, ітерації циклів, результати кожного кроку алгоритму. На Android цьому рівню відповідає Log.v(), на iOS — OSLog з типом debug (до iOS 14 використовувався os_trace).

Debug — налагоджувальні повідомлення, корисні при розробці та тестуванні. Містять інформацію про стан ключових об’єктів, результати SQL-запитів, параметри API-викликів. На відміну від Verbose, Debug-повідомлення структуровані та семантично значущі. На iOS цьому рівню відповідає OSLogType.debug.

Info — інформаційні повідомлення про штатні події додатку: ініціалізація SDK, успішна авторизація, відкриття екрану, отримання даних з сервера. Info-повідомлення не повинні містити персональні дані користувачів і мають бути безпечними для production-аналізу. На iOS використовується OSLogType.info, на Android — Log.i().

Warn — попередження про потенційні проблеми. Додаток продовжує працювати, але ситуація потребує уваги: близький до ліміту розмір кешу, застаріла версія API, повільна мережева відповідь, повторна спроба з’єднання. На Android — Log.w(), на iOS — OSLogType.default (для попереджень).

Error — критичні помилки, при яких додаток не може виконати запитану операцію, але продовжує роботу: невдалий запит до API, втрата з’єднання, помилка запису в БД, відсутність дозволів. На iOS для помилок використовується OSLogType.error, на Android — Log.e().

Assert (WTF) — найвищий рівень, що позначає ситуацію „цього не може статися“. Використовується для логування багів, які порушують фундаментальні інваріанти системи. На Android Assert-повідомлення не виводяться в release-збірках за замовчуванням. На iOS WTF (What a Terrible Failure) обробляється через OSLogType.fault.

Використання Log Level на Android

Android Log API — вбудований механізм логування з пакета android.util.Log. Надає 6 статичних методів: Log.v(), Log.d(), Log.i(), Log.w(), Log.e() та Log.wtf(). Кожен метод приймає tag (рядок-ідентифікатор джерела) та msg (текст повідомлення).

kotlin
class UserRepository {
    companion object {
        private val TAG = "UserRepo"
    }

    suspend fun loadUser(id: String): User {
        Log.d(TAG, "Завантаження користувача з id: $id")

        return try {
            val response = api.fetchUser(id)
            Log.i(TAG, "Користувач успішно завантажений")
            response.toUser()
        } catch (e: Exception) {
            Log.e(TAG, "Не вдалося завантажити користувача: ${e.message}")
            throw e
        }
    }
}

Фільтрація за рівнями в Android Logcat здійснюється через ADB: adb logcat *:E покаже лише Error-повідомлення. В production-збірках всі Log.v() та Log.d() виклики видаляються ProGuard/R8 при включеній мініфікації. Log.i(), Log.w() та Log.e() залишаються, тому важливо не виводити чутливі дані через ці методи.

Для кастомної фільтрації в runtime Android надає Log.isLoggable(tag, level) — метод, який перевіряє, чи включений вказаний рівень для даного tag. Це дозволяє динамічно включати детальне логування для конкретного модуля без перескладання додатку.

Використання Log Level на iOS та macOS

OSLog — уніфікована система логування Apple, що замінила deprecated NSLog. OSLog надає 5 рівнів: debug, info, default (notice), error та fault. Головна перевага — структуроване логування з підтримкою форматованих рядків та динамічною фільтрацією через консоль.

swift
import OSLog

let logger = Logger(
    subsystem: "com.example.app",
    category: "network"
)

func fetchData(from url: URL) {
    logger.debug("Starting request to \(url.absoluteString)")

    do {
        let data = try Data(contentsOf: url)
        logger.info("Received \(data.count) bytes")
    } catch {
        logger.error("Request failed: \(error.localizedDescription)")
    }
}

Система фільтрації OSLog працює на рівні операційної системи. Debug-повідомлення записуються тільки при підключенні налагоджувача або включенні аргументу -com.apple.CoreData.Logging.debug 1. Info-повідомлення збираються в пам’яті пристрою (до 512 КБ) та доступні через Console.app. Error та fault записуються постійно і доступні для збору через crash-reporting системи.

Важлива особливість OSLog: форматовані рядки з плейсхолдерами. Замість інтерполяції рядків Swift (яка обчислюється завжди, незалежно від рівня), OSLog використовує os_log формат з %{public}@ та %{private}@ для розмежування чутливих даних. Приватні параметри маскуються в production-логах.

Production vs Debug: як налаштувати фільтрацію рівнів

Основне правило — мінімальний набір рівнів у production: Info, Warn, Error, Assert. Debug та Verbose мають бути відключені. Причина не стільки в безпеці, скільки в продуктивності: кожен лог-виклик займає процесорний час на форматування рядка, навіть якщо повідомлення не виводиться.

Ліниве форматування рядків

Критична оптимізація — ніколи не використовуйте інтерполяцію рядків у лог-викликах. Якщо рядок формується до виклику log(), процесорний час витрачається навіть при відключеному рівні. Використовуйте ліниве форматування через лямбди або guard-умови.

В Android цієї меті служить метод Log.isLoggable(), в OSLog — нативна підтримка форматованих рядків з плейсхолдерами. Timber для Android вирішує проблему через timber.log.Tree з перевіркою рівня всередині дерева.

Динамічна зміна рівня на льоту

Remote Log Level — практика, при якій рівень логування керується з сервера через Firebase Remote Config або аналогічний сервіс. Якщо в production виникає складна помилка, розробник може дистанційно включити Debug-логування для конкретного модуля на пристроях вибраної групи користувачів.

За даними Firebase, 2024, така практика скорочує час діагностики рідкісних багів на 60% і дозволяє отримати повну картину проблеми без встановлення debug-збірки. Головне обмеження — логи вмикаються лише при наступному запуску додатку після отримання конфігурації.

Автоматична фільтрація за build type

BuildConfig.DEBUG на Android та #if DEBUG на Swift — стандартні механізми умовної компіляції, що відключають налагоджувальні рівні в release-збірках. Для чистої архітектури рекомендується винести вибір Log Level в DI-контейнер або фабрику логерів, щоб не захаращувати бізнес-логіку умовними директивами.

Кращі практики при виборі рівня логування

Перше правило — кожен лог-виклик повинен відповідати на питання „хто, що, коли“. Хто — компонент або модуль (tag на Android, category на iOS). Що — конкретна подія або зміна стану. Коли — часова мітка, що проставляється автоматично системою логування.

Друге правило — не логуйте чутливі дані через Info і вище. Паролі, токени, email, номери телефонів, точні геокоординати — категорично заборонені в будь-якому лозі, який потрапляє в production. При необхідності використовуйте маскування: „email: us***@example.com“.

Третє правило — рівень Warn — зона відповідальності розробника, Error — команди. Warn означає „тут потенційна проблема, слідкуй“. Error — „тут проблема, виправляй“. Не використовуйте Error для ситуацій, які очікувані та оброблені (наприклад, 404 помилка API).

Четверте правило — консистентність. Весь проект повинен використовувати єдині угоди про іменування tag та категорій. Рекомендується ClassName.methodName для Android tag та module.subsystem для iOS category. Це дозволяє швидко фільтрувати логи за компонентом.

П’яте правило — тестуйте логи. В unit-тестах перевіряйте, що в певних сценаріях викликається правильний Log Level. Для цього існують mock-бібліотеки логування: Mockito для Android, Cuckoo для iOS. Перевірка рівнів у тестах запобігає витоку налагоджувальних повідомлень у production.

Часті запитання

Що станеться, якщо залишити Debug-логи в production?

Прискорений розряд батареї та надмірний запис на диск. Кожен Debug-лог форматує рядок і записує дані в буфер. На пристроях з Flash-пам’яттю це прискорює знос накопичувача. Крім того, Debug-логи можуть містити чутливі дані, недоступні для перегляду в production.

Який Log Level використовувати для логування мережевих запитів?

Debug — для тіла запиту та відповіді, заголовків та статус-коду. Info — для факту виконання запиту (URL, метод, тривалість). Error — для невдалих запитів з кодом 4xx/5xx. Ніколи не використовуйте Verbose для мережевих логів у production.

Чим відрізняється OSLogType.default від OSLogType.info?

OSLogType.default (рівень notice) — повідомлення середньої важливості, зберігаються в системному лозі та видні в Console.app. OSLogType.info — технічні повідомлення, не зберігаються постійно, доступні тільки при активному профілюванні через Instruments.

Як ProGuard обробляє Log-виклики на Android?

R8/ProGuard видаляє Log.v() та Log.d() при включеній мініфікації в release-збірці. Log.i(), Log.w() та Log.e() зберігаються. Для повного видалення всіх логів потрібне кастомне правило -assumenosideeffects class android.util.Log із зазначенням всіх рівнів.

Чи повинен кожен метод логувати свій початок і кінець?

Ні — надмірне логування погіршує читабельність та продуктивність. Логуйте вхід тільки в складних або асинхронних методах. Для синхронних методів достатньо одного лога в точці повернення або помилки. Використовуйте Debug-рівень для трасування викликів.

Підсумки

  • Log Level — шкала критичності від Verbose до Assert, що визначає видимість кожного лог-повідомлення
  • Verbose та Debug — призначені для розробки і повинні бути відключені в production-збірках
  • Info — ключові події додатку, безпечні для production-аналізу
  • Warn — потенційні проблеми, що не потребують негайного виправлення
  • Error — критичні збої, що потребують втручання команди розробки
  • Android Log API використовує tag + level, OSLog на iOS — subsystem + category + level
  • Ліниве форматування та умовна компіляція — ключові техніки оптимізації логування в production

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також