2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AoToAdvent Calendar 2023

Day 10

Oura API V2 を読み解いて、Datadog にヘルスケアデータを連携する

Last updated at Posted at 2023-12-10

はじめに

こんにちは、Datadog Japan で Sales Engineer をしている AoTo です。

この記事は AoTo Advent Calendar 2023 10日目の記事です。

この記事は完全に趣味の記事です。Oura Ring や Datadog を個人で利用している方は是非最後までお読みください。

みなさん、Oura Ring はご存知でしょうか? Oura Ring は フィンランドのヘルスケア企業 Oura Health Oy によって開発された、睡眠と身体活動を追跡するために使用されるスマートリングです。

日本では Oura Ring Gen2(第2世代) の頃から広まり、現在は Gen3(第3世代) のみが販売されています。Oura Ring によって睡眠時間や睡眠の質をはじめ、日中の活動量から最近ではストレス量までを可視化することができます。

現在これらのヘルスケアデータは Oura API V2 でエクスポートすることができるため、今回は Oura API V2 を利用して、Observability プラットフォームである Datadog にデータを連携してみました。

Oura API V2 を読み解く

Oura は開発者向けにヘルスケアデータを取得できる Oura API V2 を提供しています。追加のヘルスケアデータや機能により Oura API V1 からリビジョンされ、V1 は 2024年1月22日廃止されます。

まずは、この API V2 の仕様を簡単に読み解いていきます。

ドキュメント

API の仕様は Oura API Documentation(2.0)JSON 形式のダウンロードでの閲覧が可能です。
V2 のドキュメントはデータアクセスと認証方法から始まり、各データタイプ毎に取得方法が説明されています。

データアクセスと認証

各ヘルスケアデータはパーソナルアクセストークンを使用して API 経由で取得が可能です。このトークンを取得するためには、個人のアカウントにアクセスする必要がありますが、Oura Ring を利用していれば必ず発行しているので特に問題はありません。個人利用をする場合は、ここまでで問題ありません。

複数人のデータを取得するようにアプリケーションを構成する場合、デフォルトではユーザー数は10人に制限されています。商用利用の場合は、Oura API Ageement に同意して審査のための申請の情報を入力して送信する必要があります。

認証は OAuth2 プロトコルパーソナルアクセストークンを直接使用しての認証方法を選択できます。今回は簡易的なデータ連携のため、そのままトークンを利用することにします。アクセストークンを利用する場合は、リクエストヘッダーに以下のように含める必要があります。

GET /v2/usercollection/personal_info HTTP/1.1
Host: api.ouraring.com
Authorization: Bearer <token>

Authorization: BearerBearerは必須の文字列となるので、トークンのみとしないように注意が必要です。

レスポンスコード

各データタイプに共通のOura API のレスポンスコードとして想定されているのは200, 400, 401, 403, 404, 422, 429の7つです。

特に429となる場合は、 5分間に5000リクエストのレート制限を超えていることとなるため注意が必要です。取得方法やアプリケーションの仕様上このレート制限を超える可能性がある場合は、Oura API サポート(api-support@ouraring.com)に連絡する必要があります。

API の仕様

当たり前ですが、Oura API V2 各ヘルスケアデータの取得のみが可能で、ほぼ全ての API は GET のみとなっています。それぞれのデータタイプにおいて単一のデータか複数データを指定して取得できます。

API V2 はbaseUrlとしてhttps://cloud.ouraring.com /v2/usercollection/を利用します。その後ろにデータタイプと取得範囲を指定する形になります。

Multiple でデータを取得する際は、start_dateend_dateを指定することでその期間のすべてのデータを取得できます。それぞれの日付はYYYY-MM-DD形式で指定する必要があります。

Single でデータを取得する際は、{document_id}を指定する必要があります。この{document_id}は単一のデータに対して割り振られる一意の ID で、/^[a-zA-Z0-9]{8}-[0-9]{4}-[0-9]{4}-[a-zA-Z]{4}-[a-zA-Z0-9]{12}$/の形で表されます。1

データタイプと API 一覧

