XCLogParser 是一个命令行工具,用于解析 Xcode 和 xcodebuild
使用的 SLF
序列化格式,该格式用于存储其构建和测试日志 (xcactivitylog
文件)。
您可以在这里找到有关日志中使用格式的更多信息。您也可以查看 Erick Camacho 在 AltConf 2019 上的演讲。
该工具支持创建不同类型的报告来分析日志的内容。 XCLogParser 可以提供关于项目中每个模块和文件的构建时间、警告、错误和单元测试结果的大量见解。
这是一个从 Kickstarter iOS 开源应用程序的构建日志创建的报告示例。
XCLogParser
是一个使用 SPM 编写的可执行文件,它支持三个命令
xcactivitylog
的内容转储到 JSON
文档中。xcactivitylog
的内容解析成不同类型的报告 (json
、flatJson
、summaryJson
、chromeTracer
、issues
和 html
)。LogStoreManifest.plist
文件的 Manifest 内容转储到 JSON
文档中。根据您的需求,有多种使用场景可以使用 XCLogParser
帮助您
您可以使用命令 rake build[debug]
或 rake build[release]
编译可执行文件,或者直接使用 Swift Package Manager 命令。 您还可以运行 rake install
将可执行文件安装到您的 /usr/local/bin
目录中。
$ brew install xclogparser
我们目前正在努力添加更多安装选项。
您可以使用 post-scheme 构建操作来自动化 xcactivitylog
文件的解析。 这样,一旦构建完成,就可以立即解析最新的构建日志。 为此,请在项目中打开 scheme 编辑器,然后展开左侧的“Build”面板。 然后,您可以添加一个新的“Post-action”运行脚本,并使用所需的参数调用 xclogparser
可执行文件
xclogparser parse --project MyApp --reporter html
此脚本假定 xclogparser
可执行文件已安装并在您的 PATH 中。
运行脚本由 Xcode 在临时目录中执行,因此您可能会发现立即使用 open MyAppLogs
在脚本末尾打开生成的输出非常有用。 构建完成后,Finder 将自动打开输出文件夹,然后您可以查看生成的 HTML 页面,其中包含您构建过程的精美可视化! ✨
-resultBundlePath
时,xcodebuild
才会生成 .xcactivitylog 构建日志。 如果您使用该命令而不是 Xcode 进行编译,请务必将该选项设置为以 .xcresult
结尾的有效路径。launcher
脚本,并从您的 post-scheme 操作中按如下方式调用它:launcher command-that-parses-the-log-here
#!/bin/sh
# The first argument is the directory of the executable you want to run.
# The following arguments are directly forwarded to the executable.
# We execute the command in the background and immediately close the input, output
# and error streams in order to let Xcode and xcodebuild finish cleanly.
# This is done to prevent Xcode and xcodebuild being stuck in waiting for all
# subprocesses to end before exiting.
executable=$1
shift;
$executable "$@" <&- >&- 2>&- &
BuildAction
中将属性 runPostActionsOnFailure
设置为 YES
,如下所示<BuildAction buildImplicitDependencies='YES' parallelizeBuildables='YES' runPostActionsOnFailure='YES'>
xcactivitylog
文件由 Xcode/xcodebuild
在构建完成后几秒钟创建。 日志位于 DerivedData/YourProjectName-UUID/Logs/Build
目录中。 它是使用 gzip 压缩的 SLF
格式的二进制文件。
在同一目录中,您将找到一个 LogStoreManifest.plist
文件,其中包含为项目生成的所有 xcactivitylog
文件的列表。 可以监视此文件,以便在每次新日志准备就绪时收到通知。
测试日志在 DerivedData/YourProjectName-UUID/Logs/Test
目录中创建。 Xcode 和 xcodebuild
创建不同的日志。 您可以在这篇 博客文章中找到关于创建哪些日志的很好的描述。
将 xcactivitylog
文件的全部内容转储为 JSON
文档。 如果您想要一个原始但易于解析的日志表示形式,您可以使用此命令。
例子
xclogparser dump --file path/to/log.xcactivitylog --output activity.json
xclogparser dump --project MyProject --output activity.json --redacted
为了简洁起见,已省略示例输出,因为它可能包含有关构建的大量信息。
参数名 | 描述 | 必需 |
---|---|---|
--file |
xcactivitylog 的路径。 |
否 * |
--project |
如果您不知道日志的路径,则为项目名称。 该工具将尝试在 DerivedData 目录中以该名称开头的文件夹中查找最新的构建日志。 使用 --strictProjectName 进行更严格的名称匹配。 |
否 * |
--workspace |
如果您不知道日志的路径,则为 xcworkspace 文件的路径。 它将使用 Xcode 的哈希算法为 DerivedData 文件夹中的项目生成文件夹名称,并将尝试在该目录中找到最新的构建日志。 |
否 * |
--xcodeproj |
如果您不知道日志的路径,并且项目没有 xcworkspace 文件,则为 xcodeproj 文件的路径。 它将使用 Xcode 的哈希算法为 DerivedData 文件夹中的项目生成文件夹名称,并将尝试在该目录中找到最新的构建日志。 |
否 * |
--derived_data |
如果您使用 xcodebuild 构建项目时使用了 -derivedDataPath 选项,则为 derived data 文件夹的路径。 |
否 |
--output |
如果指定,JSON 文件将写入给定的路径。 如果未定义,该命令将输出到标准输出。 | 否 |
--redacted |
如果指定,用户名将在日志中包含的文件路径中被替换为单词 redacted 。 出于隐私原因很有用,但会稍微降低性能。 |
否 |
--without_build_specific_info |
如果指定,则将从日志中删除特定于构建的信息(例如,DerivedData/Product-bolnckhlbzxpxoeyfujluasoupft/Build 中的 bolnckhlbzxpxoeyfujluasoupft 将被删除)。 用于按其内容对日志进行分组非常有用。 |
否 |
--strictProjectName |
与 --project 结合使用。 如果指定,则将对项目名称进行更严格的名称匹配。 |
否 |
否 *: 必须提供
--file
、--project
、--workspace
、--xcodeproj
参数之一。
从 xcactivitylog
解析构建信息,并将其转换为不同的表示形式,例如 JSON 文件、扁平 JSON 文件、摘要 JSON 文件、问题 JSON 文件、Chrome Tracer 文件或静态 HTML 页面。
如果将某些标志传递给 Xcode/xcodebuild,此命令支持解析其他数据
swiftc
报告的编译时间。 要使用该功能,您需要使用选项 -Xfrontend -debug-time-expression-type-checking
和 -Xfrontend -debug-time-function-bodies
构建项目。-Xlinker -print_statistics
添加到 Xcode 的“Other Linker Flags”来生成统计信息,这对于跟踪链接时间回归非常有用。-ftime-trace
标志后,clang 将为每个转换单元生成一个 json
跟踪文件,XCLogParser 将收集它们并将数据添加到解析器输出。例子
xclogparser parse --project MyApp --reporter json --output build.json
xclogparser parse --file /path/to/log.xcactivitylog --reporter chromeTracer
xclogparser parse --workspace /path/to/MyApp.xcworkspace --derived_data /path/to/custom/DerivedData --reporter html --redacted
示例输出可在 reporters 部分中找到。
参数名 | 描述 | 必需 |
---|---|---|
--reporter |
用于转换日志的 reporter。 它可以是 json 、flatJson 、summaryJson 、chromeTracer 、issues 或 html 。(必需) |
是 |
--file |
xcactivitylog 的路径。 |
否 * |
--project |
如果您不知道日志的路径,则为项目名称。 该工具将尝试在 DerivedData 目录中以该名称开头的文件夹中查找最新的构建日志。 使用 --strictProjectName 进行更严格的名称匹配。 |
否 * |
--workspace |
如果您不知道日志的路径,则为 xcworkspace 文件的路径。 它将使用 Xcode 的哈希算法为 DerivedData 文件夹中的项目生成文件夹名称,并将尝试在该目录中找到最新的构建日志。 |
否 * |
--xcodeproj |
如果您不知道日志的路径,并且项目没有 xcworkspace 文件,则为 xcodeproj 文件的路径。 它将使用 Xcode 的哈希算法为 DerivedData 文件夹中的项目生成文件夹名称,并将尝试在该目录中找到最新的构建日志。 |
否 * |
--derived_data |
如果您使用 xcodebuild 构建项目时使用了 -derivedDataPath 选项,则为 derived data 文件夹的路径。 |
否 |
--output |
如果指定,JSON 文件将写入给定的路径。 如果未定义,该命令将输出到标准输出。 | 否 |
--rootOutput |
如果指定,HTML 文件将写入给定的文件夹,如果该文件夹不存在,则它优先于 output ,并且将被创建。 它适用于相对主目录路径 ~ |
否 |
--redacted |
如果指定,用户名将在日志中包含的文件路径中被替换为单词 redacted 。 出于隐私原因很有用,但会稍微降低性能。 |
否 |
--without_build_specific_info |
如果指定,则将从日志中删除特定于构建的信息(例如,DerivedData/Product-bolnckhlbzxpxoeyfujluasoupft/Build 中的 bolnckhlbzxpxoeyfujluasoupft 将被删除)。 用于按其内容对日志进行分组非常有用。 |
否 |
--strictProjectName |
与 --project 结合使用。 如果指定,则将对项目名称进行更严格的名称匹配。 |
否 |
--machine_name |
如果指定,计算机名称将用于创建 buildIdentifier 。 如果未指定,将使用主机名。 |
否 |
--omit_warnings |
省略最终报告中的警告详细信息。 如果警告太多并且报告的大小太大,这将非常有用。 | 否 |
--omit_notes |
省略最终报告中的注释详细信息。 如果注释太多并且报告的大小太大,这将非常有用。 | 否 |
--trunc_large_issues |
如果单个任务有超过 100 个问题(警告、注释、错误),则将其截断为 100 个。这对于减少使用的内存量很有用。 | 否 |
否 *: 必须提供
--file
、--project
、--workspace
、--xcodeproj
参数之一。
以 JSON 格式输出 LogStoreManifest.plist
的内容,该文件列出了为项目生成的所有 xcactivitylog
文件。
例子
xclogparser manifest --project MyApp
示例输出
{
"scheme" : "MyApp",
"timestampEnd" : 1548337458,
"fileName" : "D6539DED-8AC8-4508-9841-46606D0C794A.xcactivitylog",
"title" : "Build MyApp",
"duration" : 46,
"timestampStart" : 1548337412,
"uniqueIdentifier" : "D6539DED-8AC8-4508-9841-46606D0C794A",
"type" : "xcode"
}
参数名 | 描述 | 必需 |
---|---|---|
--log_manifest |
现有 LogStoreManifest.plist 的路径。 |
否 * |
--project |
如果您不知道日志的路径,则为项目名称。 该工具将尝试在 DerivedData 目录中以该名称开头的文件夹中查找最新的构建日志。 使用 --strictProjectName 进行更严格的名称匹配。 |
否 * |
--workspace |
如果您不知道日志的路径,则为 xcworkspace 文件的路径。 它将使用 Xcode 的哈希算法为 DerivedData 文件夹中的项目生成文件夹名称,并将尝试在该目录中找到最新的构建日志。 |
否 * |
--xcodeproj |
如果您不知道日志的路径,并且项目没有 xcworkspace 文件,则为 xcodeproj 文件的路径。 它将使用 Xcode 的哈希算法为 DerivedData 文件夹中的项目生成文件夹名称,并将尝试在该目录中找到最新的构建日志。 |
否 * |
--derived_data |
如果您使用 xcodebuild 构建项目时使用了 -derivedDataPath 选项,则为 derived data 文件夹的路径。 |
否 |
--output |
如果指定,JSON 文件将写入给定的路径。 如果未定义,该命令将输出到标准输出。 | 否 |
--strictProjectName |
与 --project 结合使用。 如果指定,则将对项目名称进行更严格的名称匹配。 |
否 |
否 *: 必须提供
--log-manifest
、--project
、--workspace
、--xcodeproj
参数之一。
parse 命令 内置了不同类型的 reporter,可以表示和可视化日志数据
此 reporter 解析日志并将其输出为 JSON。 它包含有关构建中每个步骤的持续时间的信息,以及其他元数据和有趣的信息,例如错误和警告。
例子
xclogparser parse --project MyApp --reporter json
{
"detailStepType" : "swiftCompilation",
"startTimestamp" : 1545143336.649699,
"endTimestamp" : 1545143336.649699,
"schema" : "MyApp",
"domain" : "com.apple.dt.IDE.BuildLogSection",
"parentIdentifier" : "095709ba230e4eda80ab43be3b68f99c_1545299644.4805899_20",
"endDate" : "2018-12-18T14:28:56.650000+0000",
"title" : "Compile \/Users\/<redacted>\/projects\/MyApp\/Libraries\/Utilities\/Sources\/Disposables\/Cancelable.swift",
"identifier" : "095709ba230e4eda80ab43be3b68f99c_1545299644.4805899_185",
"signature" : "CompileSwift normal x86_64 \/Users\/<redacted>\/MyApp\/Libraries\/Utilities\/Sources\/Disposables\/Cancelable.swift",
"type" : "detail",
"buildStatus" : "succeeded",
"subSteps" : [
],
"startDate" : "2018-12-18T14:28:56.650000+0000",
"buildIdentifier" : "095709ba230e4eda80ab43be3b68f99c_1545299644.4805899",
"machineName" : "095709ba230e4eda80ab43be3b68f99c",
"duration" : 5.5941859483718872,
"errors" : "",
"warnings" : "",
"errorCount" : 0,
"warningCount" : 0,
"errors" : [],
"warnings" : [],
"swiftFunctionTimes" : [
{
"durationMS" : 0.08,
"occurrences" : 5,
"startingColumn" : 36,
"startingLine" : 48,
"file" : "file:\/\/\/Users\/<redacted>\/MyApp\/Libraries\/Utilities\/Sources\/Disposables\/Cancelable.swift",
"signature" : "getter description"
}
],
"swiftTypeCheckTimes" : [
{
"durationMS" : 0.5,
"occurrences" : 2,
"startingColumn" : 16,
"startingLine" : 9,
"file" : "file:\/\/\/Users\/<redacted>\/MyApp\/Libraries\/Utilities\/Sources\/Disposables\/Cancelable.swift",
}
]
}
有关每个字段的更多信息,请查看 JSON 格式文档。
将日志解析为 JSON 对象数组,没有嵌套步骤(字段 subSteps
始终为空)。 将数据转储到数据库中以便于分析非常有用。
数组中 JSON 对象的格式与 json
reporter 中使用的格式相同。
例子
xclogparser parse --file path/to/log.xcactivitylog --reporter flatJson
[
{
"parentIdentifier" : "",
"title" : "Build MobiusCore",
"warningCount" : 0,
"duration" : 0,
"startTimestamp" : 1558590748,
"signature" : "Build MobiusCore",
"endDate" : "2019-05-23T05:52:28.274000Z",
"errorCount" : 0,
"domain" : "Xcode.IDEActivityLogDomainType.BuildLog",
"type" : "main",
"identifier" : "68a2bbd0048a454d91b3734b5d5dc45e_1558640253_1",
"buildStatus" : "succeeded",
"schema" : "MobiusCore",
"subSteps" : [
],
"endTimestamp" : 1558590748,
"architecture" : "",
"machineName" : "68a2bbd0048a454d91b3734b5d5dc45e",
"buildIdentifier" : "68a2bbd0048a454d91b3734b5d5dc45e_1558640253",
"startDate" : "2019-05-23T05:52:28.244000Z",
"documentURL" : "",
"detailStepType" : "none"
},
{
"parentIdentifier" : "68a2bbd0048a454d91b3734b5d5dc45e_1558640253_1",
"title" : "Prepare build",
"warningCount" : 0,
"duration" : 0,
"startTimestamp" : 1558590748,
"signature" : "Prepare build",
"endDate" : "2019-05-23T05:52:28.261000Z",
"errorCount" : 0,
"domain" : "Xcode.IDEActivityLogDomainType.XCBuild.Preparation",
"type" : "target",
"identifier" : "68a2bbd0048a454d91b3734b5d5dc45e_1558640253_2",
"buildStatus" : "succeeded",
"schema" : "MobiusCore",
"subSteps" : [
],
"endTimestamp" : 1558590748,
"architecture" : "",
"machineName" : "68a2bbd0048a454d91b3734b5d5dc45e",
"buildIdentifier" : "68a2bbd0048a454d91b3734b5d5dc45e_1558640253",
"startDate" : "2019-05-23T05:52:28.254000Z",
"documentURL" : "",
"detailStepType" : "none"
},{
"parentIdentifier" : "68a2bbd0048a454d91b3734b5d5dc45e_1558640253_1",
"title" : "Build target MobiusCore",
"warningCount" : 0,
"duration" : 4,
"startTimestamp" : 1558590708,
"signature" : "MobiusCore-fmrwijcuutzbrmbgantlsfqxegcg",
"endDate" : "2019-05-23T05:51:51.890000Z",
"errorCount" : 0,
"domain" : "Xcode.IDEActivityLogDomainType.target.product-type.framework",
"type" : "target",
"identifier" : "68a2bbd0048a454d91b3734b5d5dc45e_1558640253_3",
"buildStatus" : "succeeded",
"schema" : "MobiusCore",
"subSteps" : [
],
"endTimestamp" : 1558590712,
"architecture" : "",
"machineName" : "68a2bbd0048a454d91b3734b5d5dc45e",
"buildIdentifier" : "68a2bbd0048a454d91b3734b5d5dc45e_1558640253",
"startDate" : "2019-05-23T05:51:48.206000Z",
"documentURL" : "",
"detailStepType" : "none"
},
...
]
有关每个字段的更多信息,请查看 JSON 格式文档。
将日志解析为 JSON 对象,没有嵌套步骤(字段 subSteps
始终为空)。 获取构建的高级摘要非常有用。
例子
xclogparser parse --file path/to/log.xcactivitylog --reporter summaryJson
{
"parentIdentifier" : "",
"title" : "Build MobiusCore",
"warningCount" : 0,
"duration" : 0,
"startTimestamp" : 1558590748,
"signature" : "Build MobiusCore",
"endDate" : "2019-05-23T05:52:28.274000Z",
"errorCount" : 0,
"domain" : "Xcode.IDEActivityLogDomainType.BuildLog",
"type" : "main",
"identifier" : "68a2bbd0048a454d91b3734b5d5dc45e_1558640253_1",
"buildStatus" : "succeeded",
"schema" : "MobiusCore",
"subSteps" : [
],
"endTimestamp" : 1558590748,
"architecture" : "",
"machineName" : "68a2bbd0048a454d91b3734b5d5dc45e",
"buildIdentifier" : "68a2bbd0048a454d91b3734b5d5dc45e_1558640253",
"startDate" : "2019-05-23T05:52:28.244000Z",
"documentURL" : "",
"detailStepType" : "none"
}
有关每个字段的更多信息,请查看 JSON 格式文档。
以 Chrome tracer 使用的格式将 xcactivitylog
解析为 JSON 对象数组。 您可以使用此 JSON 在 Chrome 中的 Chrome 跟踪工具中可视化构建时间:chrome://tracing
。
例子
xclogparser parse --file path/to/log.xcactivitylog --reporter chromeTracer
将日志中找到的错误和警告列表输出为 JSON 文档。 当您只想检查构建时发现的问题时,这非常有用。
例子
xclogparser parse --file path/to/log.xcactivitylog --reporter issues
```json
{
"errors" : [
{
"characterRangeStart" : 0,
"startingColumnNumber" : 5,
"endingColumnNumber" : 30,
"characterRangeEnd" : 18446744073709551615,
"title" : "use of undeclared type 'AType'",
"endingLineNumber" : 10,
"type" : "swiftError",
"documentURL" : "file:\/\/\/MyProject\/MyFile.swift",
"startingLineNumber" : 10,
"severity" : 1
"detail": "\/MyProject\/MyFile.swift:10:5: error: use of undeclared type 'AType'\r func doSomething(completion: @escaping () -> AType) -> void) {\r^~~~\r"
}
],
"warnings" : [
{
"characterRangeStart" : 0,
"startingColumnNumber" : 5,
"endingColumnNumber" : 30,
"characterRangeEnd" : 18446744073709551615,
"title" : "Warning",
"endingLineNumber" : 10,
"type" : "swiftWarning",
"documentURL" : "file:\/\/\/MyProject\/MyFile.swift",
"startingLineNumber" : 10,
"severity" : 1
}
]
}
```
生成 HTML 报告,以可视化每个模块和文件的构建时间,以及警告和错误消息。
例子
xclogparser parse --file path/to/log.xcactivitylog --reporter html --output build/reports
环境 | 版本 |
---|---|
🛠 Xcode | 13.0 |
🐦 语言 | Swift 5.5 |
XCLogParser 目前处于 alpha 状态。我们正在内部使用它,并在各种项目上进行了测试,但我们需要社区的帮助,以便在更多的 iOS 和 Mac 应用程序上进行测试和改进。
MacOS
git clone git@github.com:MobileNativeFoundation/XCLogParser.git
克隆存储库。rake gen_resources
以生成编译应用程序所需的静态资源 Swift 文件。swift package generate-xcodeproj
以生成 Xcode 项目(或使用任何文本编辑器)。rake test
。Linux
docker build --tag xclogparser .
./run-in-docker.sh
如果您发现错误或想提出改进建议,欢迎您创建一个 issue。
vx.x.x
。提供发布标题和描述。DEVELOPER_DIR=<path_to_xcode_version> rake archive
构建一个工件。使用与 要求 部分匹配的 Xcode 版本。./build_release_in_docker.sh
releases/XCLogParser-x.x.x.zip
中的 zip 文件releases/linux/XCLogParser-x.x.x-Linux.zip
此项目遵循 开放行为准则。 参与者应遵守此准则。