Понимание доставки сообщений

Для устранения неполадок, связанных с проблемами доставки сообщений, используйте средство устранения неполадок FCM и ознакомьтесь с этой статьей в блоге , чтобы понять различные причины, по которым вы можете не видеть свое сообщение. Вы также можете посетить панель мониторинга состояния FCM , чтобы определить, есть ли какие-либо сбои в работе сервиса, влияющие на FCM.

FCM также предоставляет три набора инструментов, которые помогут вам получить представление о всесторонней оценке успеха и стратегии обмена сообщениями:

  • Отчеты о доставке сообщений в консоли Firebase
  • Сводные метрики доставки Android SDK из Firebase Cloud Messaging Data API
  • Комплексный экспорт данных в Google BigQuery

Для экспорта данных в BigQuery и работы вкладки «Отчеты» в консоли Firebase требуется Google Analytics . Вы можете включить Google Analytics в настройках. > Вкладка «Интеграции» в консоли Firebase . Для работы функции «Агрегированные данные доставки » Google Analytics не требуется.

Учтите, что отображение многих статистических данных на этой странице может задерживаться до 24 часов из-за пакетной обработки аналитических данных.

Отчеты о доставке сообщений

В консоли Firebase перейдите в раздел DevOps & Engagement > Messaging > вкладка Reports , чтобы просмотреть следующие данные по сообщениям, отправленным в SDK FCM для платформ Android или Apple, включая сообщения, отправленные с помощью Notifications composer и API FCM:

  • Отправлено — Сообщение данных или уведомление поставлено в очередь на доставку или успешно передано стороннему сервису, например, APNs, для доставки. Обратите внимание, что статистика отправленных сообщений может отображаться с задержкой в ​​несколько часов. Дополнительную информацию см. в разделе «Срок жизни сообщения» .
  • Получено (доступно только на устройствах Android) — Приложение получило сообщение с данными или уведомление. Эти данные доступны, если на принимающем устройстве Android установлен FCM SDK версии 18.0.1 или выше.
  • Показы (доступно только для уведомлений на устройствах Android) — Уведомление отображалось на устройстве, пока приложение работало в фоновом режиме.
  • Открытие — Пользователь открыл уведомление. Сообщается только об уведомлениях, полученных, когда приложение находится в фоновом режиме.

Эти данные доступны для всех сообщений с полезной нагрузкой уведомления и для всех сообщений с помеченными данными. Чтобы узнать больше о метках, см. раздел «Добавление аналитических меток к сообщениям» .

При просмотре отчетов по сообщениям можно задать диапазон дат для отображаемых данных с возможностью экспорта в CSV-файл. Также можно фильтровать данные по следующим критериям:

  • Платформа (iOS или Android)
  • Приложение
  • Пользовательские аналитические метки

Добавление аналитических меток к сообщениям

Добавление меток к сообщениям очень полезно для пользовательского анализа, позволяя фильтровать статистику доставки по меткам или наборам меток. Вы можете добавить метку к любому сообщению, отправленному с использованием API HTTP v1, установив поле fcmOptions.analyticsLabel в объекте сообщения или в полях AndroidFcmOptions или ApnsFcmOptions , специфичных для платформы.

Метки аналитики представляют собой текстовые строки в формате ^[a-zA-Z0-9-_.~%]{1,50}$ . Метки могут содержать строчные и прописные буквы, цифры и следующие символы:

  • -
  • ~
  • %

Максимальная длина — 50 символов. Вы можете указать до 100 уникальных меток в день; сообщения с метками, добавленными сверх этого лимита, не отображаются в результатах поиска.

На вкладке «Отчеты» в консоли Firebase можно выполнить поиск по списку всех существующих меток и применить их по отдельности или в комбинации для фильтрации отображаемой статистики.

Агрегированные данные о доставке с использованием API данных FCM

The Firebase Cloud Messaging Data API lets you retrieve information that can help you understand the outcomes of message requests targeted to Android applications. The API provides aggregated data across all data collection-enabled Android devices in a project. This includes details on the percentage of messages delivered without delay as well as how many messages were delayed or dropped within the Android Transport Layer . Evaluating this data can reveal broad trends in message delivery and help you find effective ways to improve the performance of your send requests. See Aggregate data timelines for information on date range availability in the reports.

API предоставляет все доступные данные для данного приложения. См. справочную документацию по API .

Как структурированы данные?

