获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

了解消息传递

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

FCM 提供了三组工具来帮助您深入了解消息传递:

  • Firebase 控制台消息传递报告
  • 来自 Firebase Cloud Messaging Data API 的汇总 Android SDK 交付指标
  • 全面的数据导出到 Google BigQuery

本页中描述的报告工具都需要 Google Analytics 才能运行。如果您的项目未启用 Google Analytics,您可以在 Firebase 项目设置的集成选项卡中进行设置。

请记住,由于分析数据的批处理,此页面上的许多统计数据的报告可能会延迟长达 24 小时。

消息传递报告

在 Firebase 控制台的“报告”选项卡中,您可以查看发送到 Android 或 Apple 平台 FCM SDK 的消息的以下数据,包括通过 Notifications Composer 和 FCM API 发送的消息:

  • 发送 - 数据消息或通知消息已入队以进行传递,或已成功传递到 APNs 等第三方服务以进行传递。有关更多信息,请参阅消息的生命周期
  • 已收到(仅适用于 Android 设备)— 应用程序已收到数据消息或通知消息。当接收 Android 设备安装了 FCM SDK 18.0.1 或更高版本时,此数据可用。
  • 印象数(仅适用于 Android 设备上的通知消息)— 显示通知已在应用程序处于后台时显示在设备上。
  • 打开 — 用户打开了通知消息。仅报告应用程序在后台时收到的通知。

此数据可用于所有带有通知负载的消息和所有标记数据消息。要了解有关标签的更多信息,请参阅向消息添加分析标签

查看消息报告时,您可以设置显示数据的日期范围,并可选择导出为 CSV。您还可以按以下条件过滤:

  • 平台(iOS 或 Android)
  • 应用程序
  • 自定义分析标签

向消息添加分析标签

标记消息对于自定义分析非常有用,允许您按标签或标签集过滤传递统计信息。您可以通过在消息对象或特定于平台的AndroidFcmOptionsApnsFcmOptions字段中设置fcmOptions.analyticsLabel字段,为通过 HTTP v1 API 发送的任何消息添加标签。

Analytics 标签是格式为^[a-zA-Z0-9-_.~%]{1,50}$的文本字符串。标签可以包含大小写字母、数字和以下符号:

  • -
  • ~
  • %

最大长度为 50 个字符。您每天最多可以指定 100 个唯一标签;添加的标签超出该限制的消息不会被报告。

在 Firebase 控制台消息报告选项卡中,您可以搜索所有现有标签的列表,并单独或组合应用它们以过滤显示的统计信息。

通过 FCM 数据 API 聚合的交付数据

Firebase Cloud Messaging Data API 可让您检索有助于了解针对 Android 应用程序的消息请求结果的信息。 API 提供跨项目中所有支持数据收集的 Android 设备的聚合数据。这包括有关无延迟传递的消息百分比的详细信息,以及在Android 传输层中延迟或丢弃的消息数量。评估这些数据可以揭示消息传递的广泛趋势,并帮助您找到提高发送请求性能的有效方法。有关报告中日期范围可用性的信息,请参阅汇总数据时间表

API 提供给定应用程序可用的所有数据。请参阅API 参考文档

数据是如何分解的?

