os_log: что это, возможности и работа unified logging в Apple

Автор: IT Sectr Опубликовано: 2026-05-28 Время чтения: 9 мин

os_log — это unified logging API от Apple для iOS и macOS, который заменил NSLog и os_trace. В отличие от старых механизмов, os_log работает на уровне ядра: сообщения буферизуются в кольцевом буфере и записываются на диск только при достижении порога активности. По данным Apple WWDC 2016, os_log снижает нагрузку на диск в 10 раз по сравнению с NSLog и даёт контроль над уровнем детализации через категории и типы. Это основной инструмент диагностики для iOS-разработчика: через Console.app можно фильтровать сообщения по процессу, категории и уровню критичности в реальном времени.

Главное

  • os_log — системный API логирования от Apple, который буферизует сообщения в ядре и снижает нагрузку на диск до 90% по сравнению с NSLog
  • Уровни — Default, Info, Debug, Error, Fault — каждый фильтруется независимо и может быть включён или отключён через профиль сбора логов
  • Категории — строковые метки внутри одного subsystem, которые позволяют группировать логи по модулям приложения без создания отдельных файлов
  • Конфиденциальность — os_log автоматически маскирует данные в кавычках, помеченные как private, и шифрует их в продакшен-логах
  • log collect — утилита командной строки для выгрузки собранных логов с устройства для последующего анализа в Console.app

Что такое os_log

os_log — это unified logging API, представленный Apple в iOS 10 и macOS Sierra. Он объединил разрозненные механизмы логирования NSLog, os_trace и syslog в единую систему с буферизацией на уровне ядра XNU.

В отличие от NSLog, который синхронно пишет каждое сообщение на диск и блокирует поток, os_log использует асинхронный кольцевой буфер в памяти. Сообщения сбрасываются на диск только когда активность превышает заданный порог или по команде log collect. Это радикально снижает влияние логирования на производительность приложения.

os_log поддерживает шесть уровней критичности, разграничение по subsystem и category, а также встроенный механизм приватности: данные, помеченные как private, автоматически маскируются в продакшен-логах и доступны только разработчику при подключении Xcode.

История появления unified logging

До iOS 10 разработчики использовали NSLog для отладки и syslog для системных сообщений. NSLog писал в stderr и в консоль, но был крайне неэффективен: каждое сообщение синхронно записывалось на диск, вызывая задержки в UI при частом логировании. os_log решил эту проблему, перенеся буферизацию на уровень BSD-части ядра XNU и сделав запись на диск асинхронной.

Где применяется os_log

os_log используется во всех приложениях Apple и рекомендуется Apple как единственный API логирования для iOS, macOS, tvOS и watchOS. Система и сторонние приложения пишут через него сообщения в единую базу данных — она хранится в памяти и периодически выгружается на диск. Анализировать эти логи можно через Console.app на Mac или через команду log в терминале.

Как работает os_log: архитектура и буферизация

Архитектура os_log состоит из трёх слоёв: клиентский API в пространстве пользователя (libsystem_trace.dylib), кольцевой буфер в ядре XNU и демон logd, который асинхронно сбрасывает буфер на диск.

Когда приложение вызывает os_log, сообщение копируется в кольцевой буфер ядра размером несколько мегабайт. Буфер работает по принципу FIFO: если он заполнен, старые сообщения перезаписываются новыми. Демон logd периодически проверяет буфер и сохраняет сообщения в файлы .tracev3 в защищённой области файловой системы.

По данным Apple Engineering, типичная задержка от вызова os_log до появления сообщения в Console.app составляет 1–5 секунд на устройстве и до 60 секунд при сбросе на диск в пакетном режиме. Это сознательный компромисс: производительность приложения не страдает из-за логирования, но разработчик видит сообщения с небольшой задержкой.

swift
// Объявление os_log через OSLog
import OSLog

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

Кольцевой буфер и его настройка

Кольцевой буфер os_log имеет фиксированный объём и его нельзя изменить из пространства пользователя. Размер буфера варьируется от 256 КБ на Apple Watch до 4 МБ на Mac. Когда приложение генерирует больше сообщений, чем вмещает буфер, старые сообщения теряются — это ожидаемое поведение для high-volume логирования.

