PerformanceSuite 1.2.5

PerformanceSuite 1.2.5

Pilot34 维护。



  • 作者
  • 格莱布·塔拉斯夫

GitHub Workflow Status Cocoapods Cocoapods Cocoapods platforms Code Coverage

PerformanceSuite_logo_small

PerformanceSuite

PerformanceSuite 是一个用于测量和收集 iOS 应用性能和质量指标的 iOS Swift 库。

与其他解决方案(如 MetricKit、Firebase Performance、Instabug、Sentry 等)相比,它提供额外的灵活性。然而,它专注于性能监控的原生部分。对于存储和可视化您的指标,构建监控图,以及设置警报,您需要有您自己的后端。

此库用于 主 Booking.com iOS 应用程序,该应用程序由数以百万计的用户每天使用。

我们还开源了类似的 Android PerformanceSuite 代码。

优点

  • 性能事件实时传递到您的代码中,允许进行全面分析。
  • 您可以在 A/B 测试中监控性能。
  • 您具有构建任何实时性能图表,并设置自定义警报的灵活性。

缺点

  • 需要一个自定义后端来收集指标,显示图表和设置警报。

支持的功能

  • TTI(可交互时间)对屏幕的监控。
  • 冻结时间渲染性能对屏幕的监控。
  • 整体应用的冻结时间监控。
  • 启动时间监控。
  • 有堆栈跟踪的致命和非致命 挂起
  • 看门狗 终止(内存或CPU终止)。
  • 记录所有UIKit控制器事件以简化调试。

查阅我们的 Wiki 了解更多信息。

请注意,PerformanceSuite 当前不支持跟踪标准崩溃。您需要额外的工具来收集崩溃的堆栈跟踪(例如,Firebase Crashlytics)。

如何工作

PerformanceSuite 监控应在您的应用启动时激活,通过提供设置用于处理性能指标的的对象。随着您的应用继续运行,您将接收到回调以传递这些指标。

func startupTimeReceived(_ data: StartupTimeData) { ... }

func fatalHangReceived(info: HangInfo) { ... }

func nonFatalHangReceived(info: HangInfo) { ... }

func viewControllerLeakReceived(viewController: UIViewController) { ... }

func watchdogTerminationReceived(_ data: WatchdogTerminationData) { ... }

func appRenderingMetricsReceived(metrics: RenderingMetrics) { ... }

对于屏幕级指标,您应该返回 truefalse,以确定是否应该监控此特定的视图控制器对象

func shouldTrack(viewController: UIViewController) -> Bool { ... }

func ttiMetricsReceived(metrics: TTIMetrics, viewController: UIViewController) { ... }

func renderingMetricsReceived(metrics: RenderingMetrics, viewController: UIViewController) { ... }

SwiftUI 支持

PerformanceSuite 屏幕跟踪高度依赖 UIKit UIViewController 的生命周期。

对于纯SwiftUI应用程序,iOS仍然在底层创建UINavigationController来执行导航,并且这些情况得到了PerformanceSuite的支持。

然而,那些在底层不创建任何UIHostingController的自定义SwiftUI过渡目前还没有自动化。目前你可以使用片段TTI跟踪来处理这种情况下。如果对此有需求,我们可能会 later引入一些语法糖。

但是,对于大多数应用程序来说,当前的设置已经足够自动跟踪带有SwiftUI视图的UIHostingController中的屏幕打开。详见使用方法部分。

安装

Swift Package Manager

  • 在Xcode中,选择文件 > 添加包。
  • 在“搜索或输入包URL”对话框中输入https://github.com/bookingcom/perfsuite-ios
  • 在下一页中选择“向上至下一个主版本”并指定最新版本。
  • 在最后一页上,选择PerformanceSuite库并将其添加到您的目标中。
  • 您的包依赖项将被添加到您的.xcodeproj文件中。

CocoaPods

要使用CocoaPods将PerformanceSuite集成到您的Xcode项目中,请在Podfile中指定它

pod 'PerformanceSuite'

目前CocoaPods仓库遇到了索引新添加的Pod的问题,因此如果它不起作用,您可以指定源URL和标记