交付数据按应用程序、日期和分析标签细分。对 API 的调用将返回日期、应用程序和分析标签的每个组合的数据。例如,单个androidDeliveryData JSON 对象如下所示:

 {
  "appId": "1:23456789:android:a93a5mb1234efe56",
  "date": {
    "year": 2021,
    "month": 1,
    "day": 1
  },
  "analyticsLabel": "foo",
  "data": {
    "countMessagesAccepted": "314159",
    "messageOutcomePercents": {
      "delivered": 71,
      "pending": 15
    },
   "deliveryPerformancePercents": {
      "deliveredNoDelay": 45,
      "delayedDeviceOffline": 11
    }
  }

如何解释指标

传递数据概述了符合以下每个指标的消息的百分比。一条消息可能适合多个指标。由于我们收集数据的方式以及我们聚合指标的粒度级别的限制,一些消息结果根本没有在指标中表示,因此下面的百分比总和不会达到 100%。

计算接受的消息

数据集中包含的唯一计数是 FCM 接受以传递到 Android 设备的消息计数。所有百分比都使用该值作为分母。请记住,此计数不包括针对已在其设备上禁用收集使用情况和诊断信息的用户的消息。

消息结果百分比

MessageOutcomePercents对象中包含的字段提供有关消息请求结果的信息。这些类别都是互斥的。它可以回答诸如“我的消息是否被传递?”之类的问题。和“是什么导致消息被丢弃?”

例如, droppedTooManyPendingMessages字段的高值可能表明应用实例正在接收大量不可折叠的消息,超过 FCM 的 100 条待处理消息的限制。为了缓解这种情况,请确保您的应用处理对onDeletedMessages的调用,并考虑发送可折叠消息。同样, droppedDeviceInactive的高百分比可能是更新服务器上的注册令牌、删除陈旧令牌并从主题中取消订阅它们的信号。有关此领域的最佳实践,请参阅管理 FCM 注册令牌

交付绩效百分比

DeliveryPerformancePercents对象中的字段提供有关已成功传递的消息的信息。它可以回答诸如“我的消息延迟了吗?”之类的问题。和“为什么消息延迟?”例如, delayedMessageThrottled的高值会清楚地表明您超出了每个设备的最大限制,并且应该调整您发送消息的速率。

消息洞察百分比

此对象提供有关所有消息发送的附加信息。 priorityLowered字段表示优先级从HIGH降低到NORMAL的已接受消息的百分比。如果此值较高,请尝试发送较少的高优先级消息或确保在发送高优先级消息时始终显示通知。有关更多信息,请参阅我们关于消息优先级的文档

此数据与导出到 BigQuery 的数据有何不同?

BigQuery 导出提供有关 FCM 后端接受消息以及在设备上的 SDK 中传递消息的单独消息日志( FCM 架构的第 2 步和第 4 步)。此数据对于确保接受和传递单个消息很有用。在下一部分中详细了解BigQuery 数据导出

相比之下,Firebase 云消息传递数据 API 提供了有关在 Android 传输层(或FCM 架构的第 3 步)中具体发生的情况的汇总详细信息。该数据专门提供了对从 FCM 后端到 Android SDK 的消息传递的洞察。它对于显示在此传输过程中为什么消息被延迟或丢弃的趋势特别有用。

在某些情况下,由于以下原因,这两个数据集可能不完全匹配:

  • 聚合指标仅对所有消息的一部分进行采样
  • 汇总指标四舍五入
  • 我们不会提供低于隐私阈值的指标
  • 由于我们管理大量流量的方式进行了优化,部分消息结果丢失。

API 的限制

聚合数据时间线

API会返回7天的历史数据;但是,此 API 返回的数据最多会延迟 5 天。例如,在 1 月 20 日,1 月 9 日至 1 月 15 日的数据可用,但 1 月 16 日或之后的数据不可用。此外,数据是尽最大努力提供的。如果发生数据中断,FCM 将努力向前修复,并且在问题修复后不会回填数据。在较大的中断中,数据可能会在一周或更长时间内不可用。

数据覆盖率

Firebase Cloud Messaging Data API 提供的指标旨在深入了解消息传递的广泛趋势。但是,它们不能 100% 覆盖所有消息场景。以下情景是未反映在指标中的已知结果。

折叠的消息

已被另一条消息折叠的消息不会出现在数据集中。

给非活动设备的消息

发送到非活动设备的消息可能会或可能不会显示在数据集中,具体取决于它们采用的数据路径。这可能会导致在droppedDeviceInactivepending字段中出现一些错误计数。

向具有特定用户偏好的设备发送消息

根据他们的偏好,禁用收集其设备上的使用和诊断信息的用户将不会将他们的消息包含在我们的计数中。

四舍五入和最小值

FCM 故意舍入并排除数量不够大的计数。

BigQuery 数据导出

您可以将消息数据导出到BigQuery以进行进一步分析。 BigQuery 允许您使用 BigQuery SQL 分析数据,将其导出到另一个云提供商,或将数据用于您的自定义 ML 模型。到 BigQuery 的导出包括消息的所有可用数据,无论消息类型如何,或者消息是通过 API 还是通过通知编写器发送的。

对于发送到具有以下 FCM SDK 最低版本的设备的消息,您可以选择为您的应用启用消息传递数据的导出:

  • 安卓 20.1.0 或更高版本。
  • iOS 8.6.0 或更高版本
  • Firebase Web SDK 9.0.0 或更高版本

有关为AndroidiOS启用数据导出的详细信息,请参见下文。

首先,将您的项目链接到 BigQuery:

  1. 选择以下选项之一:

    • 打开Notifications composer ,然后点击页面底部的访问 BigQuery

    • 在 Firebase 控制台的集成页面中,点击BigQuery卡片中的链接

      此页面显示项目中所有启用 FCM 的应用程序的 FCM 导出选项。

  2. 按照屏幕上的说明启用 BigQuery。

如需了解详情,请参阅将Firebase 链接到 BigQuery

当您为云消息传递启用 BigQuery 导出时:

  • Firebase将您的数据导出到 BigQuery。请注意,用于导出的数据的初始传播最多可能需要 48 小时才能完成。

  • 创建数据集后,位置无法更改,但您可以将数据集复制到其他位置或手动将数据集移动(重新创建)到其他位置。要了解更多信息,请参阅更改数据集位置

  • Firebase 会定期将您的数据从 Firebase 项目同步到 BigQuery。这些每日出口操作从太平洋时间凌晨 4:00 开始,通常在 24 小时内完成。

  • 默认情况下,您项目中的所有应用都与 BigQuery 相关联,您以后添加到项目中的所有应用都会自动与 BigQuery 相关联。您可以管理哪些应用程序发送数据

要停用 BigQuery 导出,请在 Firebase 控制台中取消关联您的项目

启用消息传递数据导出

具有 FCM SDK 8.6.0 或更高版本的 iOS 设备可以启用其应用的消息传递数据导出。 FCM 支持警报和后台通知的数据导出。在启用这些选项之前,您必须首先为您的项目创建 FCM-BiqQuery 链接,如BigQuery 数据导出中所述。

启用警报通知的交付数据导出

因为只有警报通知才能触发通知服务应用扩展,所以您必须在应用中添加通知服务扩展,并在服务扩展中调用此 API 以启用显示消息跟踪。请参阅 Apple 关于修改新交付通知中的内容的文档。

必须为收到的每个通知进行以下调用:

迅速

// For alert notifications, call the API inside the service extension:
class NotificationService: UNNotificationServiceExtension {
  override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
  Messaging.extensionHelper()
      .exportDeliveryMetricsToBigQuery(withMessageInfo:request.content.userInfo)
  }
}