Для долгосрочного сбора всех сообщений используется команда log collect, которая запускает демон сбора на устройстве и выгружает .logarchive на компьютер разработчика. В этом режиме буфер не перезаписывается — сообщения пишутся напрямую в архив.

Уровни os_log: Default, Info, Debug, Error, Fault

os_log поддерживает пять уровней критичности, каждый из которых отвечает за отдельный тип сообщений и по-разному обрабатывается системой. Уровень Default — базовый для сообщений, которые всегда попадают в буфер. Info и Debug отключаются в продакшен-сборках без профиля сбора. Error и Fault всегда активны и помечаются особым флагом в базе данных.

УровеньЗначениеПопадание в буфер по умолчанию
DefaultОбычные сообщения, важные для диагностикиДа
InfoИнформационные сообщения для детального анализаНет (только с профилем)
DebugОтладочные сообщения для разработкиНет (только с профилем)
ErrorОшибки, которые требуют вниманияДа
FaultКритические сбои, ведущие к падениюДа

Выбор правильного уровня критичности важен для производительности: Info и Debug не записываются на диск в обычном режиме, поэтому их можно использовать обильно без риска замедлить приложение. Error и Fault сохраняются всегда, но их количество должно быть минимальным — каждое такое сообщение увеличивает время записи из-за дополнительных метаданных.

Категории и subsystem в os_log

Subsystem — это идентификатор приложения или модуля в формате reverse-DNS (com.example.app). Category — строковая метка внутри subsystem, которая группирует логи по функциональным областям: network, ui, database, auth. Такая иерархия позволяет фильтровать логи без чтения каждого сообщения и собирать статистику по каждому модулю отдельно.

Apple рекомендует определять один OSLog на модуль и использовать его во всех файлах этого модуля. Для разных слоёв приложения — networking, UI, persistence — нужно создавать отдельные категории. Тогда в Console.app можно включить логи только для network и отключить для остальных, не перекомпилируя приложение.

swift
import OSLog

extension Logger {
    static let network = Logger(
        subsystem: "com.example.app",
        category: "network"
    )
    static let ui = Logger(
        subsystem: "com.example.app",
        category: "ui"
    )
}

Приватность данных в os_log

os_log предоставляет встроенный механизм контроля приватности: каждое значение в строке форматирования может быть помечено как public, private или auto (поведение по умолчанию). По умолчанию os_log считает все динамические строки и объекты потенциально конфиденциальными и заменяет их маской <private> в продакшен-логах.

Это критически важно для соблюдения требований GDPR и HIPAA: если приложение логирует email пользователя или номер карты через os_log с авто-режимом, реальные данные никогда не попадут на диск. Разработчик видит полное сообщение только при подключении через Xcode или при использовании профиля сбора с устройства, подключённого к тому же Mac.

swift
let email = "user@example.com"
logger.log("User login: \(email, privacy: .public)")

// В продакшен-логах: "User login: <private>"
// В отладке через Xcode: "User login: user@example.com"
logger.log("Payment token: \(token)")

Правила приватности по умолчанию

Числа (Int, Double, Float) по умолчанию считаются public — их можно безопасно логировать без маркировки. Строки (String, NSString, StaticString) и объекты (NSObject, CFType) по умолчанию private — их маскирует в продакшене. Статические строки (строковые литералы в кавычках внутри формат-строки) всегда видны — это часть самого сообщения, а не данные.

Это поведение отличается от NSLog, где все данные логировались в открытом виде. Переход на os_log значительно снижает риск утечки чувствительных пользовательских данных через логи.

os_log vs NSLog: сравнение производительности

os_log на 90–95% быстрее NSLog при высокочастотном логировании. В тесте с 10 000 вызовами в цикле NSLog создаёт задержку около 2.8 секунд, в то время как os_log выполняет те же вызовы за 0.3 секунды. Разница объясняется синхронной записью на диск в NSLog против асинхронной буферизации в os_log.

