KKMonitor

SDK API 参考

KMonitor SDK 的公共 API 参考,以及 Android 和 iOS 的每个平台代码示例。

初始化 SDK

在调用任何其他方法之前,先通过 init 初始化 SDK。请在应用启动时尽早调用它,以便从一开始就捕获崩溃、错误和事件。

import sh.measure.android.Measure
import sh.measure.android.config.ClientInfo
import sh.measure.android.config.MeasureConfig

Measure.init(
  this,
  MeasureConfig(),
  ClientInfo(apiKey = "YOUR_API_KEY", apiUrl = "YOUR_API_URL"),
)
import Measure

let clientInfo = ClientInfo(apiKey: "<apiKey>", apiUrl: "<apiUrl>")
Measure.initialize(with: clientInfo, config: BaseMeasureConfig())

SDK 配置选项

将配置对象传递给init自定义 SDK。可用选项因平台而异。

选项类型默认描述
enableLoggingBooleanfalse打开内部 SDK 日志。
autoStartBooleantrue在 init 上自动开始跟踪。设置为false延迟开始收集。
maxDiskUsageInMbInt50限制用于缓冲数据的磁盘空间。夹在中间20MB1500MB.
trackActivityIntentDataBooleanfalse捕获用于启动活动的意图数据。
requestHeadersProviderMsrRequestHeadersProvider?null添加自定义 HTTP 标头以请求 SDK 发送到 KMonitor API,这对于自托管设置很有用。
enableFullCollectionModeBooleanfalse覆盖所有采样并收集每个事件和跟踪。增加成本,因此仅将其用于调试。
enableDiagnosticModeBooleanfalse将所有 SDK 日志写入您可以在报告 SDK bug 时附加的文件。
选项类型默认描述
enableLoggingBoolfalse打开内部 SDK 日志。
autoStartBooltrueinit 后自动开始采集。设置为 false 可延后启动采集。
maxDiskUsageInMbInt50限制用于缓存数据的磁盘空间,范围为 20MB1500MB
requestHeadersProviderMsrRequestHeadersProvider?nil为 SDK 发往 KMonitor API 的请求添加自定义 HTTP Header,常用于自托管部署。
enableFullCollectionModeBoolfalse覆盖所有采样设置,采集每个事件和 Trace。会增加成本,仅建议调试时使用。
enableDiagnosticModeBoolfalse将所有 SDK 日志写入您可以在报告 SDK bug 时附加的文件。
enableDiagnosticModeGestureBoolfalse使用两指双击共享表导出 SDK 日志。需要enableDiagnosticMode.

开始追踪

SDK 开始自动收集数据init。如果你设置autoStartfalse在配置中,调用start当您准备好开始跟踪时。

import sh.measure.android.Measure

Measure.start()
import Measure

Measure.start()

停止追踪

暂停数据收集stop。停止时,SDK 不会收集任何数据。称呼start恢复。

import sh.measure.android.Measure

Measure.stop()
import Measure

Measure.stop()

跟踪错误

您可以报告已发现并恢复的错误。这些错误不会导致应用崩溃,但通常表示存在值得修复的问题。崩溃和 ANR 会自动捕获,因此无需手动记录它们。

跟踪已处理的错误

import sh.measure.android.Measure

try {
    methodThatThrows()
} catch (e: Exception) {
    Measure.trackHandledException(e)
}
import Measure

// Track a Swift Error or an NSError with trackError
do {
    try someThrowingFunction()
} catch {
    Measure.trackError(error)
}

添加属性

属性限制对于允许的键和值。

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val attributes = AttributesBuilder().put("screen", "Login").build()
Measure.trackHandledException(e, attributes)
import Measure

Measure.trackError(error, attributes: ["screen": .string("Login")])

记录自定义事件

使用 trackEvent 记录应用特有的事件,例如用户操作或功能使用情况。

  • 事件名称最多可包含 64 个字符。
  • 事件名称只能包含字母、数字、连字符和下划线。