Neme Multiple Single
Daily Activity /daily_activity /daily_activity/{document_id}
Daily Readiness /daily_readiness /daily_readiness/{document_id}
Daily Sleep /daily_sleep /daily_sleep/{document_id}
Daily Spo2 /dailiy_spo2 /dailiy_sp02/{document_id}
Heart Rate - /heartrate
Personal Info /presonal_info -
Rest Mode Period /rest_mode_period /rest_mode_period/{document_id}
Ring Configuration /ring_configuration /ring_configuration/{document_id}
Session /session /session/{document_id}
Sleep /sleep /sleep/{document_id}
Sleep Time /sleep_time /sleep_time/{document_id}
Tag /tag /tag/{document_id}
Workout /workout /workout/{document_id}

Webhook サブスクリプション

上記の API とは異なり、Oura API に Webhook サブスクリプションを作成することで、Webhook を利用してほぼリアルタイムに Oura データの更新を受信できる仕様が用意されています。

Webhook サブスクリプションを利用するには、Create Webhook Subscription から行う必要があります。この API にはリクエストボディにapplication/json形式で、callback_urlでサブスクリプションをする URL、verification_tokenで認証トークンを、event_typeでイベントタイプを、data_typeで取得するデータタイプを指定します。

この Webhook サブスクリプションを作成した時に渡したデータを元に、Oura API はデータが更新される毎に最新のデータをサブスクリプションをする元に POST します。この内容を更新したい場合は、Update Webhook Subscription を利用できます。

Datadog に連携をする場合、データタイプやフォーマットを Datadog のメトリクス・ログに合うように考慮する必要があるので、今回はこの方法を利用せずに特定のデータを明示的に指定して取得します。

Datadog に連携する

Datadog にデータを連携するためには、Datadog API を利用することができます。データ連携を行うために、Oura API V2 では cURL, Python, JavaScript, Java でのサンプルコードを提示しています。

AWS Lambda のようなサーバレス関数を Amazon EventBridge Scheduler を利用して定期的に実行するイベントドリブンアーキテクチャの構成を取ることもできますが、Datadog と Oura API のみで完成させる方法はあるのでしょうか。

はい、あります。

Datadog Workflow Automation を使用することで、ローコード UI を用いて Oura API V2 を利用したデータの取得Datadog API を利用したデータの記録が行えます。

Datadog Workflow Automation とは

Datadog Workflow Automation は Datadog の SaaS プラットフォーム上で作成できる、ローコードの自動化ツールです。公式ドキュメントの内容を引用すると、HTTP アクションJavaScript データ演算子を定義できるため、Oura API V2 へ curl で取得したデータを Datadog の形式に変換して Datadog API を用いて保存できます。

HTTP アクションや JavaScript データ演算子などの Workflow 固有のアクションに加え、複数のツールにまたがる 400 以上のアクションを提供します。これらのアクションにより、フローで必要とされるあらゆるタスクを実行することができます。

今回作成する Workflow

今回は Oura ヘルスケアデータの中から、タイプの異なる睡眠サマリーと心拍数のデータを取得します。

Sleep データHeart Rate データは、それぞれイベントとメトリクスとして記録します。

どちらも①トリガーで Workflow を起動 ②日時情報の生成 ③Oura API V2 によるヘルスケアデータの取得 ④Datadog API Action によるデータの記録の順で行います。それぞれ、①スケジュールトリガー ②JavaScript アクション ③HTTP リクエスト ④Datadog アクションを利用します。

HeartRateforOura.jpg

① Workflow スケジュールトリガー

Workflow のトリガーには、Workflow ページや Dashboard からの手動トリガーMonitor や Security Signal からの自動トリガーSchedule による定期実行が可能です。

今回は、定期的に Workflow を実行して Oura API V2 からヘルスケアデータを取得したいため、Schedule による定期実行を選択します。単一の Workflow にトリガーは1つしか設定できませんが、手動のトリガーは別途 Workflow ページから実行したり Dashboard に設定したりすることができます。

今回はSleep データを日次で、 Heart Rate データを5分毎に取得します。

② 日時生成 JavaScript アクション

現在のところ Datadog Workflow Automation では日時データをアクションの実行から取得できないため、カスタム JavaScript アクションを用いて Oura API V2 で用いられるYYYY-MM-DD形式で、実行時点の日付と前日の日付を取得します。2

今回は Oura Ring のタイムゾーンをAsia/Tokyoとしていますので、JSTのタイムゾーンでの日付を取得するようにしています。

