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

了解消息传递

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

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

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

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

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

消息传递报告

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

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

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

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

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

向消息添加分析标签

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

分析标签是格式为^[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的高值将清楚地表明您超出了每个设备的最大限制,并且应该调整您发送消息的速率。

Message Insight 百分比

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

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

BigQuery 导出提供有关 FCM 后端消息接受和设备 SDK 中消息传递的单独消息日志( FCM 架构的第 2 步和第 4 步)。此数据对于确保接受和传递个别消息很有用。在下一节中阅读有关BigQuery 数据导出的更多信息。

相比之下,Firebase Cloud Messaging Data 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 最低版本的设备的消息,您可以选择为您的应用启用消息传递数据的导出:

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

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

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

  1. 选择以下选项之一:

    • 打开Notifications composer ,然后点击页面底部的Access 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 20.1.0 或更高版本的 Android 设备可以启用其应用程序的消息传递数据导出。默认情况下,在应用程序级别禁用数据导出。在应用程序实例级别以编程方式启用它允许您请求最终用户允许分析他们的消息传递数据(推荐)。在两者都设置的情况下,应用程序实例级别值将覆盖应用程序级别值。

在启用这些选项之前,您必须先为您的项目创建 FCM-BiqQuery 链接,如BigQuery 数据导出中所述。

为应用程序实例启用交付数据导出

对于大多数情况,我们建议您仅在应用实例级别启用消息传递数据导出,并在应用级别禁用它。

 FirebaseMessaging.getInstance().setDeliveryMetricsExportToBigQuery(true)

为应用启用交付数据导出

如果您更喜欢在应用程序级别启用导出,请确保不要调用setDeliveryMetricsExportToBigQuery方法,并将以下属性添加到应用程序清单中的应用程序对象:

<application>
  <meta-data android:name="delivery_metrics_exported_to_big_query_enabled"
      android:value="true" />
</application>

哪些数据会导出到 BigQuery?

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

导出表的架构是:

_PARTITIONTIME时间戳此伪列包含加载数据的当天开始时间(UTC 时间)。对于 YYYYMMDD 分区,此伪列包含值 TIMESTAMP('YYYY-MM-DD')。
事件时间戳时间戳服务器记录的事件时间戳
项目编号整数项目编号标识发送消息的项目
消息编号细绳消息 ID 标识一条消息。从 App ID 和时间戳生成,消息 ID 在某些情况下可能不是全局唯一的。
instance_id细绳消息发送到的应用程序的唯一 ID(如果可用)。它可以是实例 ID 或 Firebase 安装 ID。
消息类型细绳消息的类型。可以是通知消息或数据消息。主题用于标识主题或活动发送的原始消息;随后的消息是通知或数据消息。
sdk_平台细绳收件人应用程序的平台
应用名称细绳Android 应用程序包名称或 iOS 应用程序包 ID
折叠键细绳折叠键标识一组可以折叠的消息。当设备未连接时,只有具有给定折叠键的最后一条消息排队等待最终传递
优先整数消息的优先级。有效值为“正常”和“高”。在 iOS 上,这些对应于 APNs 优先级 5 和 10
电讯报整数此参数指定如果设备处于离线状态,消息应在 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 与为端点声明的不匹配,发送消息的请求被拒绝;
  • QUOTA_EXCEEDED:由于配额不足,发送消息的请求被拒绝;
  • INVALID_REGISTRATION:由于注册无效,发送消息的请求被拒绝;
  • INVALID_PACKAGE_NAME:发送消息的请求因包名无效而被拒绝;
  • INVALID_APNS_CREDENTIAL:由于 APNS 证书无效,发送消息的请求被拒绝;
  • INVALID_PARAMETERS:发送消息的请求因参数无效而被拒绝;
  • PAYLOAD_TOO_LARGE:由于负载大于限制,发送消息的请求被拒绝;
  • AUTHENTICATION_ERROR:由于身份验证错误,发送消息的请求被拒绝(检查用于发送消息的 API 密钥);
  • 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;