跟踪事件

import sh.measure.android.Measure

Measure.trackEvent("event_name")
import Measure

Measure.trackEvent(name: "event_name", attributes: [:])

设置自定义时间戳

记录特定时间(自纪元以来的毫秒数)的事件。使用getCurrentTime以获得准确的单调值。

import sh.measure.android.Measure

Measure.trackEvent("event_name", timestamp = Measure.getCurrentTime())
import Measure

Measure.trackEvent(name: "event_name", attributes: [:], timestamp: Measure.getCurrentTime())

添加属性

属性限制对于允许的键和值。

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val attributes = AttributesBuilder().put("is_premium_user", true).build()
Measure.trackEvent("event_name", attributes = attributes)
import Measure

Measure.trackEvent(name: "event_name", attributes: ["is_premium_user": .boolean(true)])

跟踪屏幕视图

SDK自动跟踪屏幕视图来自每个平台的导航系统。通过自定义导航设置录制屏幕trackScreenView.

跟踪屏幕视图

import sh.measure.android.Measure

Measure.trackScreenView("Home")
import Measure

Measure.trackScreenView("Home", attributes: nil)

添加属性

属性限制对于允许的键和值。

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val attributes = AttributesBuilder().put("source", "deep_link").build()
Measure.trackScreenView("Home", attributes)
import Measure

Measure.trackScreenView("Home", attributes: ["source": .string("deep_link")])

记录性能 Trace

KMonitor 可以记录任意操作在 Span 中花费的时间。一个 Span 代表一个工作单元;通过设置 parent 可以跟踪多步骤流程。

  • Span 名称最多可包含 64 个字符。
  • Span 名称不能为空。

开始一个 Span

通过 startSpan 立即开始一个 Span。

import sh.measure.android.Measure

val span = Measure.startSpan("span-name")
import Measure

let span = Measure.startSpan(name: "span-name")

从时间戳开始

对于已经开始的操作,可以传入 getCurrentTime 返回的开始时间来创建 Trace,避免设备时钟变化造成时间偏差。

import sh.measure.android.Measure

val span = Measure.startSpan("span-name", timestamp = Measure.getCurrentTime())
import Measure

let span = Measure.startSpan(name: "span-name", timestamp: Measure.getCurrentTime())

结束 Span

通过 end 结束 Span。结束前请先设置状态。

import sh.measure.android.Measure
import sh.measure.android.tracing.SpanStatus

val span = Measure.startSpan("span-name")
span.setStatus(SpanStatus.Ok).end()
import Measure

let span = Measure.startSpan(name: "span-name")
span.setStatus(.ok).end()

以时间戳结束

对于已经完成的 Span,可以传入 getCurrentTime 返回的结束时间来结束它。

import sh.measure.android.Measure
import sh.measure.android.tracing.SpanStatus

val span = Measure.startSpan("span-name")
span.setStatus(SpanStatus.Ok).end(timestamp = Measure.getCurrentTime())
import Measure

let span = Measure.startSpan(name: "span-name")
span.setStatus(.ok).end(timestamp: Measure.getCurrentTime())

设置状态

设置操作的结果setStatus。值为Ok, ErrorUnset(默认)。

import sh.measure.android.Measure
import sh.measure.android.tracing.SpanStatus

val span = Measure.startSpan("span-name")
span.setStatus(SpanStatus.Ok)
import Measure

let span = Measure.startSpan(name: "span-name")
span.setStatus(.ok)

设置父级

通过 setParent 设置父 Span,构建操作层级。

import sh.measure.android.Measure

val parent = Measure.startSpan("parent-span")
val child = Measure.startSpan("child-span").setParent(parent)
import Measure

let parent = Measure.startSpan(name: "parent-span")
let child = Measure.startSpan(name: "child-span").setParent(parent)

添加属性

