Log Level — klasifikace logovacích zpráv podle stupně kritičnosti, umožňující vývojářům kontrolovat objem výstupních informací v různých fázích provozu aplikace. Podle údajů Google Android Developers, 2024 správný výběr úrovně logování snižuje objem logů v produkci o 85–95% a urychluje diagnostiku chyb. Každá úroveň řeší svůj úkol — od ladění ve fázi vývoje až po monitorování kritických selhání v produkci.
Hlavní body
Log Level — atribut každé logovací zprávy, který určuje její důležitost a naléhavost zpracování. Moderní platformy iOS a Android podporují jednotnou škálu 6–7 úrovní: od maximálně detailní (Verbose/Trace) po kritickou (Error/Assert). Výběr úrovně určuje, zda bude zpráva zapsána do logu při aktuální konfiguraci aplikace.
Koncepce Log Level je založena na principu pyramidy kritičnosti: čím vyšší úroveň, tím méně zpráv se na ní zobrazuje. Podle údajů Semaphore CI, 2024 vypadá rozdělení v produkční aplikaci takto: Info — 60% zpráv, Warn — 25%, Error — 10%, Debug — 5%. Verbose zprávy musí být v produkci zcela vypnuty.
Každá platforma implementuje Log Level prostřednictvím vlastního API. Android používá android.util.Log s metodami v(), d(), i(), w(), e(). Apple — OSLog s úrovněmi default, info, debug, error, fault. Knihovny jako Timber a CocoaLumberjack staví další funkčnost nad tato standardní API.
Podle údajů Google I/O 2023 je nesprávný výběr Log Level příčinou 40% problémů s výkonem v produkci. Vývojáři nechávají Debug logy v release sestavení, což vede k nadměrnému zápisu na disk a zrychlenému vybíjení baterie.
Verbose (TRACE) — nejpodrobnější úroveň, určená výhradně pro vývoj. Na této úrovni se zobrazují všechny mezivýpočty, iterace smyček, výsledky každého kroku algoritmu. Na Androidu této úrovni odpovídá Log.v(), na iOS — OSLog s typem debug (před iOS 14 se používalo os_trace).
Debug — ladící zprávy, užitečné během vývoje a testování. Obsahují informace o stavu klíčových objektů, výsledky SQL dotazů, parametry API volání. Na rozdíl od Verbose jsou Debug zprávy strukturované a sémanticky významné. Na iOS této úrovni odpovídá OSLogType.debug.
Info — informační zprávy o běžných událostech aplikace: inicializace SDK, úspěšná autorizace, otevření obrazovky, příjem dat ze serveru. Info zprávy nesmí obsahovat osobní údaje uživatelů a musí být bezpečné pro analýzu v produkci. Na iOS se používá OSLogType.info, na Androidu — Log.i().
Warn — varování o potenciálních problémech. Aplikace nadále funguje, ale situace vyžaduje pozornost: velikost mezipaměti blízko limitu, zastaralá verze API, pomalá síťová odpověď, opakovaný pokus o připojení. Na Androidu — Log.w(), na iOS — OSLogType.default (pro varování).
Error — kritické chyby, při kterých aplikace nemůže provést požadovanou operaci, ale pokračuje v činnosti: neúspěšný požadavek na API, ztráta připojení, chyba zápisu do databáze, chybějící oprávnění. Na iOS se pro chyby používá OSLogType.error, na Androidu — Log.e().
Assert (WTF) — nejvyšší úroveň, označující situaci „toto se nemůže stát”. Používá se pro logování chyb, které narušují fundamentální invarianty systému. Na Androidu se Assert zprávy ve výchozím nastavení nezobrazují v release sestaveních. Na iOS je WTF (What a Terrible Failure) zpracováváno prostřednictvím OSLogType.fault.
Android Log API — vestavěný mechanismus logování z balíčku android.util.Log. Poskytuje 6 statických metod: Log.v(), Log.d(), Log.i(), Log.w(), Log.e() a Log.wtf(). Každá metoda přijímá tag (řetězec identifikující zdroj) a msg (text zprávy).
class UserRepository {
companion object {
private val TAG = "UserRepo"
}
suspend fun loadUser(id: String): User {
Log.d(TAG, "Načítání uživatele s id: $id")
return try {
val response = api.fetchUser(id)
Log.i(TAG, "Uživatel úspěšně načten")
response.toUser()
} catch (e: Exception) {
Log.e(TAG, "Nepodařilo se načíst uživatele: ${e.message}")
throw e
}
}
}
Filtrování podle úrovní v Android Logcat se provádí přes ADB: adb logcat *:E zobrazí pouze Error zprávy. V produkčních sestaveních jsou všechna volání Log.v() a Log.d() odstraněna ProGuard/R8 při zapnuté minifikaci. Log.i(), Log.w() a Log.e() zůstávají, proto je důležité nevyvádět citlivá data prostřednictvím těchto metod.
Pro vlastní filtrování za běhu poskytuje Android Log.isLoggable(tag, level) — metodu, která kontroluje, zda je pro daný tag zapnuta zadaná úroveň. To umožňuje dynamicky zapnout detailní logování pro konkrétní modul bez přestavby aplikace.
OSLog — jednotný logovací systém Apple, který nahradil zastaralý NSLog. OSLog poskytuje 5 úrovní: debug, info, default (notice), error a fault. Hlavní výhodou je strukturované logování s podporou formátovaných řetězců a dynamickým filtrováním přes konzoli.
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)")
}
}
Filtrovací systém OSLog funguje na úrovni operačního systému. Debug zprávy se zapisují pouze při připojeném debuggeru nebo při zapnutém argumentu -com.apple.CoreData.Logging.debug 1. Info zprávy se shromažďují v paměti zařízení (až 512 KB) a jsou přístupné přes Console.app. Error a fault se zapisují trvale a jsou k dispozici pro sběr prostřednictvím systémů pro hlášení pádů.
Důležitá vlastnost OSLog: formátované řetězce s placeholder-y. Místo interpolace řetězců Swift (která se počítá vždy, bez ohledu na úroveň) používá OSLog formát os_log s %{public}@ a %{private}@ pro rozlišení citlivých dat. Soukromé parametry jsou maskovány v produkčních logách.
Základní pravidlo — minimální sada úrovní v produkci: Info, Warn, Error, Assert. Debug a Verbose musí být vypnuty. Důvod není ani tak v bezpečnosti, jako spíše ve výkonu: každé logovací volání zabírá čas procesoru na formátování řetězce, i když se zpráva nezobrazuje.
Kritická optimalizace — nikdy nepoužívejte interpolaci řetězců v logovacích voláních. Pokud je řetězec tvořen před voláním log(), procesorový čas se plýtvá i při vypnuté úrovni. Používejte líné formátování prostřednictvím lambd nebo ochranných podmínek.
Na Androidu tomuto účelu slouží metoda Log.isLoggable(), v OSLog — nativní podpora formátovaných řetězců s placeholder-y. Timber pro Android řeší problém prostřednictvím timber.log.Tree s kontrolou úrovně uvnitř stromu.
Remote Log Level — praxe, při které je úroveň logování řízena ze serveru prostřednictvím Firebase Remote Config nebo podobné služby. Pokud se v produkci vyskytne komplexní chyba, může vývojář vzdáleně zapnout Debug logování pro konkrétní modul na zařízeních vybrané skupiny uživatelů.
Podle údajů Firebase, 2024 tato praxe zkracuje dobu diagnostiky vzácných chyb o 60% a umožňuje získat úplný obrázek o problému bez instalace debug sestavení. Hlavním omezením je, že logy se aktivují až při příštím spuštění aplikace po obdržení konfigurace.
BuildConfig.DEBUG na Androidu a #if DEBUG ve Swift — standardní mechanismy podmíněného překladu, které vypínají ladící úrovně v release sestaveních. Pro čistou architekturu se doporučuje přesunout výběr Log Level do DI kontejneru nebo továrny loggerů, aby nebyla obchodní logika zatížena podmíněnými direktivami.
První pravidlo — každé logovací volání by mělo odpovídat na otázku „kdo, co, kdy”. Kdo — komponenta nebo modul (tag na Androidu, category na iOS). Co — konkrétní událost nebo změna stavu. Kdy — časové razítko, automaticky nastavené logovacím systémem.
Druhé pravidlo — nelogujte citlivá data přes Info a výš. Hesla, tokeny, emaily, telefonní čísla, přesné geografické souřadnice — jsou kategoricky zakázány v jakémkoli logu, který se dostane do produkce. V případě potřeby použijte maskování: „email: us***@example.com”.
Třetí pravidlo — úroveň Warn je zodpovědností vývojáře, Error — týmu. Warn znamená „zde je potenciální problém, sleduj”. Error — „zde je problém, oprav”. Nepoužívejte Error pro situace, které jsou očekávané a ošetřené (například chyba API 404).
Čtvrté pravidlo — konzistence. Celý projekt by měl používat jednotné konvence pro pojmenování tagů a kategorií. Doporučuje se ClassName.methodName pro Android tagy a module.subsystem pro iOS kategorie. To umožňuje rychlé filtrování logů podle komponenty.
Páté pravidlo — testujte logy. V unit testech kontrolujte, že se v určitých scénářích volá správná Log Level. K tomuto účelu existují mockovací knihovny pro logování: Mockito pro Android, Cuckoo pro iOS. Kontrola úrovní v testech zabraňuje úniku ladících zpráv do produkce.
Často kladené otázky
Zrychlené vybíjení baterie a nadměrný zápis na disk. Každý Debug log formátuje řetězec a zapisuje data do vyrovnávací paměti. Na zařízeních s Flash pamětí to urychluje opotřebení úložiště. Kromě toho mohou Debug logy obsahovat citlivá data nedostupná k prohlížení v produkci.
Debug — pro tělo požadavku a odpovědi, hlavičky a stavový kód. Info — pro fakt provedení požadavku (URL, metoda, doba trvání). Error — pro neúspěšné požadavky s kódem 4xx/5xx. Nikdy nepoužívejte Verbose pro síťové logy v produkci.
OSLogType.default (úroveň notice) — zprávy střední důležitosti, ukládané do systémového logu a viditelné v Console.app. OSLogType.info — technické zprávy, neukládané trvale, dostupné pouze při aktivním profilování přes Instruments.
R8/ProGuard odstraňuje Log.v() a Log.d() při zapnuté minifikaci v release sestavení. Log.i(), Log.w(), Log.e() jsou zachovány. Pro úplné odstranění všech logů je vyžadováno vlastní pravidlo -assumenosideeffects class android.util.Log s uvedením všech úrovní.
Ne — nadměrné logování zhoršuje čitelnost a výkon. Logujte vstup pouze u složitých nebo asynchronních metod. U synchronních metod stačí jeden log v bodě návratu nebo chyby. Používejte Debug úroveň pro trasování volání.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také