pod 'PerformanceSuite', :git => 'https://github.com/bookingcom/perfsuite-ios.git', :tag => '0.0.4' # use the last released version here

使用

要接收性能事件,您必须有实现以下协议之一的类

  • TTIMetricsReceiver
  • RenderingMetricsReceiver
  • AppRenderingMetricsReceiver
  • WatchDogTerminationsReceiver
  • HangsReceiver
  • ViewControllerLeaksReceiver
  • StartupTimeReceiver
  • ViewControllerLoggingReceiver
  • FragmentTTIMetricsReceiver

或者,您可以使用PerformanceSuiteMetricsReceiver来接收所有事件。

应在应用程序的尽可能早的阶段开始性能监控。例如,您可以在
application(application:didFinishLaunchingWithOptions:)方法的开始处开始。

let metricsConsumer = MetricsConsumer()
try PerformanceMonitoring.enable(config: .all(receiver: metricsConsumer))

// or with more flexibility

let metricsConsumer = MetricsConsumer()
let config: Config = [
    .screenLevelTTI(metricsConsumer),
    .screenLevelRendering(metricsConsumer),
    .appLevelRendering(metricsConsumer),
    .hangs(metricsConsumer),
]
try PerformanceMonitoring.enable(
    config: config,
    // you may pass your own key-value storage
    storage: KeyValueStorage.default,
    // you may pass a flag if app did crash from Crashlytics
    didCrashPreviously: didCrashPreviously
)

屏幕标识符

所有屏幕级别的指标都通过UIViewController对象从PerformanceSuite发送到您的代码。要将视图控制器对象转换为字符串标识符,您可以采用以下方法

  • 定义PerformanceScreen枚举,其中包含所有屏幕的屏幕标识符
  • 定义协议PerformanceTrackableScreen,其中每个屏幕都应该返回此枚举
  • 如果需要,添加对UIHostingController的SwiftUI支持
// We define enum with all our possible screens
// If you have too many screens, there can be several enums, 
// or just a string identifier.
enum PerformanceScreen: String {
    case search
    case details
    case checkout
}

// We define a protocol for screens to conform
protocol PerformanceTrackableScreen {
    var performanceScreen: PerformanceScreen? { get }
}

// For view controllers it is easy, we just return which screen is this
extension SearchViewController: PerformanceTrackableScreen {
    var performanceScreen: PerformanceScreen? { .search  }
}

// If you have SwiftUI screens without corresponding custom `UIHostingController`, 
// you will need to add introspection logic to find root views 
// in any `UIHostingController` in the app.
//
// We should conform to this protocol in the topmost view of the screen.
//
// NB: if possible, better to use your own subclass for `UIHostingController`
// and implement `PerformanceTrackableScreen` only in your subclass.
// Otherwise it may be additional performance overhead to introspect 
// all hosting controllers in the app
extension CheckoutScreenSwiftUIView: PerformanceTrackableScreen {
    var performanceScreen: PerformanceScreen? { .checkout }
}

// We also need to implement the protocol in UIHostingController,
// So we can determine which is the SwiftUI view inside this controller.
extension UIHostingController: PerformanceTrackableScreen {
    var performanceScreen: PerformanceScreen? {
        return (introspectRootView() as? PerformanceTrackableScreen)?.performanceScreen
    }
}

// In our metrics consumer we will receive UIViewController 
// and should determine which screen is this.
class MetricsConsumer: TTIMetricsReceiver {
    func shouldTrack(viewController: UIViewController) -> Bool {
        (viewController as? PerformanceTrackableScreen)?.performanceScreen != nil
    }

    func ttiMetricsReceived(metrics: TTIMetrics, viewController: UIViewController) {
        // find identifier for UIViewController
        guard let performanceScreen = (viewController as? PerformanceTrackableScreen)?.performanceScreen else {
            return
        }

        // send the event to your backend with this identifier
        send(metric: "tti", value: metrics.tti.seconds, screen: performanceScreen.rawValue)
    }
}

认可

该软件最初在Booking.com开发。经Booking.com批准,该软件以开源形式发布,作者们对此表示感谢。