Objective-C

// For alert notifications, call the API inside the service extension:
@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request
                   withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler {
  [[FIRMessaging extensionHelper] exportDeliveryMetricsToBigQueryWithMessageInfo:request.content.userInfo];
}
@end

如果您使用 HTTP v1 API 构建发送请求,请确保在有效负载对象中指定mutable-content = 1

为后台通知启用交付数据导出

对于应用在前台或后台时收到的后台消息,您可以在主应用的数据消息处理程序中调用数据导出 API。必须为收到的每个通知进行此调用:

迅速

// For background notifications, call the API inside the UIApplicationDelegate or NSApplicationDelegate method:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
  Messaging.extensionHelper().exportDeliveryMetricsToBigQuery(withMessageInfo:userInfo)
}

Objective-C

// For background notifications, call the API inside the UIApplicationDelegate or NSApplicationDelegate method:
@implementation AppDelegate
- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  [[FIRMessaging extensionHelper] exportDeliveryMetricsToBigQueryWithMessageInfo:userInfo];
}
@end

哪些数据会导出到 BigQuery?

请注意,针对过时的令牌或不活跃的注册可能会夸大其中一些统计数据。

导出表的架构是:

_PARTITIONTIME时间戳此伪列包含加载数据的当天开始时间(以 UTC 为单位)的时间戳。对于 YYYYMMDD 分区,此伪列包含值 TIMESTAMP('YYYY-MM-DD')。
event_timestamp时间戳服务器记录的事件时间戳
项目编号整数项目编号标识发送消息的项目
message_id细绳消息 ID 标识消息。从 App ID 和时间戳生成的消息 ID 在某些情况下可能不是全局唯一的。
instance_id细绳消息发送到的应用程序的唯一 ID(如果可用)。它可以是实例 ID 或 Firebase 安装 ID。
消息类型细绳消息的类型。可以是通知消息或数据消息。主题用于标识主题或活动发送的原始消息;随后的消息是通知或数据消息。
sdk_platform细绳收件人应用程序的平台
app_name细绳Android 应用程序的包名称或 iOS 应用程序的包 ID
折叠键细绳折叠键标识一组可以折叠的消息。当设备未连接时,只有具有给定折叠键的最后一条消息排队等待最终传递
优先整数消息的优先级。有效值为“正常”和“高”。在 iOS 上,这些对应于 APNs 优先级 5 和 10
ttl整数此参数指定如果设备处于脱机状态,消息应在 FCM 存储中保留多长时间(以秒为单位)
话题细绳向其发送消息的主题的名称(如果适用)
bulk_id整数批量 ID 标识一组相关消息,例如发送到某个主题的特定消息
事件细绳事件的类型。可能的值为:
  • MESSAGE_ACCEPTED:消息被FCM服务器接收,请求有效;
  • MESSAGE_DELIVERED:消息已发送到设备上应用的 FCM SDK。默认情况下,不传播此字段。要启用,请按照setDeliveryMetricsExportToBigQuery(boolean)中提供的说明进行操作。
  • MISSING_REGISTRATIONS:由于缺少注册,请求被拒绝;
  • UNAUTHORIZED_REGISTRATION:邮件被拒绝,因为发件人无权发送到注册;
  • MESSAGE_RECEIVED_INTERNAL_ERROR:处理消息请求时出现未指明的错误;
  • MISMATCH_SENDER_ID:发送消息的请求被拒绝,因为发送消息的发送者 ID 与为端点声明的 ID 不匹配;
  • QUOTA_EXCEEDED:发送消息的请求因配额不足而被拒绝;
  • INVALID_REGISTRATION:发送消息的请求因注册无效而被拒绝;
  • INVALID_PACKAGE_NAME:由于包名无效,发送消息的请求被拒绝;
  • INVALID_APNS_CREDENTIAL:由于APNS证书无效,发送消息的请求被拒绝;
  • INVALID_PARAMETERS:发送消息的请求因参数无效而被拒绝;
  • PAYLOAD_TOO_LARGE:由于负载大于限制,发送消息的请求被拒绝;
  • AUTHENTICATION_ERROR:发送消息的请求由于身份验证错误而被拒绝(检查用于发送消息的 API Key);
  • INVALID_TTL:由于 TTL 无效,发送消息的请求被拒绝。
