
XcGloggerは、Swiftプロジェクトで使用するオリジナルのデバッグログモジュールです。
SwiftにはC Preprocessorが含まれていないため、開発者はObjective-Cで使用するデバッグログ#defineマクロを使用できません。これは、素敵なデバッグログを生成する従来の方法が機能しなくなったことを意味します。単なる古い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 。 Carthageのインストールと使用の詳細については、プロジェクトページをご覧ください。
Swiftで5.0以上を実行している開発者は、 $(SRCROOT)/Carthage/Build/iOS/ObjcExceptionBridging.frameworkをコピーCarthage Frameworksビルドフェーズに入力ファイルに追加する必要があります。
Podfileに次の線に似たものを追加します。プラットフォーム、バージョン/ブランチなどに基づいて調整する必要がある場合があります。
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '12.0'
use_frameworks!
pod 'XCGLogger', '~> 7.1.5'
POD XCGLogger単独で指定するには、コアフレームワークが含まれます。オプションのコンポーネントを含めることができるように、サブペックを追加し始めています。
pod 'XCGLogger/UserInfoHelpers', '~> 7.1.5' :userInfo辞書を使用してログメッセージにタグを付けるのに役立つ実験コードを含めます。
次に、 pod installを実行します。 Cocoapodsのインストールと使用の詳細については、公式のWebサイトをご覧ください。
注:cocoapods 1.4.0の前に、Swiftバージョンの混合で複数のポッドを使用することはできませんでした。各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 XCGLoggerAppDelegate(またはその他のグローバルファイル)で、デフォルトのXcGloggerインスタンスにグローバル定数を宣言します。
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に設定するか、コンソールと同じログレベルを使用するように省略します。
次に、何かを記録したいときはいつでも、便利な方法の1つを使用してください。
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デバッグコンソールにログメッセージを出力し、オプションでパスが提供されている場合はファイルになります。 Appleシステムコンソール、データベース、サードパーティサーバー、または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 ( )ニーズに応じて、各ログの宛先を異なるオプションで構成できます。
もう1つの一般的な使用パターンは、複数のロガーを持つことです。1つはUIの問題、1つはネットワーク用、もう1つはデータの問題です。
各ログの宛先は、独自のログレベルを持つことができます。便宜上、ログオブジェクト自体にログレベルを設定でき、各宛先にそのレベルを渡すことができます。次に、異なる必要がある目的地を設定します。
注:宛先オブジェクトは1つのロガーオブジェクトにのみ追加でき、1秒に追加すると、最初から削除されます。
または、閉鎖を使用してグローバル変数を初期化して、すべての初期化が1か所で行われるようにすることができます
let log : XCGLogger = {
let log = XCGLogger ( identifier : " advancedLogger " , includeDefaultDestinations : false )
// Customize as needed
return log
} ( )注:これにより、ログオブジェクトがゆっくりと作成されます。つまり、実際に必要になるまで作成されないことを意味します。これにより、アプリ情報の詳細の初期出力が遅れます。このため、アプリの起動にまだログを記録していない場合は、 let _ = log didFinishLaunchingメソッドにLET _ = LET LET LET LET LET LET LET LET LET LET LET LETを追加することにより、ログオブジェクトをアプリの起動時に作成することを強制することをお勧めします。
文字列を記録できます。
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プロパティが使用されます。 1つの宛先を記録するには、他のすべての宛先が何かをフィルタリングしながら、フィルターをログオブジェクトに追加し、1つの宛先のfiltersプロパティを空の配列に設定します[] 。
注:宛先とは異なり、同じフィルターオブジェクトを複数のロガーおよび/または複数の宛先に追加できます。
特定のファイルからすべてのログメッセージを除外するには、次のような除外フィルターを作成します。
log . filters = [ FileNameFilter ( excludeFrom : [ " AppDelegate.swift " ] , excludePathWhenMatching : true ) ] excludeFrom: Array<String>またはSet<String>して、複数のファイルを同時に指定できるようにします。
excludePathWhenMatching:デフォルトはtrueであるため、パスも一致させたくない限り省略できます。
ファイルに特定のセットに対してのみログメッセージを含めるには、 includeFrom: initializerを使用してフィルターを作成します。 inverseプロパティを切り替えて、除外フィルターをインクルージョンフィルターに反転することもできます。
タグでログメッセージをフィルタリングするには、もちろんログメッセージにタグを設定できる必要があります。各ログメッセージには、フィルター(および/またはフォーマッタなど)で使用される追加のユーザー定義データが添付されるようになりました。これはuserInfo: Dictionary<String, Any> objectで処理されます。辞書キーは、将来の追加との衝突を避けるために、名前付き文字列である必要があります。公式キーは、 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を使用して、指定されたタグを持つログメッセージのみを含めることができます。
開発者によるフィルタリングは、 XCGLogger.Constants.userInfoKeyDevsのuserInfoキーを使用するみを使用して、タグによるフィルタリングとまったく同じです。実際、両方のフィルターは、追加のフィルターを作成するために使用できるUserInfoFilterクラスのサブクラスです。以下のXcGloggerの拡張を参照してください。
複数の開発者との大規模なプロジェクトでは、おそらくログメッセージのタグを開始するだけでなく、メッセージを追加した開発者に示すことをお勧めします。
非常に柔軟ですが、 userInfo辞書は使用するのが少し面倒です。単に物事に使用できるいくつかの可能な方法があります。私はまだこれらを自分でテストしているので、それらはまだライブラリの一部ではありません(フィードバックやその他の提案が大好きです)。
userinfo辞書の作成に役立つ実験コードを作成しました。 (ココアポッドを使用している場合は、オプションのUserInfoHelpers subspecを含めます)。 iOSデモアプリを確認して使用していることを確認してください。
UserInfoTaggingProtocolプロトコルに準拠する2つの構造体があります。 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がない限り、辞書をマージします。辞書の1つにSetが含まれている場合、それらの1つをマージせずに使用します。両側に同じキーのセットがある場合は、左側を好みます。userInfo:パラメーターには辞書が必要なため、単一の開発オブジェクトまたはタグオブジェクトを渡すことはできません。 |で少なくとも2つを使用する必要があります。互換性のある辞書に自動的に変換するオペレーター。たとえば、1つのタグのみが必要な場合は、 .dictionaryパラメーターに手動でアクセスする必要があります。userinfo userInfo: Tag("Blah").dictionary 。すべてのログメソッドは閉鎖で動作します。 Swiftの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を返したり、Methodのいずれかを使用したりする場合は、 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カラーサポートを使用して、ファイリングオブジェクトに色を追加し、端末ウィンドウを介してログを表示できます。これにより、大胆なイタリック体、または(しないでください)瞬きなどの追加のオプションが提供されます!
有効になると、各ログレベルは独自の色を持つことができます。これらの色は、必要に応じてカスタマイズできます。複数のロガーを使用している場合、それぞれのロガーを独自の色に設定することができます。
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 ]
}フィルターと同様に、複数のロガーや複数の宛先に同じフォーマッタオブジェクトを使用できます。目的地のformattersプロパティがnilの場合、代わりにロガーのformattersプロパティが使用されます。
独自のカスタムフォーマッタの作成に関する情報については、以下の拡張XcGloggerを参照してください。
Swiftビルドフラグを使用することにより、デバッグとステージング/制作に異なるログレベルを使用できます。ビルド設定に移動します - > Swiftコンパイラ - カスタムフラグ - >その他のSwiftフラグを-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任意の数のオプションを同様の方法で設定できます。オプションに基づいてさまざまなログの宛先を使用する例については、 USE_NSLOGを検索する例については、更新されたiOSDEMOアプリを参照してください。
デフォルトでは、付属のログ宛先は、呼び出されたスレッドのログを処理します。これは、アプリケーションをデバッグするときにすぐにログメッセージが表示されるようにするためです。ログコールの直後にブレークポイントを追加して、ブレークポイントがヒットしたときに結果を確認できます。
ただし、アプリケーションを積極的にデバッグしていない場合は、現在のスレッドのログを処理すると、パフォーマンスヒットが導入される可能性があります。これで、宛先プロセスにログを指定して、選択したディスパッチキューにログが表示されます(または、デフォルトの提供されたものを使用します)。
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ロガーの詳細な構成を使用する場合(上記の高度な使用法を参照)、自動的に上書きする代わりに、ロガーが既存のログファイルに追加されることを指定できるようになりました。
Optional shouldAppend: ParameterをFileDestinationオブジェクトを初期化するときに追加します。 appendMarker:パラメーターを追加して、アプリの新しいインスタンスがアプリを開始した場所を示すログファイルにマーカーを追加することもできます。デフォルトでは、パラメーターが省略されている場合-- ** ** ** --を追加します。マーカーのアプリをスキップするには、それをnilに設定します。
let fileDestination = FileDestination(writeToFile: "/path/to/file", identifier: "advancedLogger.fileDestination", shouldAppend: true, appendMarker: "-- Relauched App --")
ファイルにログすると、ログファイルをアーカイブされた宛先に自動的に回転させ、ロガーに古いログファイルの代わりに新しいログファイルを自動的に作成するオプションがあります。
AutoRotatingFileDestinationクラスを使用して宛先を作成し、次のプロパティを設定します。
targetMaxFileSize :ファイルがこれよりも大きいと自動回転
targetMaxTimeInterval :この数秒後に自動回転します
targetMaxLogFiles :保持するアーカイブされたログファイルの数、古いログファイルは自動的に削除されます
これらはすべて、ロガーのガイドラインであり、厳しい制限ではありません。
代替ログの目的地を作成できます(組み込みの宛先以外)。カスタムログの宛先は、 DestinationProtocolプロトコルを実装する必要があります。オブジェクトをインスタンス化して構成し、 add(destination:)でXCGLoggerオブジェクトに追加します。 2つのベースの宛先クラス( BaseDestinationとBaseQueuedDestination )があります。ほとんどのプロセスを処理するために継承することができ、カスタムクラスに1つの追加方法のみを実装する必要があります。例については、 ConsoleDestinationとFileDestinationをご覧ください。
カスタムフィルターまたはフォーマッタを作成することもできます。開始点として提供されたバージョンを見てください。フィルターとフォーマッタには、ログメッセージが処理されたときに変更する機能があることに注意してください。これは、パスワードをストリップし、特定の単語を強調し、メッセージを暗号化するなどのフィルターを作成できることを意味します。
XcGloggerは、あなたのようなコミュニティからの貢献により、Swiftが利用できる最高のロガーです。それを素晴らしいものにし続けるのを助けることができる多くの方法があります。
注:プルリクエストを送信するときは、1つの大きなコミットメントの節をたくさん使用してください。新しいバージョンには組み合わせる必要があるいくつかのプルリクエストがある場合、マージするのがはるかに簡単になります。
このライブラリが役立つと思う場合は、この他のツールが役立つことは間違いありません。
ウォッチドッグ:https://watchdogforxcode.com/
また、私の他のプロジェクトのいくつかをチェックしてください:
変更ログは独自のファイルにあります:changelog.md