Skip to content

Telemetry and automatic repair

App code reads the host-bound aggregate with:

js
const summary = await opencloud.telemetry.summary();

The six surfaces are page, rest, storage, realtime, function, and cron. Each surface has:

  • lastActivityAt
  • requests24h
  • errors24h
  • lastStatus

Freshness lives at activity.telemetry, not at the top level:

js
const {
  status,
  latestIngestedAt,
  ingestionLagSeconds,
  sampledEntries,
  truncated,
} = summary.activity.telemetry;

Use usage?.completeness and timestamps when showing storage/user rollups.

Honest status

js
function telemetryLabel(summary) {
  const source = summary.activity.telemetry;
  if (source.status === "unavailable") return "Telemetry unavailable";
  if (source.truncated) return "Partial sample";
  if (!source.latestIngestedAt) return "No recent evidence";
  return `Ingested ${new Date(source.latestIngestedAt).toLocaleString()}`;
}

Do not label an absent surface “healthy.” Read the exact SDK response.

Builders can also inspect scoped control-plane logs and usage:

bash
opencloud logs "$APP_ID" --level error
opencloud usage "$APP_ID"

Decide whether custom monitoring is needed

Before promotion, decide whether the app has an important product failure that OpenCloud cannot already derive. Built-in monitoring covers failed apps and deployments, failed operations and cron runs, dead-lettered background jobs, high HTTP error rate, and stale runtime telemetry. Do not duplicate those signals or add custom monitoring merely because the capability is available.

For an uncovered failure, connect the complete product signal: declare its counter or gauge, declare the matching manifest rule, and record the metric through the supported browser SDK at the real failure boundary. Counters with sum fit occurrences; gauges with latest or max fit stuck state or backlog. The generic starter does not invent a fake failure or a Function telemetry API.

Product metrics and alerts

Use manifest-declared custom counters or gauges only for product signals the platform cannot derive. Dimensions must be small, fixed enums:

yaml
observability:
  metrics:
    - name: tasks_created
      type: counter
      dimensions:
        assignee_type:
          values: [parent, child]
    - name: task_processing_failures
      type: counter
      unit: failures
  alertRules:
    - id: task-processing-failure
      name: Task processing failure
      metric: task_processing_failures
      aggregation: sum
      operator: gte
      threshold: 1
      window: 5m
      minimumSamples: 1
      severity: critical
js
await opencloud.telemetry.increment("tasks_created", 1, {
  dimensions: { assignee_type: "child" },
});

Connect the declared failure counter to the real browser failure boundary without hiding the original error:

js
async function processTask(taskId) {
  try {
    return await opencloud.functions.call("process-task", { taskId });
  } catch (error) {
    try {
      await opencloud.telemetry.increment("task_processing_failures");
    } catch {
      // Preserve the product failure when telemetry itself is unavailable.
    }
    throw error;
  }
}

The SDK owns the private idempotency key and one safe transient retry.

Agents use the app-scoped Agent Feed and fixed threshold rules rather than Grafana, PromQL, or LogQL. Read the complete telemetry and alert contract.

An enabled rule that crosses its threshold creates one deduplicated alert fire in the app's existing Agent conversation. The rule remains a stateless definition; the fire moves from unresolved to in_progress when the Agent starts working and to resolved only after its repair deployment is verified. App-owned rules belong in the same manifest revision as their metrics. They are validated before promotion and become active atomically with the deployment, so there is no post-deploy monitoring gap. Existing manually managed rules remain available for immediate operational use. Rule responses identify their origin as manifest or operational_override; an operational rule with the same ID takes precedence until it is deleted. Move a proven durable override into the next manifest revision.

Background queues contribute platform-derived jobs.created, jobs.retried, jobs.succeeded, jobs.failed, and jobs.active signals. They are retained job-state totals, not inferred 24-hour metrics, so their window is explicitly null. Recent terminal failures also appear as safe job events and activate the built-in background-job failure alert. Use the dashboard or owner job diagnostic API for per-queue depth and individual execution metadata; neither surface exposes payloads or idempotency keys.

Self-hosted infrastructure for agent-built applications.