
Xcglogger - это оригинальный журнал отладки для использования в Swift Projects.
Swift не включает препроцессор C, поэтому разработчики не могут использовать журнал отладки #define , которые они будут использовать в Objective-C. Это означает, что наш традиционный способ создания хороших журналов отладки больше не работает. Прибегая к простому старым print звонкам означает, что вы теряете много полезной информации или требуете, чтобы вы набрали гораздо больше кода.
Xcglogger позволяет вам войти в систему в консоли (и, опционально файл, или другие пользовательские направления), точно так же, как вы имели бы с помощью NSLog() или print() , но с дополнительной информацией, такой как дата, имя функции, имя файла и номер строки.
Уйти от этого:
Simple message
к этому:
2014-06-09 06:44:43.600 [Debug] [AppDelegate.swift:40] application(_:didFinishLaunchingWithOptions:): Simple message
Выполнять:
git submodule add https://github.com/DaveWoodCom/XCGLogger.git
В папке репозитория.
Добавьте следующую строку в свой Cartfile .
github "DaveWoodCom/XCGLogger" ~> 7.1.5
Затем запустите carthage update --no-use-binaries или просто carthage update . Для получения подробной информации об установке и использовании Карфагена, посетите его страницу проекта.
Разработчики, работающие 5,0 и выше в Swift, должны будут добавить $(SRCROOT)/Carthage/Build/iOS/ObjcExceptionBridging.framework в свои входные файлы на фазе сборки карфаймов Caprathage Frameworks.
Добавьте что -то похожее на следующие строки в свой Podfile . Вам может потребоваться настроить на основе вашей платформы, версии/филиала и т. Д.
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '12.0'
use_frameworks!
pod 'XCGLogger', '~> 7.1.5'
Указание POD XCGLogger самостоятельно будет включать в себя структуру CORE. Мы начинаем добавлять подвинки, чтобы также включать дополнительные компоненты:
pod 'XCGLogger/UserInfoHelpers', '~> 7.1.5' : включите некоторый экспериментальный код, чтобы помочь справиться с использованием словарей UserInfo для тега.
Затем запустите pod install . Для получения подробной информации об установке и использовании кокопод, посетите его официальный веб -сайт.
ПРИМЕЧАНИЕ. Перед кокоподами 1.4.0 было невозможно использовать несколько стручков с смесью быстрых версий. Возможно, вам потребуется убедиться, что каждый POD настроен для правильной версии Swift (проверьте цели в проекте POD вашего рабочего пространства). Если вы вручную отрегулируете версию Swift для проекта, она сбросится в следующий раз, когда вы запустите pod install . Вы можете добавить крюк post_install в свой Podfile, чтобы автоматизировать настройку правильных версий Swift. Это в значительной степени не проверено, и я не уверен, что это хорошее решение, но, похоже, работает:
post_install do |installer|
installer.pods_project.targets.each do |target|
if ['SomeTarget-iOS', 'SomeTarget-watchOS'].include? "#{target}"
print "Setting #{target}'s SWIFT_VERSION to 4.2n"
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '4.2'
end
else
print "Setting #{target}'s SWIFT_VERSION to Undefined (Xcode will automatically resolve)n"
target.build_configurations.each do |config|
config.build_settings.delete('SWIFT_VERSION')
end
end
end
print "Setting the default SWIFT_VERSION to 3.2n"
installer.pods_project.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '3.2'
end
end
Вы можете настроить это в соответствии с вашими потребностями, конечно.
Добавьте следующую запись в зависимости вашего пакета:
.Package(url: "https://github.com/DaveWoodCom/XCGLogger.git", majorVersion: 7)
Использовать:
Этот метод быстрого запуска предназначен просто для того, чтобы вы могли работать с журналом. Однако вы должны использовать расширенное использование ниже, чтобы получить максимальную отдачу от этой библиотеки.
Добавьте проект Xcglogger в качестве подпроекта в ваш проект и добавьте соответствующую библиотеку в качестве зависимости вашей цели. Под General вкладкой вашей цели добавьте XCGLogger.framework и ObjcExceptionBridging.framework в раздел Embedded Binaries .
Затем в каждом исходном файле:
import XCGLoggerВ вашем AppDelegate (или в другом глобальном файле) объявьте глобальную постоянную экземпляр XCGLOGGE по умолчанию.
let log = XCGLogger . defaultВ
application ( _ application : UIApplication , didFinishLaunchingWithOptions launchOptions : [ UIApplicationLaunchOptionsKey : Any ] ? = nil ) // iOS, tvOSили
applicationDidFinishLaunching ( _ notification : Notification ) // macOSфункция, настройте необходимые варианты:
log . setup ( level : . debug , showThreadName : true , showLevel : true , showFileNames : true , showLineNumbers : true , writeToFile : " path/to/file " , fileLevel : . debug ) Значение для writeToFile: может быть String или URL . Если файл уже существует, он будет очищен до того, как мы его используем. Опустите параметр или установите его в nil , чтобы войти только в консоль. При желании вы можете установить другой уровень журнала для вывода файла, используя параметр fileLevel: Установите его на nil или опустите его, чтобы использовать тот же уровень журнала, что и консоль.
Затем, когда вы хотите что -то зарегистрировать, используйте один из методов удобства:
log . verbose ( " A verbose message, usually useful when working on a specific problem " )
log . debug ( " A debug message " )
log . info ( " An info message, probably useful to power users looking in console.app " )
log . notice ( " A notice message " )
log . warning ( " A warning message, may indicate a possible error " )
log . error ( " An error occurred, but it's recoverable, just info about what happened " )
log . severe ( " A severe error occurred, we are likely about to crash now " )
log . alert ( " An alert error occurred, a log destination could be made to email someone " )
log . emergency ( " An emergency error occurred, a log destination could be made to text someone " ) Различные методы устанавливают уровень журнала сообщения. XCGLOGGER будет печатать только сообщения только с уровнем журнала, который выше или равен своим текущим настройкам уровня журнала. Таким образом, регистратор с уровнем .error будет выходить из сообщений журнала только с уровнем .error , .severe , .alert или .emergency .
Xcglogger стремится быть простым в использовании и быстро заработать и работать с 2 строками кода выше. Но это обеспечивает гораздо больший контроль и гибкость.
Регистратор может быть настроен для доставки сообщений журнала в различные пункты назначения. Используя базовую настройку выше, журнал будет выводить сообщения журнала в стандартную консоли отладки XCode и, опционально, файл, если будет предоставлен путь. Вполне вероятно, что вы захотите отправить журналы в более интересные места, такие как Console Apple System, база данных, сторонний сервер или другое приложение, такое как NSLOGGER. Это достигается путем добавления пункта назначения к регистратору.
Вот пример настройки регистратора для вывода в журнал системы Apple, а также файл.
// Create a logger object with no destinations
let log = XCGLogger ( identifier : " advancedLogger " , includeDefaultDestinations : false )
// Create a destination for the system console log (via NSLog)
let systemDestination = AppleSystemLogDestination ( identifier : " advancedLogger.systemDestination " )
// Optionally set some configuration options
systemDestination . outputLevel = . debug
systemDestination . showLogIdentifier = false
systemDestination . showFunctionName = true
systemDestination . showThreadName = true
systemDestination . showLevel = true
systemDestination . showFileName = true
systemDestination . showLineNumber = true
systemDestination . showDate = true
// Add the destination to the logger
log . add ( destination : systemDestination )
// Create a file log destination
let fileDestination = FileDestination ( writeToFile : " /path/to/file " , identifier : " advancedLogger.fileDestination " )
// Optionally set some configuration options
fileDestination . outputLevel = . debug
fileDestination . showLogIdentifier = false
fileDestination . showFunctionName = true
fileDestination . showThreadName = true
fileDestination . showLevel = true
fileDestination . showFileName = true
fileDestination . showLineNumber = true
fileDestination . showDate = true
// Process this destination in the background
fileDestination . logQueue = XCGLogger . logQueue
// Add the destination to the logger
log . add ( destination : fileDestination )
// Add basic app info, version info etc, to the start of the logs
log . logAppDetails ( )Вы можете настроить каждое место назначения журнала с разными параметрами в зависимости от ваших потребностей.
Еще одна распространенная модель использования - иметь несколько регистраторов, возможно, один для проблем пользовательского интерфейса, один для сети, а другой - для проблем с данными.
Каждое место для журнала может иметь свой собственный уровень журнала. В качестве удобства вы можете установить уровень журнала на самом объекте журнала, и он передаст этот уровень каждому пункту назначения. Затем установите направления, которые должны быть разными.
ПРИМЕЧАНИЕ . Объект назначения может быть добавлен только в один объект Logger, добавив его на секунду удалит его с первого.
В качестве альтернативы вы можете использовать закрытие для инициализации своей глобальной переменной, чтобы вся инициализация выполнялась в одном месте
let log : XCGLogger = {
let log = XCGLogger ( identifier : " advancedLogger " , includeDefaultDestinations : false )
// Customize as needed
return log
} ( ) Примечание : это лениво создает объект журнала, что означает, что он не создается, пока он не понадобится. Это задерживает начальный вывод информации о приложении. Из -за этого я рекомендую создать объект журнала при запуске приложения, добавив строку let _ = log в верхней части вашего метода didFinishLaunching , если вы еще не регистрируете что -то при запуске приложения.
Вы можете записать строки:
log . debug ( " Hi there! " )Или почти все, что вы хотите:
log . debug ( true )
log . debug ( CGPoint ( x : 1.1 , y : 2.2 ) )
log . debug ( MyEnum . Option )
log . debug ( ( 4 , 2 ) )
log . debug ( [ " Device " : " iPhone " , " Version " : 7 ] ) Новичок в Xcglogger 4, вы теперь можете создавать фильтры для применения к своему регистратору (или к определенным направлениям). Создайте и настройте свои фильтры (примеры ниже), а затем добавьте их в объекты регистратора или назначения, установив свойство дополнительных filters на массив, содержащий фильтры. Фильтры применяются в том порядке, который они существуют в массиве. Во время обработки каждый фильтр спрашивает, следует ли исключить сообщение журнала из журнала. Если какой -либо фильтр исключает сообщение журнала, оно исключено. Фильтры не имеют возможности отменить исключение другого фильтра.
Если свойство filters назначения равна nil , вместо этого используется свойство filters журнала. Чтобы иметь один журнал назначения все, при этом все другие направления отфильтровали что -то, добавьте фильтры в объект журнала и установите свойство filters одного назначения» в пустой массив [] .
Примечание . В отличие от пунктов назначения, вы можете добавить один и тот же объект фильтра в несколько регистраторов и/или несколько направлений.
Чтобы исключить все сообщения журнала из определенного файла, создайте исключительный фильтр, как SO:
log . filters = [ FileNameFilter ( excludeFrom : [ " AppDelegate.swift " ] , excludePathWhenMatching : true ) ] excludeFrom: принимает Array<String> или Set<String> чтобы вы могли указать несколько файлов одновременно.
excludePathWhenMatching: по умолчанию к true , чтобы вы могли опустить его, если вы тоже не хотите соответствовать пути.
Чтобы включить сообщения журнала только для определенного набора для файлов, создайте фильтр, используя includeFrom: инициализатор. Также можно просто переключить inverse свойство, чтобы перевернуть фильтр исключения в фильтр включения.
Чтобы фильтровать сообщения журнала по тегу, вы, конечно, должны установить тег в сообщениях журнала. Каждое сообщение журнала теперь может иметь дополнительные, определенные пользовательские данные, прикрепленные к ним, которые будут использоваться фильтрами (и/или форматами и т. Д.). Это обрабатывается с помощью userInfo: Dictionary<String, Any> объект. Ключ словаря должен быть строкой с имен, чтобы избежать столкновений с будущими дополнениями. Официальные ключи начнутся с com.cerebralgardens.xcglogger . Ключ тега можно получить с помощью XCGLogger.Constants.userInfoKeyTags . Вы определенно не хотите печатать это, поэтому не стесняйтесь создавать глобальный ярлык: let tags = XCGLogger.Constants.userInfoKeyTags . Теперь вы можете легко пометить свои журналы:
let sensitiveTag = " Sensitive "
log . debug ( " A tagged log message " , userInfo : [ tags : sensitiveTag ] ) Значение для тегов может быть Array<String> , Set<String> или просто String , в зависимости от ваших потребностей. Все они будут работать так же, когда он отфильтрован.
В зависимости от вашего рабочего процесса и использования, вы, вероятно, создаете более быстрые методы для настройки словаря userInfo . См. Ниже для других возможных ярлыков.
Теперь, когда у вас тегите журналы, вы можете легко отфильтровать:
log . filters = [ TagFilter ( excludeFrom : [ sensitiveTag ] ) ] Как и FileNameFilter , вы можете использовать includeFrom: или Toggle inverse чтобы включить только сообщения журнала, которые имеют указанные теги.
Фильтрация разработчиком точно так же, как фильтрация с помощью тега, только используя ключ userInfo XCGLogger.Constants.userInfoKeyDevs . Фактически, оба фильтра являются подклассами класса UserInfoFilter , который вы можете использовать для создания дополнительных фильтров. См. Расширение Xcglogger ниже.
В крупных проектах с несколькими разработчиками, вы, вероятно, захотите начать тегать сообщения журнала, а также указать разработчику, который добавил сообщение.
Несмотря на чрезвычайно гибкий, словарь userInfo может быть немного громоздким в использовании. Есть несколько возможных методов, которые вы можете использовать для простого. Я все еще проверяю их сам, поэтому они еще официально не являются частью библиотеки (я бы хотел отзывы или другие предложения).
Я создал некоторый экспериментальный код, чтобы помочь создать словарь пользователей. (Включите опциональный подпространство UserInfoHelpers , если использует кокопод). Проверьте демо -приложение для iOS, чтобы увидеть его в использовании.
Есть две структуры, которые соответствуют протоколу UserInfoTaggingProtocol . Tag и Dev .
Вы можете создать расширение на каждом из них, которые соответствуют вашему проекту. Например:
extension Tag {
static let sensitive = Tag ( " sensitive " )
static let ui = Tag ( " ui " )
static let data = Tag ( " data " )
}
extension Dev {
static let dave = Dev ( " dave " )
static let sabby = Dev ( " sabby " )
} Наряду с этими типами, есть перегруженный оператор | Это может быть использовано для объединения их в словаре, совместимый с UserInfo: параметр вызовов журнала.
Тогда вы можете регистрировать сообщения, как это:
log . debug ( " A tagged log message " , userInfo : Dev . dave | Tag . sensitive ) Есть некоторые текущие проблемы, которые я вижу с этими UserInfoHelpers , поэтому я сделал это необязательным/экспериментальным на данный момент. Я хотел бы услышать комментарии/предложения для улучшений.
| Сочетает словаря, пока нет никаких Set . Если один из словари содержит Set , он будет использовать один из них, не объединяя их. Предпочитая левую сторону, если обе стороны имеют набор для одного и того же ключа.userInfo: параметр нуждается в словаре, вы не можете передать один объект Dev или Tag. Вам нужно использовать как минимум два с | Оператор, чтобы он автоматически преобразовал в совместимый словарь. Если вам нужен только один тег, например, вы должны получить доступ к параметру .dictionary вручную: userInfo: Tag("Blah").dictionary . Все методы журнала работают при закрытии. Используя тот же синтаксический сахар, что и функция Swift's assert() , этот подход гарантирует, что мы не тратим ресурсы, которые в любом случае не будут выходить, в то же время сохраняя сайт чистого вызова.
Например, следующий оператор журнала не будет тратить ресурсы, если уровень журнала отладки подавлен:
log . debug ( " The description of ( thisObject ) is really expensive to create " ) Точно так же, допустим, вы должны итерации через петлю, чтобы сделать некоторые расчеты, прежде чем регистрировать результат. В Objective-C вы можете поместить этот блок кода между #if #endif и предотвратить запуск кода. Но в Swift ранее вам нужно все еще обрабатывать этот цикл, тратить ресурсы. С XCGLogger это так же просто, как:
log . debug {
var total = 0.0
for receipt in receipts {
total += receipt . total
}
return " Total of all receipts: ( total ) "
} В тех случаях, когда вы хотите выборочно выполнить код, не генерируя строку журнала, возвращайте nil или используйте один из методов: verboseExec , debugExec , infoExec , warningExec , errorExec и severeExec .
Вы можете создать свой собственный объект DateFormatter и назначить его регистратору.
let dateFormatter = DateFormatter ( )
dateFormatter . dateFormat = " MM/dd/yyyy hh:mma "
dateFormatter . locale = Locale . current
log . dateFormatter = dateFormatterXcglogger поддерживает добавление кодов форматирования в сообщения ваших журналов, чтобы включить цвет в разных местах. Оригинальная опция заключалась в том, чтобы использовать плагин Xcodecolors. Тем не менее, Xcode (как версия 8) больше не поддерживает плагины. Вы все еще можете просматривать свои журналы в цвете, только не в XCode в данный момент. Вы можете использовать опору ANSI Color, чтобы добавить цвет в ваши объекты подачи заявки и просмотреть свои журналы через окно терминала. Это дает вам несколько дополнительных вариантов, таких как добавление жирного шрифта, курсив или (пожалуйста, не позволяйте) мигать!
После включения каждый уровень журнала может иметь свой собственный цвет. Эти цвета могут быть настроены по желанию. Если вы используете несколько регистраторов, вы можете альтернативно установить каждый журнал на свой собственный цвет.
Пример настройки форматера ANSI:
if let fileDestination : FileDestination = log . destination ( withIdentifier : XCGLogger . Constants . fileDestinationIdentifier ) as? FileDestination {
let ansiColorLogFormatter : ANSIColorLogFormatter = ANSIColorLogFormatter ( )
ansiColorLogFormatter . colorize ( level : . verbose , with : . colorIndex ( number : 244 ) , options : [ . faint ] )
ansiColorLogFormatter . colorize ( level : . debug , with : . black )
ansiColorLogFormatter . colorize ( level : . info , with : . blue , options : [ . underline ] )
ansiColorLogFormatter . colorize ( level : . notice , with : . green , options : [ . italic ] )
ansiColorLogFormatter . colorize ( level : . warning , with : . red , options : [ . faint ] )
ansiColorLogFormatter . colorize ( level : . error , with : . red , options : [ . bold ] )
ansiColorLogFormatter . colorize ( level : . severe , with : . white , on : . red )
ansiColorLogFormatter . colorize ( level : . alert , with : . white , on : . red , options : [ . bold ] )
ansiColorLogFormatter . colorize ( level : . emergency , with : . white , on : . red , options : [ . bold , . blink ] )
fileDestination . formatters = [ ansiColorLogFormatter ]
} Как и в случае с фильтрами, вы можете использовать одни и те же объекты Formatter для нескольких регистраторов и/или нескольких направлений. Если свойство formatters назначения равна nil , вместо этого будет использоваться свойство formatters Logger.
См. Extending Xcglogger ниже для получения информации о создании собственных пользовательских форматов.
Используя флаги Swift Build, различные уровни журналов могут использоваться при отладке по сравнению с постановкой/производством. Перейдите в настройки сборки -> Swift Compiler -Custom Flags -> Другие Flift Flags и добавьте -DDEBUG к записи отладки.
#if DEBUG
log . setup ( level : . debug , showThreadName : true , showLevel : true , showFileNames : true , showLineNumbers : true )
#else
log . setup ( level : . severe , showThreadName : true , showLevel : true , showFileNames : true , showLineNumbers : true )
#endif Вы можете установить любое количество опций аналогичным образом. См. Обновленное приложение iosdemo для примера использования различных направлений журнала на основе параметров, поиск USE_NSLOG .
По умолчанию предоставленные направления для журнала будут обрабатывать журналы в потоке, в котором они вызываются. Это для обеспечения того, чтобы сообщение журнала отображалось немедленно при отладке приложения. Вы можете добавить точку останова сразу после журнала и увидеть результаты, когда попадает точка останова.
Однако, если вы не отлаживаете приложение, обработка журналов в текущем потоке может представить HIT. Теперь вы можете указать процесс назначения в его журналах в очереди для отправки по вашему выбору (или даже использовать поставленную по умолчанию).
fileDestination . logQueue = XCGLogger . logQueueили даже
fileDestination . logQueue = DispatchQueue . global ( qos : . background )Это работает очень хорошо в сочетании с методом альтернативных конфигураций выше.
#if DEBUG
log . setup ( level : . debug , showThreadName : true , showLevel : true , showFileNames : true , showLineNumbers : true )
#else
log . setup ( level : . severe , showThreadName : true , showLevel : true , showFileNames : true , showLineNumbers : true )
if let consoleLog = log . logDestination ( XCGLogger . Constants . baseConsoleDestinationIdentifier ) as? ConsoleDestination {
consoleLog . logQueue = XCGLogger . logQueue
}
#endifПри использовании расширенной конфигурации журнала (см. Расширенное использование выше), вы теперь можете указать, что регистратор добавляет к существующему файлу журнала, вместо того, чтобы автоматически перезаписать его.
Добавьте необязательный shouldAppend: параметр при инициализации объекта FileDestination . Вы также можете добавить параметр appendMarker: добавить маркер в файл журнала, указывающий, где начал добавлять новый экземпляр вашего приложения. По умолчанию мы добавим -- ** ** ** -- Если параметр опущен. Установите его на nil , чтобы пропустить добавление маркера.
let fileDestination = FileDestination(writeToFile: "/path/to/file", identifier: "advancedLogger.fileDestination", shouldAppend: true, appendMarker: "-- Relauched App --")
При входе в файл у вас есть возможность автоматически повернуть файл журнала в архивное место назначения и позволить журналу автоматически создавать новый файл журнала вместо старого.
Создайте пункт назначения с использованием класса AutoRotatingFileDestination и установите следующие свойства:
targetMaxFileSize : Auto вращается после того, как файл будет больше, чем этот
targetMaxTimeInterval : Auto votate через много секунд
targetMaxLogFiles : количество архивных файлов журнала для сохранения, более старые автоматически удаляются
Все это руководящие принципы для регистрации, а не жесткие ограничения.
Вы можете создать альтернативные направления для журнала (помимо встроенных). Ваш пользовательский пункт назначения журнала должен реализовать протокол DestinationProtocol . Создайте свой объект, настройте его, а затем добавьте его в объект XCGLogger с помощью add(destination:) . Существует два класса базовых пунктов назначения ( BaseDestination и BaseQueuedDestination ), от которых вы можете унаследовать, чтобы справиться с большей частью процесса для вас, требуя от вас реализации только одного дополнительного метода в своем пользовательском классе. Взгляните на ConsoleDestination и FileDestination примеров.
Вы также можете создавать пользовательские фильтры или форматер. Взгляните на предоставленные версии в качестве отправной точки. Обратите внимание, что фильтры и форматер имеют возможность изменять сообщения журнала при обработке. Это означает, что вы можете создать фильтр, который снимает пароли, выделяет конкретные слова, шифрует сообщения и т. Д.
Xcglogger - лучший регистратор, доступный для Swift из -за вклада сообщества, как вы. Есть много способов, которыми вы можете помочь продолжать делать это великолепным.
Примечание . При отправке запроса на привлечение, пожалуйста, используйте множество небольших стихов, один огромный коммит. Это значительно облегчает слияние, когда есть несколько запросов на притяжение, которые необходимо объединить для новой версии.
Если вы найдете эту библиотеку полезной, вы обязательно найдете этот другой инструмент полезным:
WATCHDOG: https://watchdogforxcode.com/
Кроме того, пожалуйста, ознакомьтесь с некоторыми другими моими проектами:
Журнал изменения теперь в своем собственном файле: Changelog.md