iOS开发高级分享 - iOS 13 中的新框架 — MetriKit

MetriKit是iOS 13中用于收集和处理电池和性能指标的新框架。这是在WWDC今年与XCTestMetrics和Xcode Metrics组织者一起,作为一项协调一致的努力的一部分,为开发人员带来关于他们的应用程序在该领域的表现的新见解。

苹果会自动从AppStore上安装的应用程序中收集度量指标。您可以在Xcode 11中通过打开组织者(? ? ? o)并选择新的Metrics选项卡。

MetriKit是Xcode组织者度量的补充,它提供了一种编程方式来接收有关应用程序在该领域中的表现的日常信息。有了这些信息,您可以自己收集、聚合和分析比通过Xcode更详细的信息。

文章结尾有礼包

理解应用度量

度量可以帮助您发现您在本地测试时可能没有看到的问题,并允许您跟踪和更改不同版本的应用程序。在这个最初的版本中,苹果专注于两个对用户最重要的指标:电池使用和性能.

电池使用

电池寿命取决于许多不同的因素。物理方面,如设备的年龄和充电周期的次数是决定性的,

但你的手机使用方式也很重要。

比如CPU的使用、显示器的亮度和屏幕上的颜色,以及收音机用于获取数据或获取当前位置的频率--所有这些都会产生很大的影响。但最重要的是要记住的是,用户非常关心电池的使用寿命。

除了相机有多好外,电荷之间的间隔时间也是很长的。这个这些天当有人买新手机时的决定因素。

所以当他们的新的,昂贵的手机不度过这一天,他们会很不开心的。

直到最近,苹果公司还在电池问题上承担了大部分的责任。

但自从iOS 12和它的新电池使用屏在设置中,用户现在可以判断他们最喜欢的应用程序是什么时候被指责的。

幸运的是,有了iOS 13,你现在就拥有了所有你需要的东西,以确保你的应用程序不会与合理的能源使用发生冲突。

性能

性能是整个用户体验中的另一个关键因素。正常情况下,我们可能会看数据,如处理器时钟速度或帧速率作为业绩的衡量标准。但相反,苹果专注于不那么抽象和更具可操作性的指标:

挂率

主/UI线程被阻塞的频率有多大,以致应用程序对用户输入没有响应?

发射时间

用户点击图标后,应用程序需要多长时间才能使用?

峰值记忆&悬浮记忆

在进入后台之前,应用程序在峰值时使用了多少内存?

磁盘写入

这个应用程序多久写一次到磁盘,如果你还不知道,那就是相对缓慢运行 (即使是iPhone上的闪存!)

使用MetriKit

从API使用者的角度来看,很难想象`MetriKit`如何更容易合并。您所需要的只是您的应用程序的某些部分作为一个度量订阅者(一个明显的选择是您的`AppDelegate`),并将其添加到共享`MXMetricManager:`

import UIKit
import MetricKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
MXMetricManager.shared.add(self)
return true
}

func applicationWillTerminate(_ application: UIApplication) {
MXMetricManager.shared.remove(self)
}
}

extension AppDelegate: MXMetricManagerSubscriber {
func didReceive(_ payloads: [MXMetricPayload]) {
...
}
}

iOS在使用应用程序时会自动收集样本,并且每天(每24小时)发送一次包含这些指标的聚合报告。

以验证您的`MXMetricManagerSubscriber`正在按预期调用其委托方法,在Xcode运行应用程序时,从Debug菜单中选择SIMPLE MetriKit有效载荷。

模拟MetriKit有效载荷菜单项要求应用程序在实际设备上运行,并为模拟器构建禁用。

用路标标注关键代码节

除了为您收集的基线统计数据之外,还可以使用`mxSignpost`函数来收集代码中最重要部分的度量。这,这个路标支持API捕获CPU时间、内存和写入磁盘。

例如,如果应用程序的一部分确实对音频流进行了后处理,您可以用公制路标对这些区域进行注释,以确定该工作的能量和性能影响:

let audioLogHandle = MXMetricManager.makeLogHandle(category: "Audio")

func processAudioStream() {
mxSignpost(.begin, log: audioLogHandle, name: "ProcessAudioStream")
...
mxSignpost(.end, log: audioLogHandle, name: "ProcessAudioStream")
}

创建用于收集AppMetrics的自托管Web服务

既然你掌握了这些信息,你会怎么处理呢?我们该怎么填` ... `实现中的占位符`didReceive(_:)?`

你,你们能把它转交给一些付费的分析或事故报告服务,但这其中的乐趣在哪里呢??让我们构建自己的Web服务来收集这些以供进一步分析:

用PostgreSQL存储和查询度量

这个 MXMetricPayload 由度量管理器订阅者接收的对象有一个方便的 jsonRepresentation() 方法生成如下内容:

[点击查看 JSON表示 ]