Данные о доставке разбиты по приложению, дате и метке аналитики . Вызов API вернет данные для любой комбинации даты, приложения и метки аналитики. Например, один объект JSON androidDeliveryData будет выглядеть так:

 {
  "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 предоставляют информацию о результатах запросов сообщений. Все категории являются взаимоисключающими. Они могут ответить на такие вопросы, как «Доставляются ли мои сообщения?» и «Что вызывает потерю сообщений?».

For example, a high value for the droppedTooManyPendingMessages field could signal that app instances are receiving volumes of non-collapsible messages exceeding FCM 's limit of 100 pending messages. To mitigate this, make sure your app handles calls to onDeletedMessages , and consider sending collapsible messages. Similarly, high percentages for droppedDeviceInactive could be a signal to update registration tokens on your server, removing stale tokens and unsubscribing them from topics. See Manage FCM registration tokens for best practices in this area.

Процент выполнения доставки

The fields in the DeliveryPerformancePercents object provide information about messages that were successfully delivered. It can answer questions such as "Were my messages delayed?" and "Why are messages delayed?" For example, a high value for delayedMessageThrottled would clearly indicate that you are exceeding per-device maximum limits , and should adjust the rate at which you are sending messages.

Процентное соотношение анализа сообщений

This object provides additional information about all message sends. The priorityLowered field expresses the percentage of accepted messages that had priority lowered from HIGH to NORMAL . If this value is high, try sending fewer high priority messages or ensure that you always display a notification when a high priority message is sent. See our documentation on message priority for more info

Чем эти данные отличаются от данных, экспортированных в BigQuery?

Экспорт данных из BigQuery предоставляет журналы отдельных сообщений, отражающие их принятие бэкэндом FCM и доставку в SDK на устройстве (шаги 2 и 4 архитектуры FCM ). Эти данные полезны для проверки того, были ли приняты и доставлены отдельные сообщения. Подробнее об экспорте данных из BigQuery читайте в следующем разделе.

By contrast, the Firebase Cloud Messaging Data API provides aggregated details about what happens specifically in the Android Transport Layer (or Step 3 of the FCM Architecture ). This data specifically provides insight into the delivery of messages from FCM backends to the Android SDK. It's particularly useful for showing trends as to why messages were delayed or dropped during this transport.

В некоторых случаях возможно, что два набора данных не будут точно совпадать по следующим причинам:

  • Сводные метрики отражают лишь часть всех сообщений.
  • Сводные показатели округлены.
  • Мы не публикуем показатели, не соответствующие установленному уровню конфиденциальности.
  • Часть результатов обработки сообщений отсутствует из-за оптимизации способов управления большим объемом трафика.

Ограничения API

Сводные временные шкалы данных

The API will return 7 days of historical data; however, data returned by this API will be delayed by up to 5 days. For example, on January 20th, the data for January 9th - January 15th would be available, but not for January 16th or later. Additionally, the data is provided at best effort. In the event of a data outage, FCM will work to fix forward and won't backfill the data after the issue is fixed. In larger outages, the data could be unavailable for a week or more.

Покрытие данных

Метрики, предоставляемые API данных Firebase Cloud Messaging, призваны дать представление об общих тенденциях доставки сообщений. Однако они не обеспечивают 100% охвата всех сценариев обмена сообщениями. Следующие сценарии представляют собой известные результаты, не отраженные в метриках.

Устаревшие сообщения

Если время жизни (TTL) истекает после окончания указанной даты в журнале, сообщение не будет считаться отброшенным как droppedTtlExpired в эту дату.

Сообщения на неактивные устройства

Сообщения, отправленные на неактивные устройства, могут отображаться или не отображаться в наборе данных в зависимости от выбранного пути передачи данных. Это может привести к ошибкам в подсчете в полях droppedDeviceInactive и pending .

Сообщения на устройства с определенными пользовательскими настройками.

В соответствии с предпочтениями пользователей, отключивших сбор информации об использовании и диагностике на своих устройствах, их сообщения не будут учитываться в нашем подсчете.

Округление и минимальные значения

Компания FCM намеренно округляет и исключает данные, где объемы недостаточно велики.

экспорт данных BigQuery

Вы можете экспортировать данные сообщений в BigQuery для дальнейшего анализа. BigQuery позволяет анализировать данные с помощью BigQuery SQL, экспортировать их в другой облачный провайдер или использовать данные для ваших собственных моделей машинного обучения. Экспорт в BigQuery включает все доступные данные для сообщений, независимо от типа сообщения или от того, отправлено ли сообщение через API или через редактор уведомлений.

Для сообщений, отправляемых на устройства со следующими минимальными версиями FCM SDK, у вас есть дополнительная возможность включить экспорт данных о доставке сообщений для вашего приложения:

  • Android 20.1.0 или выше.
  • iOS 8.6.0 или выше
  • Firebase Web SDK 12.14.0 или выше

Для начала свяжите свой проект с BigQuery с помощью консоли Firebase :

  1. Выберите один из следующих вариантов:

    • Перейдите в раздел DevOps & Engagement > Messaging > Notifications Composer , затем нажмите Access BigQuery внизу страницы.

    • Перейдите в > Вкладка «Интеграции» . Затем в BigQuery нажмите «Связать» .

      На этой странице отображаются параметры экспорта FCM для всех приложений проекта, поддерживающих FCM .

  2. Следуйте инструкциям на экране, чтобы включить BigQuery .

Для получения более подробной информации см. раздел «Связывание Firebase с BigQuery» .

При включении экспорта BigQuery для Cloud Messaging :

  • Firebase экспортирует ваши данные в BigQuery . Обратите внимание, что первоначальная передача данных для экспорта может занять до 48 часов.

  • После создания набора данных его местоположение изменить нельзя, но вы можете скопировать набор данных в другое место или вручную переместить (пересоздать) его в другом месте. Для получения дополнительной информации см. раздел «Изменение местоположения набора данных» .

  • Firebase настраивает регулярную синхронизацию ваших данных из проекта Firebase в BigQuery . Эти ежедневные операции экспорта начинаются в 4:00 утра по тихоокеанскому времени и обычно завершаются в течение 24 часов.

  • По умолчанию все приложения в вашем проекте связаны с BigQuery , и любые приложения, которые вы добавите в проект позже, автоматически будут связаны с BigQuery . Вы можете управлять тем, какие приложения отправляют данные .

Чтобы отключить экспорт BigQuery , отвяжите свой проект в консоли Firebase .

Включить экспорт данных о доставке сообщений

iOS+

iOS devices with the FCM SDK 8.6.0 or higher can enable their app's message delivery data export. FCM supports data export for both alert and background notifications. Data export is disabled by default at the app level . Programmatically enabling it at the app instance level lets you ask end users for permission to analyze their message delivery data (recommended). When both are set, the app instance level value overrides the app level value.

Прежде чем включить эти параметры, необходимо сначала создать связь 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.serviceExtension().exportDeliveryMetrics(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

Если вы формируете запросы на отправку с использованием API HTTP v1, обязательно укажите `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.serviceExtension().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

Android

На устройствах Android с установленным FCM SDK версии 20.1.0 или выше можно включить экспорт данных о доставке сообщений из приложения. Экспорт данных по умолчанию отключен на уровне приложения . Программное включение экспорта на уровне экземпляра приложения позволяет запрашивать у конечных пользователей разрешение на анализ данных о доставке их сообщений (рекомендуется). Если оба параметра заданы, значение на уровне экземпляра приложения переопределяет значение на уровне приложения.

Прежде чем включить эти параметры, необходимо сначала создать связь FCM -BiqQuery для вашего проекта, как описано в разделе «Экспорт данных BigQuery» .

Включить экспорт данных о доставке для экземпляров приложения

В большинстве случаев мы рекомендуем включать экспорт данных о доставке сообщений только на уровне экземпляра приложения и оставлять его отключенным на уровне приложения.

FirebaseMessaging.getInstance().setDeliveryMetricsExportToBigQuery(true);

Включить экспорт данных о доставке для приложения

Если вы предпочитаете включить экспорт на уровне приложения, убедитесь, что не вызываете метод setDeliveryMetricsExportToBigQuery , и добавьте следующее свойство в объект приложения в манифесте вашего приложения:

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

Веб

The FCM SDK for Web 12.14.0 or higher allows a delivery data export. Data export is disabled by default at the app level . Programmatically enabling it at the app instance level lets you ask end users for permission to analyze their message delivery data (recommended). When both are set, the app instance level value overrides the app level value. When an end user gives consent or rejects data collection, the app should set the experimental enable or disable flag for each app instance as shown:

// userConsent holds the decision of the user to give big query export consent.
const userConsent = ...;

const messaging = getMessagingInSw(app);

experimentalSetDeliveryMetricsExportedToBigQueryEnabled(messaging, userConsent);

Какие данные экспортируются в BigQuery?

Следует отметить, что таргетирование устаревших токенов или неактивных регистраций может завышать некоторые из этих статистических данных.

Схема экспортируемой таблицы следующая:

_ВРЕМЯ РАЗДЕЛЕНИЯ ОТМЕТКА ВРЕМЕНИ Этот псевдостолбец содержит метку времени начала дня (в формате UTC), в который были загружены данные. Для раздела YYYYMMDD этот псевдостолбец содержит значение TIMESTAMP('YYYY-MM-DD').
event_timestamp ОТМЕТКА ВРЕМЕНИ Отметка времени события, записанная сервером.
номер_проекта ЦЕЛОЕ Номер проекта идентифицирует проект, отправивший сообщение.
message_id НИТЬ Идентификатор сообщения (message ID) определяет сообщение. Созданный на основе идентификатора приложения (App ID) и метки времени, идентификатор сообщения в некоторых случаях может быть не уникальным в глобальном масштабе.
instance_id НИТЬ Уникальный идентификатор приложения, которому отправляется сообщение (если доступен). Это может быть идентификатор экземпляра или идентификатор установки Firebase .
message_type НИТЬ Тип сообщения. Может быть уведомлением или сообщением с данными. Тема используется для идентификации исходного сообщения для темы или рассылки кампании; последующие сообщения могут быть либо уведомлением, либо сообщением с данными.
sdk_platform НИТЬ Платформа приложения получателя
имя_приложения НИТЬ Имя пакета для приложений Android или идентификатор пакета для приложений iOS.
collapse_key НИТЬ Ключ сворачивания определяет группу сообщений, которые можно свернуть. Когда устройство не подключено, в очередь на доставку ставится только последнее сообщение с данным ключом сворачивания.
приоритет ЦЕЛОЕ Приоритет сообщения. 5 — «нормальный» приоритет, 10 — «высокий» приоритет.
ттл ЦЕЛОЕ Этот параметр определяет, как долго (в секундах) сообщение должно храниться в памяти FCM, если устройство находится в автономном режиме.
тема НИТЬ Название темы, по которой было отправлено сообщение (если применимо).
bulk_id ЦЕЛОЕ Идентификатор группы сообщений (bulk ID) определяет группу связанных сообщений, например, конкретную отправку в определенную тему.
событие НИТЬ Тип события. Возможные значения:
  • MESSAGE_ACCEPTED: сообщение получено сервером FCM, и запрос действителен;
  • MESSAGE_DELIVERED: сообщение доставлено в SDK FCM приложения на устройстве. По умолчанию это поле не передается. Чтобы включить его, следуйте инструкциям, приведенным в setDeliveryMetricsExportToBigQuery(boolean) .
  • ОТСУТСТВУЮЩИЕ РЕГИСТРАЦИИ: запрос был отклонен из-за отсутствия регистрации;
  • UNAUTHORIZED_REGISTRATION: сообщение было отклонено, поскольку отправитель не имеет права отправлять его на регистрацию;
  • MESSAGE_RECEIVED_INTERNAL_ERROR: при обработке запроса сообщения произошла неуказанная ошибка;
  • MISMATCH_SENDER_ID: запрос на отправку сообщения был отклонен из-за несоответствия идентификатора отправителя сообщения и идентификатора, указанного для конечной точки;
  • QUOTA_EXCEEDED: запрос на отправку сообщения был отклонен из-за недостаточной квоты;
  • INVALID_REGISTRATION: запрос на отправку сообщения был отклонен из-за недействительной регистрации;
  • INVALID_PACKAGE_NAME: запрос на отправку сообщения был отклонен из-за недопустимого имени пакета;
  • INVALID_APNS_CREDENTIAL: запрос на отправку сообщения был отклонен из-за недействительного сертификата APNS;
  • INVALID_PARAMETERS: запрос на отправку сообщения был отклонен из-за недопустимых параметров;
  • PAYLOAD_TOO_LARGE: запрос на отправку сообщения был отклонен из-за превышения лимита полезной нагрузки;
  • AUTHENTICATION_ERROR: запрос на отправку сообщения был отклонен из-за ошибки аутентификации (проверьте ключ API, использованный для отправки сообщения);
  • INVALID_TTL: запрос на отправку сообщения был отклонен из-за недопустимого значения TTL.
analytics_label НИТЬ С помощью API HTTP v1 можно установить метку аналитики при отправке сообщения, чтобы пометить его для целей аналитики.

Что можно сделать с экспортированными данными?

В следующих разделах приведены примеры запросов, которые можно выполнить в 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;

Отслеживайте все события для заданного идентификатора сообщения и идентификатора экземпляра.

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;

Вычислите задержку для заданного идентификатора сообщения и идентификатора экземпляра.

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;