分析标签细绳使用HTTP v1 API ,可以在发送消息时设置分析标签,以便标记消息以用于分析目的

你可以用导出的数据做什么?

以下部分提供了可以在 BigQuery 中针对导出的 FCM 数据运行的查询示例。

按应用统计发送的消息

SELECT app_name, COUNT(1)
FROM `project ID.firebase_messaging.data`
WHERE
  _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
  AND event = 'MESSAGE_ACCEPTED'
  AND message_id != ''
GROUP BY 1;

计算消息所针对的唯一应用程序实例

SELECT COUNT(DISTINCT instance_id)
FROM `project ID.firebase_messaging.data`
WHERE
  _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
  AND event = 'MESSAGE_ACCEPTED';

计算发送的通知消息

SELECT COUNT(1)
FROM `project ID.firebase_messaging.data`
WHERE
  _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
  AND event = 'MESSAGE_ACCEPTED'
  AND message_type = 'DISPLAY_NOTIFICATION';

统计发送的数据消息

SELECT COUNT(1)
FROM `project ID.firebase_messaging.data`
WHERE
  _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
  AND event = 'MESSAGE_ACCEPTED'
  AND message_type = 'DATA_MESSAGE';

计数发送到主题或活动的消息

SELECT COUNT(1)
FROM `project ID.firebase_messaging.data`
WHERE
  _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
  AND event = 'MESSAGE_ACCEPTED'
  AND bulk_id = your bulk id AND message_id != '';