正如你所看到的,这个表示法有很多地方。为所有这些信息定义模式将是一项艰巨的工作,而且不能保证这种情况今后不会改变。因此,让我们采用NoSQL范式(尽管是负责任地使用波斯特格斯)通过将有效载荷存储在JSONB列:

CREATE TABLE IF NOT EXISTS metrics (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
payload JSONB NOT NULL
);

我们可以使用JSON算子就像这样:

SELECT (payload -> ‘applicationTimeMetrics‘
->> ‘cumulativeForegroundTime‘)::INTERVAL
FROM metrics;
-- interval
-- ═══════════════════
-- @ 11 mins 40 secs
-- (1 row)

度量的JSON表示将时间和内存的度量存储为带有单位的字符串(如"100 ms"和500 kB)。在Postgres中,您可以直接将时间度量转换到INTERVAL类型但是,您需要创建一个转换为字节计数的函数:

CREATE OR REPLACE FUNCTION parse_byte_count (TEXT)
RETURNS BIGINT
AS $$
SELECT
replace(split_part($1, ‘ ‘, 1),‘,‘,‘‘)::BIGINT *
CASE split_part($1, ‘ ‘, 2)
WHEN ‘kB‘ THEN 1024
WHEN ‘MB‘ THEN 1024 * 1024
WHEN ‘GB‘ THEN 1024 * 1024 * 1024
END
$$ LANGUAGE ‘sql‘ STRICT IMMUTABLE;

高级:创建视图

PostgreSQL中的JSON运算符使用起来可能很麻烦--特别是对于更复杂的查询。其中一种帮助方法是创建一个视图。(物化或以其他方式)要以最方便的表示方式向您投射最重要的信息:

DROP VIEW key_performance_indicators;
CREATE VIEW key_performance_indicators AS
SELECT
id,
(payload -> ‘appVersion‘) AS app_version,
(payload -> ‘metaData‘ ->> ‘deviceType‘) AS device_type,
(payload -> ‘metaData‘ ->> ‘regionFormat‘) AS region,
(payload -> ‘applicationTimeMetrics‘
->> ‘cumulativeForegroundTime‘
)::INTERVAL AS cumulative_foreground_time,
parse_byte_count(
payload -> ‘memoryMetrics‘
->> ‘peakMemoryUsage‘
) AS peak_memory_usage_bytes
FROM metrics;

使用视图,您可以执行聚合查询在您的所有度量指标中,JSON有效负载都具有模式支持的关系数据库的方便性:

SELECT avg(cumulative_foreground_time)
FROM key_performance_indicators;
-- avg
-- ══════════════════
-- @ 9 mins 41 secs

SELECT app_version, percentile_disc(0.5)
WITHIN GROUP (ORDER BY peak_memory_usage_bytes)
AS median
FROM key_performance_indicators
GROUP BY app_version;
-- app_version │ median
-- ═════════════╪═══════════
-- "1.0.1" │ 192500000
-- "1.0.0" │ 204800000

PostgreSQL不能很好地处理CamelCase的表名或列名,所以在使用以下函数时要记住这一点jsonb_to_record.

创建Web服务

在本例中,大多数繁重的工作都委托给Postgres,这使得服务器端的实现相当枯燥。为了完整起见,以下是Ruby(Sinatra)和JavaScript(Express)中的一些参考实现:

require ‘sinatra/base‘
require ‘pg‘
require ‘sequel‘

class App < Sinatra::Base
configure do
DB = Sequel.connect(ENV[‘DATABASE_URL‘])
end

post ‘/collect‘ do
DB[:metrics].insert(payload: request.body.read)
status 204
end
end

发送度量作为JSON

现在我们已经设置好了一切,最后一步就是实现所需的`MXMetricManagerSubscriber`委托方法`didReceive(_:)`要将这些信息传递给我们的web服务:

extension AppDelegate: MXMetricManagerSubscriber {
func didReceive(_ payloads: [MXMetricPayload]) {
for payload in payloads {
let url = URL(string: "https://example.com/collect")!

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = payload.jsonRepresentation()

let task = URLSession.shared.dataTask(with: request)
task.priority = URLSessionTask.lowPriority
task.resume()
}
}
}

1024礼包

加入iOS开发交流QQ群:[1012951431],选择加入一起交流,一起学习,共享学习资料。期待你的加入!(进群可领取礼包)

转载地址 : https://nshipster.com/metrickit/

原文地址:https://www.cnblogs.com/Mayday9527/p/11732055.html

时间: 2024-10-04 17:28:41

iOS开发高级分享 - iOS 13 中的新框架 — MetriKit的相关文章

iOS开发高级分享 - iOS的可折叠表视图