GetDate.js
function formatDateJST(dt) {
  const offset = dt.getTimezoneOffset() * 60000;
  const dateInJST = new Date(dt.getTime() - offset + (9 * 60 * 60000)); // JSTはUTC+9

  return `${dateInJST.getFullYear()}-${String(dateInJST.getMonth() + 1).padStart(2, '0')}-${String(dateInJST.getDate()).padStart(2, '0')}`;
}

function getDatesJST() {
  const today = new Date();
  const todayInJST = formatDateJST(today);

  const yesterday = new Date(today.setDate(today.getDate() - 1));
  const yesterdayInJST = formatDateJST(yesterday);

  return {
    TodayDate: todayInJST,
    YesterdayDate: yesterdayInJST
  };
}

return getDatesJST();

Datadog Workflow 上で実行される JavaScript アクションは、UTC ±0 が前提となります。
Datadog プラットフォーム上の時間設定は[Organization Settings] > [General] > [Preferences] > [Monitors Time Zone Preference]から設定が可能ですが、名前の通り現在のところは Datadog Monitor にのみ反映されます。

③ Oura API V2 HTTP リクエストアクション

前述の通り、Oura API にはbaseUrlとしてhttps://cloud.ouraring.com /v2/usercollection/を共通して利用しています。その後ろに取得するデータタイプと、リクエストパラメーターを?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD形式で指定します。

さらに、HTTP リクエストアクションは、Connection にアクセストークンを使用した認証設定を反映できます。ここで設定した Token は Token Name のみ後から参照でき、Token Value は全ての Datadog ユーザーに対してマスクされます。

Connection 設定画面

ConnectionAuth.jpg

この Connection を設定することで、データタイプとパラメーターを指定するだけで、共通する API リクエストを実行することができます。ここで取得したデータは別のアクションで、コンテキスト変数の一種であるステップ出力変数として{{ Steps.<HTTP アクション名>.<オブジェクト名>.<データ名> }}のように指定することができます。

今回は、それぞれの HTTP アクションをGET_SLEEPGET_HEART_RATEのように命名しています。

④ データ記録 Datadog アクション

最後に、Datadog API を利用したデータの記録を行う Datadog アクションです。イベントの登録には Create Event をメトリクスの登録には Submit Metric を利用できます。他にも、Datadog API に準じた様々な操作が可能です。

こちらでも同様に、Connection を作成する際に Datadog の API Key と Application Key を登録します。カスタムサブドメインを設定してあっても対応可能です。

ここでは登録するイベントやメトリクスの名前を決定したら、取り出すデータを見つけ出し、ステップ出力変数として指定できます。

今回は、睡眠イベントデータをテキストとして{ {{ Steps.Get_Sleep.body }} }のように(雑に)全て記録し、心拍メトリクスデータをoura.heartrateと命名し値を{{ Steps.Get_Heart_Rate.body.data.[0].bpm }}タグをconciousness: {{ Steps.Get_Heart_Rate.body.data.[0].source }}のように最新のオブジェクトのみを参照して記録しました。

取得できたデータ

取得できたデータはそれぞれ、睡眠イベントデータは[Service Mgmt] > [Event Management] から、心拍メトリクスデータは[Metrics] > [Explorer]から参照できます。

取得できたデータ

SleepEvents.jpg

HeartRateMetrics.jpg

データの形式は今回の内容に限らずログなどの形式にもできますが、データの検索性や歌詞性を高めるために、適切なタグ付けが重要となってきます。

おわりに

3年以上愛用している Oura Ring のヘルスケアリングのデータを Datadog で見れないかなという思いで検証してみたのがきっかけでした。

Datadog ではこのように自由に様々なデータソースからのデータを連携・収集し、可視化を行うことができます。もちろん、組み込みでの設定の他にも現在では750を超えるインテグレーションが提供されているため、ご自身が連携したいものが含まれていないか確認してみてください🐶

Oura Ring もまた、個人のヘルスケアデータを可視化するパーソナルオブザーバビリティツールとして、常に精密な情報をわかりやすく提供してくれます。健康が気になってきたという方は、この機会にクリスマスプレゼントとして買ってみてはいかがでしょうか💍3

  1. この{document_id}の割り振り方には規則性がないため、未知のデータを取得することに向いていません。

  2. JavaScript 初心者なので、改善点がありましたらご指摘ください🙇

  3. 本件は個人のおすすめであり、所属する企業や商品の PR ではございません。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?