给 Span 添加键值上下文。可以一次添加一个属性,也可以通过 setAttributes 一次添加多个属性,或通过 removeAttribute 删除属性。允许的 key 和 value 请查看属性限制

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val span = Measure.startSpan("span-name")
span.setAttribute("key", "value")
span.setAttribute("count", 10)

val attributes = AttributesBuilder().put("key", "value").put("count", 10).build()
span.setAttributes(attributes)

span.removeAttribute("key")
import Measure

let span = Measure.startSpan(name: "span-name")
span.setAttribute("key", value: "value")
span.setAttribute("count", value: 10)

let attributes: [String: AttributeValue] = ["key": .string("value"), "count": .int(10)]
span.setAttributes(attributes)

span.removeAttribute("key")

重命名 Span

在 Span 开头后更新其名称setName.

import sh.measure.android.Measure

val span = Measure.startSpan("span-name")
span.setName("updated-name")
import Measure

let span = Measure.startSpan(name: "span-name")
span.setName("updated-name")

添加检查点

通过 setCheckpoint 标记 Span 中的重要时刻。一个 Span 最多可以包含 100 个 checkpoint。

import sh.measure.android.Measure

val span = Measure.startSpan("span-name")
span.setCheckpoint("checkpoint-name")
import Measure

let span = Measure.startSpan(name: "span-name")
span.setCheckpoint("checkpoint-name")

延后启动 Span

通过 createSpanBuilder 先配置 Span,稍后再启动。

import sh.measure.android.Measure

val builder = Measure.createSpanBuilder("span-name")
val span = builder?.startSpan()
import Measure

let builder = Measure.createSpanBuilder(name: "span-name")
let span = builder?.startSpan()

分布式追踪

通过在出站请求中添加 W3C traceparent Header,在服务之间传播 Trace。使用 getTraceParentHeaderKey 获取 Header 名称,使用 getTraceParentHeaderValue 获取对应的 Span 值。

import sh.measure.android.Measure

val span = Measure.startSpan("http")
val key = Measure.getTraceParentHeaderKey()
val value = Measure.getTraceParentHeaderValue(span)
import Measure

let span = Measure.startSpan(name: "http")
let key = Measure.getTraceParentHeaderKey()
let value = Measure.getTraceParentHeaderValue(span: span)

跟踪 HTTP 事件

KMonitor 会自动跟踪 Android 上的 OkHttp 和 iOS 上的 URLSession。使用trackHttpEvent记录来自任何其他 HTTP 客户端的请求,并使用getCurrentTime开始和结束时间以避免时钟偏差。

import sh.measure.android.Measure

val startTime = Measure.getCurrentTime()
// make the request
val endTime = Measure.getCurrentTime()

Measure.trackHttpEvent(
    url = "https://api.example.com/users",
    method = "GET",
    startTime = startTime,
    endTime = endTime,
    statusCode = 200,
)
import Measure

let startTime = UInt64(Measure.getCurrentTime())
// make the request
let endTime = UInt64(Measure.getCurrentTime())

Measure.trackHttpEvent(
    url: "https://api.example.com/users",
    method: "GET",
    startTime: startTime,
    endTime: endTime,
    statusCode: 200
)

跟踪错误报告

让用户从应用内提交 Bug Report。通过一次调用打开 Bug Report UI,或从自己的 UI 使用 trackBugReport 提交报告。描述最多可包含 4000 个字符,最多可包含 5 个附件。可使用 captureScreenshot 附加屏幕截图,也可以通过摇动设备触发报告。

打开错误报告屏幕

import sh.measure.android.Measure

Measure.launchBugReportActivity(takeScreenshot = true)
import Measure

Measure.launchBugReport(takeScreenshot: true)

跟踪错误报告

构建自定义 Bug Report 流程并提交 trackBugReport

import sh.measure.android.Measure

Measure.trackBugReport(description = "Cart items disappear after reopening the app")
import Measure

Measure.trackBugReport(description: "Cart items disappear after reopening the app")

添加属性

