DurationReporter 0.2.1

DurationReporter 0.2.1

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布上次发布2017 年 6 月
SwiftSwift 版本3.0
SPM支持 SPM

Kamil Tustanowski 维护。



🚀DurationReporter

Carthage compatibile

您是否想知道

  • 您的应用完成初始配置需要多长时间
  • 用户在点击播放后需要等待多长时间才能看到视频
  • 视图控制器在进行用户可以看到的操作之前正在做些什么

测量一个函数执行所需时间是很容易的。测量整个应用中整个 流程 的时间要复杂得多。尤其是如果它需要在不同的组件和屏幕上工作。

看看这个控制台日志。如果您觉得这很有用,请继续阅读。您将看到如何使用 DurationReporter 生成相似的报告。

🚀 Application Start - 3207ms
1. Loading        1006ms 31.37%
2. Loading Home   2001ms 62.39%
3. Preparing Home 200ms  6.24%

🚀 Video - 33003ms
1. Loading   2001ms  6.06%
2. Buffering 1001ms  3.03%
3. Playing   30001ms 90.90%

🚀 Share Video - 1302ms
1. Loading providers 501ms 38.48% 
2. Sending           801ms 61.52% 

工作原理

首先您表示操作开始

DurationReporter.begin(event: "ApplicationStart", action: "Loading")

当它完成后,您表示操作已结束

DurationReporter.end(event: "ApplicationStart", action: "Loading")

当您想看到结果时,您只需要打印报告

print(DurationReporter.generateReport())
🚀 ApplicationStart - 1005ms
1. Loading 1005ms 100.00%

单位

测量使用 mach_absolute_time() 进行,因为它提供的比常规日期对象更准确的数据。在生成报告时,默认单位是毫秒,但您可以轻松地更改它

DurationReporter.timeUnit = Nanosecond()
🚀 Application Start - 1006253263ns
1. Loading 1006253263ns 100.00%

请注意,在处理原始报告数据时,默认单位是

分组报告

事件聚集动作,因此我们不仅可以知道整个应用配置耗时,还可以这样做

[...]
DurationReporter.begin(event: "ApplicationStart", action: "Load config from API")
[...]
DurationReporter.end(event: "ApplicationStart", action: "Load config from API")
[...]
DurationReporter.begin(event: "ApplicationStart", action: "Save configuration")
[...]
DurationReporter.end(event: "ApplicationStart", action: "Save configuration")
[...]

结果是

🚀 ApplicationStart - 3041ms
1. Load config from API 2041ms 67.12%
2. Save configuration   1000ms 32.88%

带有重复的分组报告

启动另一个已报告的动作会导致为该事件创建另一个动作,并添加增量计数器。当尝试开始一个尚未完成的前一个动作时

  • 前一个尚未完成将显示为报告中的不完整,因为无法以可信的时间完成
  • 一个 fresh 的下一个动作将以单独的计数器等开始。

在这种情况下,无法在同一时间跟踪多个动作。

DurationReporter.begin(event: "Video", action: "Play")
[...]
DurationReporter.begin(event: "Video", action: "Play")
[...]
DurationReporter.end(event: "Video", action: "Play")
[...]
DurationReporter.begin(event: "Video", action: "Play")
[...]
DurationReporter.end(event: "Video", action: "Play")
[...]
DurationReporter.begin(event: "Video", action: "Play")
[...]
DurationReporter.end(event: "Video", action: "Play")

重复动作有 2、3、4 ... 等后缀

🚀 Video - 3008ms
1. 🔴 Play - ?
2. Play2 1006ms 33%
3. Play3 1001ms 33%
4. Play4 1001ms 33%

带自定义有效负载的报告

可能会有这种情况

  • 在报告完成后向分析工具发出报告调用
  • 创建更详细的报告

仅仅传递事件和动作名称 是不够的。对于这种情况,你可以在 beginend 上传递自定义的 payload。然后你只需要使用 beginPayloadendPayload 从报告中检索这个 payload。

DurationReporter.begin(event: "Video", action: "Watch", payload: "Sherlock S01E01")
[...]
DurationReporter.end(event: "Video", action: "Watch")
[...]
DurationReporter.begin(event: "Video", action: "Watch", payload: "Sherlock S01E02")
[...]
DurationReporter.end(event: "Video", action: "Watch")
[...]
DurationReporter.begin(event: "Video", action: "Watch", payload: "Sherlock S01E03")
[...]
DurationReporter.end(event: "Video", action: "Watch")

在正常报告中,你将看不到任何区别

🚀 Video - 3009ms
1. Watch  1007ms 33.47%
2. Watch2 1001ms 33.27%
3. Watch3 1001ms 33.27%

但是,如果你将默认的报表算法(见下面)替换为略微修改的版本(在报告动作时仅添加 \((report.beginPayload as? String) ?? "")),你会发现这样

🚀 Video - 3009ms
1. Watch  1007ms 33.47% Sherlock S01E01
2. Watch2 1001ms 33.27% Sherlock S01E02
3. Watch3 1001ms 33.27% Sherlock S01E03

你可以传递任何东西作为 payload。

报表

您可以创建自定义报表。只需获取收集到的数据

let collectedData = DurationReporter.reportData()

并使用它创建最适合您的需求的自定义报表。

您还可以替换默认的报表生成器代码

DurationReporter.reportGenerator = { collectedData in
    var output = ""
    
    collectedData.forEach { eventName, reports in
        reports.enumerated().forEach { index, report in
            if let reportDuration = report.duration {
                output += "\(eventName) → \(index). \(report.title) ⏱ \(reportDuration)ms\n"
            } else {
                output += "\(eventName) → \(index). 😱 \(report.title) - ?\n"
            }
            
        }
    }
    
    return output
}

只需调用 DurationReporter.generateReport() 即可获取您需要的任何类型的报表

Application Start → 1. Loading ⏱ 1008ms 
Application Start → 2. Loading Home ⏱ 2001ms 
Application Start → 3. Preparing Home ⏱ 201ms 

处理报表的开始和结束

在调度 begin 动作后

public static var onReportBegin: ((String, DurationReport) -> ())?

关闭函数被调用。在调度 end 动作后

public static var onReportEnd: ((String, DurationReport) -> ())?

调用。这意味着您可以在报表创建时执行自定义操作。再次考虑应用配置的示例,但在这两个关闭函数调用之前

DurationReporter.onReportBegin = { name, report in print("\(name)::\(report.title) 🚀") }
DurationReporter.onReportEnd = { name, report in print("\(name)::\(report.title) 🎉") }

以及我们得到的结果

ApplicationStart::Load config from API 🚀
ApplicationStart::Load config from API 🎉
ApplicationStart::Save configuration 🚀
ApplicationStart::Save configuration 🎉

🚀 ApplicationStart - 3007ms
1. Load config from API 2006ms 66.71%
2. Save configuration  1001ms 33.29%

这只是如何添加简单的控制台日志的一个简单示例。但为什么只打印到控制台,我们还可以做得更好,即。

  • 持久化报表数据
  • 上传测量的持续时间到外部分析

丢失的动作

如果动作没有完成,它会在报告中以🔴出现

🚀 ApplicationStart - 2006ms
1. Load config from API 2006ms 100.00%
2. 🔴 Save configuration - ?

清除

您可以使用它清除当前的报表数据并开始收集新的数据

DurationReporter.clear()

游乐场

如果您想尝试它,请克隆存储库,打开游乐场并查看它是否适合您。