导言 我曾经开发过一个iphone应用程序,它显示了大量的输入,这些输入分为不同的类别,在`UITableView`...若要更改其中一个输入的值,用户按下表视图中的对应行,并在出现的单独屏幕中更改该值.表视图为每个类别有一个节,每个节包含每个输入的表格单元格(行). 问题是输入的数量变得非常非常大,所以它没有给用户一个非常好的概述.从桌面滚动到底部甚至很乏味. 我们决定用户应该能够通过简单地按下节的标题来折叠和展开表中的部分(类别).我们要求实现这一目标的代码应该是可重用的,并且要求对现有代码

iOS开发——高级篇——iOS中常见的设计模式(MVC/单例/委托/观察者)

关于设计模式这个问题,在网上也找过一些资料,下面是我自己总结的,分享给大家 如果你刚接触设计模式,我们有好消息告诉你!首先,多亏了Cocoa的构建方式,你已经使用了许多的设计模式以及被鼓励的最佳实践. 首先得搞清楚设计模式是个什么鬼,在软件设计领域,设计模式是对通用问题的可复用的解决方案.设计模式是一系列帮你写出更可理解和复用代码的模板,设计模式帮你创建松耦合的代码以便你不需要费多大力就可以改变或者替换代码中的组件 其实iOS中的设计模式有非常多,常用的就下面这四种 一.MVC设计模式(设计模式

文顶顶 iOS开发UI篇—IOS开发中Xcode的一些使用技巧

iOS开发UI篇—IOS开发中Xcode的一些使用技巧 一.快捷键的使用 经常用到的快捷键如下: 新建 shift + cmd + n     新建项目 cmd + n             新建文件 视图 option + cmd + 回车 打开助理编辑器 cmd + 回车           显示主窗口 cmd + 0             导航窗口 option + cmd + 0    工具窗口 在.m & .h之间切换           control + cmd + 上/下 按

文顶顶 iOS开发UI篇—在UIImageView中添加按钮以及Tag的参数说明

ios开发UI篇—在ImageView中添加按钮以及Tag的参数说明 一.tag参数 一个视图通常都只有一个父视图,多个子视图,在开发中可以通过使用子视图的tag来取出对应的子视图.方法为Viewwithtag: 提示点:在xib中如果想要通过tag参数获取对应的控件(属性),不要把tag的参数设置为0,因为xib中所有的对象默认tag都为0,设置为0取不到对象. 二.ImageView中添加按钮(1)ImageView和Button的比较 Button按钮的内部可以放置多张图片(4),而Ima

iOS开发UI基础—IOS开发中Xcode的一些使用技巧

iOS开发UI基础-IOS开发中Xcode的一些使用技巧 一.快捷键的使用 经常用到的快捷键如下: 新建 shift + cmd + n     新建项目 cmd + n             新建文件 视图 option + cmd + 回车 打开助理编辑器 cmd + 回车           显示主窗口 cmd + 0             导航窗口 option + cmd + 0    工具窗口 在.m & .h之间切换           control + cmd + 上/下

IOS开发UI基础—在UIImageView中添加按钮以及Tag的参数说明

ios开发UI基础-在ImageView中添加按钮以及Tag的参数说明 一.tag参数 一个视图通常都只有一个父视图,多个子视图,在开发中可以通过使用子视图的tag来取出对应的子视图.方法为Viewwithtag: 提示点:在xib中如果想要通过tag参数获取对应的控件(属性),不要把tag的参数设置为0,因为xib中所有的对象默认tag都为0,设置为0取不到对象. 二.ImageView中添加按钮(1)ImageView和Button的比较 Button按钮的内部可以放置多张图片(4),而Im

[分享]错误“应用程序Xcode的这个版本不能与此版本的OS X配合使用”以及Mac源码和IOS开发资料分享

??[分享]错误"应用程序Xcode的这个版本不能与此版本的OS X配合使用"以及Mac源码和IOS开发资料分享 安装Xcode时,出现"应用程序Xcode的这个版本不能与此版本的OS X配合使用"错误如下: 解决方案是: /system/libary/coreservice/SystemVersion.plist中的两个10.10为10.10.5 修改过程会提示无权限修改,要不要建立副本,点击提示框中的"复制"按钮,存到桌面上. 点击一个文件右

iOS开发基础知识--碎片13

 iOS开发基础知识--碎片13 1:运行程序报the file couldn't be opened because you don't have permission to view it 解决办法:项目—>targets->build settings->build options->changed the value of the "Compiler for C/C++/Objective-C" to Default Compiler. 2:百度地图引用

iOS开发OC基础:Xcode中常见英文总结,OC常见英文错误

在开发的过程中难免会遇到很多的错误,可是当看到系统给出的英文时,又不知道是什么意思.所以这篇文章总结了Xcode中常见的一些英文单词及词组,可以帮助初学的人快速了解给出的提示.多练习,就肯定能基本掌握. expression:表达式assignable:赋值variable:变量redefinition:重复定义type:类型conflicting:冲突项invalid:无效的conversion:转换specifier:说明符indent:缩进operands:运算对象.操作数binary:二