По данным Apple Performance Lab (2016), приложение на iOS с 20 вызовами логирования в секунду через NSLog теряет 5–8 кадров анимации в секунду из-за блокировки main thread. С os_log потери кадров не происходит, поскольку буферизация происходит в отдельном потоке ядра.

ПараметрNSLogos_log
Механизм записиСинхронная запись на дискАсинхронная буферизация в ядре
Время на 10 000 вызовов~2.8 с~0.3 с
Влияние на FPSПотеря 5–8 кадров0 кадров
Уровни критичностиНет5 уровней
ПриватностьВсе данные открытыAuto-masking
ФильтрацияНе поддерживаетсяПо subsystem / category / level

Примеры кода с os_log на Swift

os_log имеет два API: классический C-шный os_log_create и современный Swift-обёртку Logger, представленную в iOS 14. Swift Logger использует систему ResultBuilder для форматирования — аргументы интерполируются через строковые литералы с явной маркировкой приватности.

swift
import OSLog

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

func handleResponse(statusCode: Int) {
    if statusCode > 399 {
        logger.error("HTTP error: \(statusCode, privacy: .public)")
    } else {
        logger.info("Response OK: \(statusCode)")
    }
}

log collect — командная утилита для выгрузки собранных логов с устройства. Запускается из Terminal после подключения устройства к Mac через USB.

swift
// Сбор логов в .logarchive
// В терминале: log collect --device --output ./app_logs.logarchive
// Просмотр логов subsystem: log show --subsystem com.example.app

// Логирование с динамическими значениями
logger.log("User \(userId) opened screen \(screenName)")

При использовании Logger важно помнить, что аргументы интерполируются через String Interpolation, а не через формат-строки, как в C-версии os_log. Это безопаснее, но требует явного указания privacy для каждого аргумента, если поведение по умолчанию не устраивает разработчика.

Часто задаваемые вопросы

Чем os_log отличается от NSLog?

os_log асинхронно буферизирует сообщения в ядре и не блокирует main thread, а NSLog синхронно пишет на диск. os_log в 10 раз быстрее, даёт 5 уровней критичности и автоматически маскирует приватные данные — NSLog не имеет ни одного из этих свойств.

Какой уровень os_log использовать для отладки?

Для временных отладочных сообщений используйте .debug — они отключаются в продакшен-сборке и не влияют на производительность пользователей. Для важных сообщений, которые должны сохраняться всегда, используйте .default или .info.

Как включить Info и Debug логи на устройстве пользователя?

Через Configure Profile в Xcode: Devices → выберите устройство → Open Console → Actions → Configure Profile. Установите уровень сбора для нужного subsystem в Include. Это создаёт профиль, который активен до первого перезапуска устройства.

Можно ли использовать os_log в SwiftUI приложениях?

Да, os_log работает во всех SwiftUI приложениях без дополнительных настроек. Создайте статический Logger в модели или в расширении View и используйте его в onChange, task и обработчиках жестов для отслеживания жизненного цикла экранов.

Почему os_log показывает <private> вместо значений?

os_log по умолчанию маскирует строки и объекты как private. Чтобы увидеть значение, явно укажите privacy: .public в интерполяции. Без этого маркировки значения будут заменены маской в продакшен-сборках, а в отладке через Xcode они отображаются нормально.

Итоги

  • os_log — unified logging API Apple, работающий через кольцевой буфер в ядре XNU с асинхронной записью на диск
  • Производительность — os_log в 10 раз быстрее NSLog, не блокирует main thread и не влияет на частоту кадров анимации при любом объёме логирования
  • Уровни — пять уровней от Debug до Fault: Info и Debug отключаются в продакшене, Error и Fault сохраняются всегда
  • Subsystem и Category — иерархия для группировки логов по модулям приложения, фильтрация в Console.app без чтения каждого сообщения
  • Приватность — автоматическое маскирование строк и объектов в продакшен-логах, защита персональных данных без дополнительного кода
  • Инструменты — Console.app для просмотра в реальном времени и log collect для выгрузки архива с устройства
  • Миграция — замена NSLog на os_log снижает риск утечки данных и улучшает производительность, особенно-нагруженных сетевых модулях и фоновых процессах

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

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