Xcode 日志存儲在擴展名為.xcactivitylog
。 文件內容是經過一種 SLF
的編碼格式進行壓縮過的。可以通過gzip -cd 展開。在Logs/Build下有一個LogStoreManifest.plist文件,終端plutil -p 打開,里面會有很多字段,其中timeStartedRecording 655351382.847489 需要使用timeIntervalSinceReferenceDate方法還原時間戳
SLF 格式
SLF文檔的頭部以SLF0開始。在header之后,文檔有一組編碼過的值。SLF編碼格式支持以下類型:
- Integer
- Double
- String
- Array
- Class names
- Class instances
- Null
編碼的值由 3 部分組成:
- 左側值(可選)
- 字符類型分隔符
- 右側值(可選)
Integer
- 字符類型分隔符:
#
- 例子:
200#
- 左側值:一個無符號的 64 位整數。
Double
- 字符類型分隔符:
^
- 例子:
afd021ebae48c141^
- 左側值:以十六進制編碼的小端浮點數。
可以使用以下bitPattern
屬性將其轉換為 Swift Double Double
:
guard let value = UInt64(input, radix: 16) else {
return nil
}
let double = Double(bitPattern: value.byteSwapped)
在xcactivitylog
的文件中,這種類型的值用于編碼時間戳。因此,double 表示使用 的timeInterval
值timeIntervalSinceReferenceDate
。
Null
- 字符類型分隔符:
-
- 沒有左邊,也沒有右邊的值
String
- 字符類型分隔符:
"
- 例子:
5"Hello
- 左側值:一個Integer,表示字符串的長度
- 右側值:
String
字符的數量在NSString中有效,但在String中無效,因為它計算字符串的UTF-16表示中的16 bit單元,而不是像在Swift的String中那樣計算字符串中的Unicode擴展字符集群的數量。
所以使用 UTF-8 對SLF格式進行字符串加載會記數不匹配,可以通過加載為 ASCII 字符串避免該問題:
let content = String(data: unzippedXcactivitylog, encoding: .ascii)
其他示例: 6"Hello--9#
在這種情況下,有三個編碼值:
- 字符串“Hello-”
- Null
- 整數 9。
Array
- 字符類型分隔符:
(
- 例子:
22(
- 左側值:一個表示數組的元素數量的整數
Array
的節點是Class instances
Class name
- 字符類型分隔符:
%
- 例子:
21%IDEActivityLogSection
- 左側值:類名字符個數的整數
- 右側值:
Class name
它遵循與String
相同的規則。
一個給定Class name
只出現一次:在它的第一個Class instance
. 在日志中存儲Class名稱的順序很重要,因為Class instance使用該索引
Class instance
- 字符類型分隔符:
@
- 例子:
2@
- 左側值:具有類實例類型的類名索引的整數。
在上述的2@
情況下,意味著Class instance的類型是在SLF文檔中第3個位置找到的Class name。
Tokenizing .xcactivitylog
使用這些規則,可以解碼日志并將其標記化。例如:
SLF010#21%IDEActivityLogSection1@0#39"Xcode.IDEActivityLogDomainType.BuildLog20"Build XCLogParserApp20"Build XCLogParserApp0074f8eaae48c141^8f19bcf4ae48c141^12(1@1#50"Xcode.IDEActivityLogDomainType.XCBuild.Preparation13"Prepare build13"Prepare build
可以獲得這些token:
[type: "int", value: 10],
[type: "className", name: "IDEActivityLogSection"],
[type: "classInstance", className: "IDEActivityLogSection"],
[type: "int", value: 0],
[type: "string", value: "Xcode.IDEActivityLogDomainType.BuildLog"],
[type: "string", value: "Build XCLogParserApp"],
[type: "string", value: "Build XCLogParserApp"],
[type: "double", value: 580158292.767495],
[type: "double", value: 580158295.086277],
[type: "array", count: 12],
[type: "classInstance", className: "IDEActivityLogSection"],
[type: "string", value: "Xcode.IDEActivityLogDomainType.XCBuild.Preparation"],
[type: "string", value: "Prepare build"],
[type: "string", value: "Prepare build"],
第一個整數是所用SLF
格式的版本。在 Xcode 10.x 和 11 Beta 中,version 為 10。version 后面的值是日志的實際內容。