> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squarecloud.app/llms.txt
> Use this file to discover all available pages before exploring further.

# リアルタイム

> client.apps.realtime() でアプリケーションのライブログ、ステータス、システムイベントをストリーミングします。ステータスフレームをマージし、自動的に再接続するイテレーター (AsyncSquareCloud では非同期イテレーター) です。

`client.apps.realtime(app_id)` は、アプリのログ、ステータス、システムイベントのライブストリームを開きます。`SquareCloud` では `for` で消費する**イテレーター**、`AsyncSquareCloud` では `async for` で消費する**非同期イテレーター**です。`with` / `async with` ブロック内で使えば、ブロックを抜けたときに接続が閉じられます。

<Tabs>
  <Tab title="同期">
    ```python theme={"system"}
    with client.apps.realtime(app_id) as stream:
        for event in stream:
            if event["event"] == "logs":
                print(event["stream"], event["line"])  # "stdout" | "stderr"
            elif event["event"] == "status":
                print(event["status"].get("cpu"), event["status"].get("ram"))  # always the full, merged state
            else:
                print(event["event"], event["data"])  # "system" or "error"
    ```
  </Tab>

  <Tab title="非同期">
    ```python theme={"system"}
    async with client.apps.realtime(app_id) as stream:  # no await: realtime() is not a coroutine
        async for event in stream:
            if event["event"] == "logs":
                print(event["stream"], event["line"])  # "stdout" | "stderr"
            elif event["event"] == "status":
                print(event["status"].get("cpu"), event["status"].get("ram"))  # always the full, merged state
            else:
                print(event["event"], event["data"])  # "system" or "error"
    ```
  </Tab>
</Tabs>

`AsyncSquareCloud` では、`apps.realtime(app_id)` は `AsyncRealtime` を直接返します。`await` **しないでください**。バックグラウンドの読み取りスレッドがイベントをイベントループに渡すため、待機中にエグゼキューターのスレッドが占有されることはありません。

## イベント

すべてのイベントは、`event`、`data` (生のフレームテキスト)、`id` (フレームにない場合は `None`) を持つ dict です。

| `event`   | 追加フィールド          | 説明                                                                                                                                              |
| --------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `logs`    | `stream`, `line` | ログ 1 行。`data` の最初の文字がストリームを示します (`\u0001` は stdout、`\u0002` は stderr)。SDK はその文字を取り除いたものを `line` に入れ、`stream` を `"stdout"` または `"stderr"` に設定します |
| `status`  | `status`         | コンテナのライブメトリクス。最初のフレームは完全で、以降のフレームは変更点のみを含みます。SDK がそれらをマージするため、`status` は常に完全な状態です                                                               |
| `system`  |                  | `REALTIME_CONNECTING \| <id>`、`REALTIME_TIMEOUT`、`REALTIME_DISCONNECTED` などの接続イベント                                                              |
| `error`   |                  | `CONTAINER_NOT_FOUND` などのエラーコード                                                                                                                 |
| `message` |                  | `event` 名のないフレーム                                                                                                                                |

### `status` オブジェクト

| フィールド      | 説明                                          |
| ---------- | ------------------------------------------- |
| `cpu`      | CPU 使用率 (%)                                 |
| `cpuLimit` | 割り当てられた CPU コア数                             |
| `ram`      | `[usedMB, limitMB]`                         |
| `status`   | コンテナの状態 (例: `running`)                      |
| `netIO`    | ネットワークの `{ i, o }` 合計。直近の間隔の値は `new` に含まれます |
| `bIO`      | ディスクの `{ i, o }` 合計                         |
| `uptime`   | コンテナが起動した時刻の Unix ミリ秒                       |

## ストリームの終了

ループは次の場合に自動的に終了します:

* サーバーが接続を正常に閉じたとき (各接続は最大 **10 分**続きます)
* サーバーが `REALTIME_DISCONNECTED` を送信したとき
* ループから `break` したとき (その後 `with` ブロックを抜けると接続が閉じられます)
* 任意のスレッドから `stream.close()` を呼び出したとき。ループがデータや再接続を待っている最中でも有効です (ループは単に終了し、例外は送出されません)

`close()` は `Realtime` と `AsyncRealtime` のどちらでも同期です。10 分を超えて監視を続けるには、ループが終了したときに新しいストリームを開いてください。

```python theme={"system"}
import threading

stream = client.apps.realtime(app_id)
threading.Timer(60, stream.close).start()  # stop after one minute

for event in stream:
    print(event["event"], event["data"])
```

## 再接続

接続が切れた場合や、サーバーが再接続をクライアントに委ねた場合 (`REALTIME_RECONNECT`)、ストリームは自動的に再び開かれます:

* **連続 3 回**まで。`logs` または `status` のイベントを受け取るとカウントはリセットされます
* API の制限 (アプリごとに 5 秒に 1 回のオープン) を下回るよう、各再オープンは前回のオープンから最低 **5.5 秒**空けて行われます

再接続に 3 回失敗すると、ループは `NETWORK_ERROR` の `SquareCloudAPIError` を送出します。各オープンは `GET` なので、オープン中のネットワークエラーも最大 `max_retries` 回[リトライ](/ja/sdks/py/errors#リトライ)されます。それでも失敗したオープンは例外を送出します。

## 制限とエラー

* 同時接続数は、全ユーザー合計でアカウントごとに **5**、アプリごとに **30** です。超過すると 429 `REALTIME_MAX_CONNECTIONS` または `REALTIME_MAX_CONNECTIONS_APP` になります。
* HTTP ステータスはストリーミングの前にチェックされるため、これらのエラー (および不明なアプリに対する 404) は最初の反復で送出されます。
* タイムアウトは、レスポンスヘッダーが届くまでのオープン処理のみが対象です。ストリーム自体にタイムアウトはありません。半開きの接続 (スリープから復帰したノート PC など) は、`close()` を呼び出すまで待ち続けます。