要跟踪发送到特定主题的消息的事件,请修改此查询以将AND message_id != ''替换为AND message_id = <your message id>; .

计算给定主题或活动的扇出持续时间

扇出开始时间是收到原始请求的时间,结束时间是创建针对单个实例的最后一条单独消息的时间。

SELECT
  TIMESTAMP_DIFF(
    end_timestamp, start_timestamp, MILLISECOND
  ) AS fanout_duration_ms,
  end_timestamp,
  start_timestamp
FROM (
    SELECT MAX(event_timestamp) AS end_timestamp
    FROM `project ID.firebase_messaging.data`
    WHERE
      _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
      AND event = 'MESSAGE_ACCEPTED'
      AND bulk_id = your bulk id
  ) sent
  CROSS JOIN (
    SELECT event_timestamp AS start_timestamp
    FROM `project ID.firebase_messaging.data`
    WHERE
      _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
      AND event = 'MESSAGE_ACCEPTED'
      AND bulk_id = your bulk id
      AND message_type = 'TOPIC'
  ) initial_message;

已发送消息的计数百分比

SELECT
  messages_sent,
  messages_delivered,
  messages_delivered / messages_sent * 100 AS percent_delivered
FROM (
    SELECT COUNT(DISTINCT CONCAT(message_id, instance_id)) AS messages_sent
    FROM `project ID.firebase_messaging.data`
    WHERE
      _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
      AND event = 'MESSAGE_ACCEPTED'
  ) sent
  CROSS JOIN (
    SELECT COUNT(DISTINCT CONCAT(message_id, instance_id)) AS messages_delivered
    FROM `project ID.firebase_messaging.data`
    WHERE
      _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
      AND (event = 'MESSAGE_DELIVERED'
      AND message_id
      IN (
        SELECT message_id FROM `project ID.firebase_messaging.data`
        WHERE
          _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
          AND event = 'MESSAGE_ACCEPTED'
        GROUP BY 1
      )
  ) delivered;

跟踪给定消息 ID 和实例 ID 的所有事件

SELECT *
FROM `project ID.firebase_messaging.data`
WHERE
    _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
    AND message_id = 'your message id'
    AND instance_id = 'your instance id'
ORDER BY event_timestamp;

计算给定消息 ID 和实例 ID 的延迟

SELECT
  TIMESTAMP_DIFF(
    MAX(delivered_time), MIN(accepted_time), MILLISECOND
  ) AS latency_ms
FROM (
    SELECT event_timestamp AS accepted_time
    FROM `project ID.firebase_messaging.data`
    WHERE
      _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
      AND message_id = 'your message id'
      AND instance_id = 'your instance id'
      AND event = 'MESSAGE_ACCEPTED'
  ) sent
  CROSS JOIN (
    SELECT event_timestamp AS delivered_time
    FROM `project ID.firebase_messaging.data`
    WHERE
      _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD') AND
      message_id = 'your message id' AND instance_id = 'your instance id'
      AND (event = 'MESSAGE_DELIVERED'
  ) delivered;