给报告附加元数据。打开 Bug Report UI 或从自己的 UI 提交报告时都可以传递属性。查看属性限制,了解允许的键和值。

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val attributes = AttributesBuilder().put("screen", "Cart").build()

Measure.launchBugReportActivity(takeScreenshot = true, attributes = attributes)
Measure.trackBugReport(description = "...", attributes = attributes)
import Measure

let attributes: [String: AttributeValue] = ["screen": .string("Cart")]

Measure.launchBugReport(takeScreenshot: true, attributes: attributes)
Measure.trackBugReport(description: "...", attributes: attributes)

摇一摇报告

注册 shake handler,让用户可以通过摇动设备打开 Bug Report。传递空 handler 可禁用。

import sh.measure.android.Measure
import sh.measure.android.bugreport.MsrShakeListener

Measure.setShakeListener(object : MsrShakeListener {
    override fun onShake() {
        Measure.launchBugReportActivity()
    }
})
import Measure

Measure.onShake {
    Measure.launchBugReport()
}

追踪日志

使用五个严重级别之一记录日志logDebug, logInfo, logWarning, logError或者logFatal。日志显示在会话时间线上并在调试时添加上下文。超过 1000 个字符的正文将被截断。

跟踪日志

import sh.measure.android.Measure

Measure.logDebug("Cache miss for key user_42")
Measure.logInfo("User signed in")
Measure.logWarning("Payment failed, retrying")
Measure.logError("Checkout request failed")
Measure.logFatal("Unrecoverable database error")
import Measure

Measure.logDebug("Cache miss for key user_42")
Measure.logInfo("User signed in")
Measure.logWarning("Payment failed, retrying")
Measure.logError("Checkout request failed")
Measure.logFatal("Unrecoverable database error")

添加属性

属性限制对于允许的键和值。

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val attributes = AttributesBuilder().put("screen", "Checkout").build()
Measure.logWarning("Payment failed", attributes)
import Measure

Measure.logWarning("Payment failed", attributes: ["screen": .string("Checkout")])

识别用户

设置用户 ID,以便在调试时将会话与用户关联起来。该 ID 会在应用启动后保持存在;用户登出时请清除它。

避免在用户 ID 中包含个人身份信息 (PII),例如电子邮件或电话号码。请改用哈希值或匿名值。

import sh.measure.android.Measure

Measure.setUserId("user-id")
Measure.clearUserId()
import Measure

Measure.setUserId("user-id")
Measure.clearUserId()

获取会话ID

读取当前会话 ID 以将应用数据与 KMonitor 会话关联起来。退货null如果 SDK 未初始化。

import sh.measure.android.Measure

val sessionId: String? = Measure.getSessionId()
import Measure

let sessionId: String? = Measure.getSessionId()

获取当前时间

从单调时钟读取 epoch 时间(毫秒)。将它用于事件、Span 和 HTTP 时间戳,可以避免设备时钟偏差。

import sh.measure.android.Measure

val currentTime: Long = Measure.getCurrentTime()
import Measure

let currentTime: Int64 = Measure.getCurrentTime()

遮罩 SwiftUI 视图

默认情况下,截图会遮罩所有 SwiftUI 内容,不受遮罩级别影响,因为 SDK 无法单独检查 SwiftUI 视图。可以用 .msrUnmask() 显示不敏感视图;对于自动检测遗漏的视图,例如 List 外的独立 Text,可以用 .msrMask() 强制遮罩。

import Measure

VStack {
    Text("Order confirmed")
        .msrUnmask()
    Text(cardNumber)
        .msrMask()
}

属性限制

属性是附加到事件、Span、日志、Bug Report、screen view 和错误上的键值对。它们在所有地方都遵循相同规则:

  • 键是字符串,最多 256 个字符。
  • 键只能包含字母、数字、连字符和下划线。
  • 值为字符串、整数、长整型、双精度型、浮点型或布尔型。
  • 字符串值最多可达 256 个字符。