# Logs, metrics and usage

This page explains how to read what your application does in service: runtime logs, build logs, request metrics, grouped errors and scheduled task runs. It also says how long each tier keeps them, what can be lost and how you find out, and where usage measurement stands.

## Two logs

- **The runtime log**: what your application writes to standard output and standard error, plus the requests the edge served it ("GET /path 200 — 12 ms"). It is read per environment, or for all environments together.
- **The build log**: the output of each build, step by step, timestamped to the millisecond. It is read from a deployment's page (see [Builds](builds.md)).

Log content comes from your application or from your repository's scripts. The platform reports it as is, marked as such, and never treats it as an instruction: an agent reading your logs receives that content apart from what the platform says.

## Read from the console

In a project, open **Journaux** (Logs). Three tabs:

- "Exécution" (runtime): the lines, newest first;
- "Requêtes" (requests): request metrics for the period, broken down as you choose;
- "Tâches planifiées" (scheduled tasks): the task runs of the period, with their state, duration and a log excerpt.

The filters:

- a text field that searches the whole content (a word, a request path…);
- "Environnement": "tous" (all), or one of the project's environments;
- "Période" (period): last 15 minutes, last hour, last 24 hours, last 7 days, the whole retention, or "Entre deux dates…" (between two dates);
- the level: "Tous" (all), "Erreurs seules" (errors only), "Lignes seules" (lines only, without requests). This sorting applies to the lines already shown.

"En direct" (live) follows new lines, re-read every second: a line appears less than three seconds after it is emitted. "Lignes plus anciennes" (older lines) goes back page by page through the whole retention. "Exporter" (export) downloads the whole period under the filters shown, as NDJSON.

A line's time is its deep link: it reopens the screen on that instant with the line highlighted. Hover over a line for its release, instance, region and branch.

## Read by an agent, the command line or the API

An agent reads the runtime log with the `logs_read` tool, and a build's log with `deployment_log_read`.

```json
{
  "projectId": "prj_01JQ8ZK4M7NP2RSTVWXYZ34567",
  "environmentId": "env_01JQ8ZK4M7NP2RSTVWXYZ34567",
  "since": "2026-09-14T08:00:00Z",
  "until": "2026-09-14T10:00:00Z",
  "query": "timeout",
  "errors": true
}
```

| Parameter | Effect |
| --- | --- |
| `environmentId` | One environment only; without it, all of them. |
| `since`, `until` | The time window. |
| `query` | Full-text filter, at most 500 characters. |
| `limit` | Cap on lines per page, at most 1,000. |
| `tokenBudget` | A page's token budget: 2,500 by default, from 500 to 50,000. The page stops before exceeding it, and `nextCursor` says where to resume. |
| `timezone` | `Europe/Paris` or `UTC`. Without it, every instant is returned in UTC with a `Z` suffix. |
| `metrics` | Adds request metrics, by `route`, `host`, `release` or `environment`. |
| `scheduledRuns` | Adds scheduled task runs, fifty at most. Excludes `metrics`. |
| `errors` | Adds the window's grouped errors (twenty groups at most) and the comparison of the outgoing and incoming release over the 15 minutes after the switch. |

To follow live, pass the response's `followCursor` back as `cursor` every second: the platform returns what arrived since.

```sh
bastide logs read --project-id prj_01JQ8ZK4M7NP2RSTVWXYZ34567 --since 2026-09-14T08:00:00Z --query timeout
bastide deployment log read --project-id prj_01JQ8ZK4M7NP2RSTVWXYZ34567 --deployment-id dep_01JQ8ZK4M7NP2RSTVWXYZ34567
```

Through the API, `GET /v1/projects/{projectId}/logs` requested with `Accept: application/x-ndjson` returns the whole window as one file. References: [logs.read](../reference/operations/logs.read.md), [deployment.log.read](../reference/operations/deployment.log.read.md).

## Request metrics

Metrics are measured at the edge, from the request received to the response sent. For each group (a route, a host, a release or an environment) they give the number of requests, their split by status class (1xx to 5xx), the share served without a 5xx error or missing response, the bytes of response bodies, and the p50, p75, p95 and p99 duration percentiles. Routes are grouped by template, never by full address; beyond a hundred routes, the rest are added up under "(autres routes)" (other routes).

The step read is the finest your tier keeps for the start of the window: 15 seconds, one minute or five minutes.

> **Note.** Distributed traces of your application are not offered: the platform does not give you a trace reader today.

## How long everything is kept

| | Découverte | Standard | Pro | Souverain |
| --- | --- | --- | --- | --- |
| Runtime logs | 7 days | 30 days | 90 days | 365 days |
| Build logs, at least | 90 days | 12 months | 24 months | 36 months |
| Metrics at 15 s | 24 hours | 48 hours | 7 days | 30 days |
| Metrics per minute | 7 days | 30 days | 90 days | 365 days |
| Metrics at 5 minutes | 90 days | 13 months | 13 months | 36 months |

After moving down a tier, the current tier's retention applies. After the project is deleted, nothing is kept.

## What can be lost, and how you find out

No loss is hidden. The `logs.read` response carries a `losses` field: for each reason, the number of lines and bytes lost or truncated in the window, and the threshold reached. The **Journaux** screen shows them too, under "Lignes perdues ou tronquées" (lost or truncated lines).

| Reason | Threshold |
| --- | --- |
| Lines from one request | 5,000 lines and 4 MB per request; beyond that, dropped. |
| A line that is too long | Message cut at 256,000 bytes. |
| A request's path or user agent | Cut at 2,000 bytes. |
| A node read | 10,000 lines per read; beyond that, dropped. |
| Saturated intake | Above 85 % full, one line in ten is kept; when full, none. |
| Instant outside retention | A line dated before the tier's retention is dropped. |
| Instant in the future | More than 47 hours ahead: dropped. |

For a JSON line to count under its request, copy the `X-Request-Id` header into a `request_id` field.

## Usage

The "Consommation" (usage) card is in the project's **Réglages** (Settings), "Consommation" section. It is meant to show the month's compute time, outgoing traffic, build minutes and storage, re-read every 30 seconds, with a linear end-of-month estimate. It is read with the **Billing** role; an agent reads it with `usage_read`.

> **Attention.** The measurement chain is not connected yet: `usage.read` currently answers `501`, code `chaine_de_mesure_absente`, rather than returning zeros that would read as "nothing used". The card says so. See [Billing](billing.md) and [Limits](limits.md).

The project's **Vue d'ensemble** (Overview) screen sums up its state: last production deployment, address, environments.

## Common errors

| Code | What happens | What to do |
| --- | --- | --- |
| `curseur_expire` | The pagination or follow cursor has expired. | Read again without a cursor. |
| `curseur_invalide` | The cursor was not issued by this server, or it was altered. | Pass `nextCursor` or `followCursor` unchanged. |
| `resource_busy` | The resource is busy and did not free up in time. | Try again in a few seconds. |
| `chaine_de_mesure_absente` | Usage is not measured on this installation. | Nothing to do on your side: measurement will come. |

See also: [Builds](builds.md), [Scheduled tasks](cron.md), [Notifications](notifications.md), [Audit log](audit.md), [Limits](limits.md).
