Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: runwhen.com/v1
kind: GenerationRules
spec:
platform: vercel
generationRules:
- resourceTypes:
- vercel_project
matchRules:
- type: pattern
pattern: ".+"
properties: [name]
mode: substring
slxs:
- baseName: vercel-project-http-error-health
qualifiers: ["team", "project"]
baseTemplateName: vercel-project-http-error-health
levelOfDetail: basic
outputItems:
- type: slx
- type: sli
- type: runbook
templateName: vercel-project-http-error-health-taskset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
apiVersion: runwhen.com/v1
kind: ServiceLevelIndicator
metadata:
name: {{slx_name}}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
displayUnitsLong: Health Score
displayUnitsShort: score
locations:
- {{default_location}}
description: Aggregates binary 5xx and 4xx health from sampled Vercel runtime logs into a 0-1 score.
codeBundle:
{% if repo_url %}
repoUrl: {{repo_url}}
{% else %}
repoUrl: https://github.com/runwhen-contrib/rw-cli-codecollection.git
{% endif %}
{% if ref %}
ref: {{ref}}
{% else %}
ref: main
{% endif %}
pathToRobot: codebundles/vercel-project-http-error-health/sli.robot
intervalStrategy: intermezzo
intervalSeconds: 180
configProvided:
- name: VERCEL_TEAM_ID
value: "{{ match_resource.resource.team_id }}"
- name: VERCEL_PROJECT
value: "{{ match_resource.resource.name }}"
- name: LOOKBACK_MINUTES
value: "60"
- name: ERROR_RATE_THRESHOLD_PCT
value: "1"
- name: MIN_ERROR_EVENTS
value: "5"
- name: EXCLUDE_404_FROM_4XX
value: "true"
secretsProvided:
{% if wb_version %}
{% include "vercel-auth.yaml" ignore missing %}
{% else %}
- name: vercel_api_token
workspaceKey: AUTH DETAILS NOT FOUND
{% endif %}
alertConfig:
tasks:
persona: eager-edgar
sessionTTL: 10m
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apiVersion: runwhen.com/v1
kind: ServiceLevelX
metadata:
name: {{ slx_name }}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
imageURL: https://storage.googleapis.com/runwhen-nonprod-shared-images/icons/cloud/cloud.svg
alias: Vercel HTTP Error Health for {{ match_resource.resource.name }}
asMeasuredBy: Sampled runtime log error rates for 5xx and 4xx responses versus thresholds.
configProvided:
- name: SLX_PLACEHOLDER
value: SLX_PLACEHOLDER
owners:
- {{ workspace.owner_email }}
statement: Production HTTP 4xx/5xx rates from Vercel runtime logs should remain within configured thresholds.
additionalContext:
qualified_name: "{{ match_resource.qualified_name }}"
tags:
- name: cloud
value: vercel
- name: service
value: vercel_project
- name: scope
value: project
- name: access
value: read-only
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
apiVersion: runwhen.com/v1
kind: Runbook
metadata:
name: {{slx_name}}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
location: {{default_location}}
description: Monitors Vercel runtime HTTP 4xx/5xx health for a project deployment using sampled logs.
codeBundle:
{% if repo_url %}
repoUrl: {{repo_url}}
{% else %}
repoUrl: https://github.com/runwhen-contrib/rw-cli-codecollection.git
{% endif %}
{% if ref %}
ref: {{ref}}
{% else %}
ref: main
{% endif %}
pathToRobot: codebundles/vercel-project-http-error-health/runbook.robot
configProvided:
- name: VERCEL_TEAM_ID
value: "{{ match_resource.resource.team_id }}"
- name: VERCEL_PROJECT
value: "{{ match_resource.resource.name }}"
- name: LOOKBACK_MINUTES
value: "60"
- name: ERROR_RATE_THRESHOLD_PCT
value: "1"
- name: MIN_ERROR_EVENTS
value: "5"
- name: EXCLUDE_404_FROM_4XX
value: "true"
secretsProvided:
{% if wb_version %}
{% include "vercel-auth.yaml" ignore missing %}
{% else %}
- name: vercel_api_token
workspaceKey: AUTH DETAILS NOT FOUND
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
version: "3"

tasks:
default:
desc: "Validate bundle structure"
cmds:
- task: validate-bundle-structure

clean:
desc: "Remove generated workspaceInfo if present"
cmds:
- rm -f workspaceInfo.yaml

build-infra:
desc: "No external infra required for Vercel API bundle; runs validation only"
cmds:
- task: validate-bundle-structure

validate-bundle-structure:
desc: "Check runbook, SLI, and RunWhen templates are present"
cmds:
- bash ./validate-bundle-structure.sh
silent: true

check-unpushed-commits:
desc: "Check for uncommitted changes outside .test"
vars:
BASE_DIR: "../"
cmds:
- |
UNCOMMITTED=$(git diff --name-only HEAD 2>/dev/null | grep -E "^${BASE_DIR}" | grep -v "/\.test/" || true)
if [ -n "$UNCOMMITTED" ]; then
echo "Uncommitted changes found. Commit before integration testing."
exit 1
fi
silent: true

generate-rwl-config:
desc: "Stub — Vercel bundle uses API tokens; extend for RunWhen Local if needed"
cmds:
- 'echo "stub: add workspaceInfo.yaml for rwl when testing against a workspace"'

run-rwl-discovery:
desc: "Stub — discovery requires workspace context"
cmds:
- 'echo "stub: run RunWhen Local discovery when workspace resources exist"'

clean-rwl-discovery:
desc: "Remove discovery output"
cmds:
- rm -rf output
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# Sanity check that required CodeBundle files exist (local dev / CI helper).
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
test -f "$ROOT/runbook.robot"
test -f "$ROOT/sli.robot"
test -f "$ROOT/.runwhen/generation-rules/vercel-project-http-error-health.yaml"
test -f "$ROOT/.runwhen/templates/vercel-project-http-error-health-slx.yaml"
test -f "$ROOT/.runwhen/templates/vercel-project-http-error-health-taskset.yaml"
test -f "$ROOT/.runwhen/templates/vercel-project-http-error-health-sli.yaml"
echo "vercel-project-http-error-health bundle structure OK"
56 changes: 56 additions & 0 deletions codebundles/vercel-project-http-error-health/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Vercel Project HTTP Error Health

This CodeBundle monitors frontend and edge/serverless request health on Vercel by sampling **runtime logs** for the latest **production** deployment. It reports 4xx and 5xx rates against configurable thresholds, optional 404 handling for 4xx analysis, and the top request paths driving failures.

## Overview

- **Access validation**: Confirms the API token can read the team scope and resolves the project by id or slug.
- **Deployment selection**: Uses the latest `READY` deployment with `target=production` as the log source (documented in the resolve task output).
- **Error rates**: Computes 5xx and (optionally non-404) 4xx rates from sampled request rows in `LOOKBACK_MINUTES`, compared to `ERROR_RATE_THRESHOLD_PCT` and `MIN_ERROR_EVENTS`.
- **Top paths**: Lists the most frequent failing paths for 5xx and for 4xx (with optional 404 exclusion).

Runtime logs are retrieved via `GET /v1/projects/{projectId}/deployments/{deploymentId}/runtime-logs` (NDJSON). High-volume traffic may be **sampled** by line limits; rates are approximate and documented in task output.

## Configuration

### Required Variables

- `VERCEL_TEAM_ID`: Vercel team id (`teamId` query parameter for API calls).
- `VERCEL_PROJECT`: Project id or slug to analyze.

### Optional Variables

- `LOOKBACK_MINUTES`: Log window ending at now (default: `60`).
- `ERROR_RATE_THRESHOLD_PCT`: Percent of sampled request rows that may be errors before raising a rate issue (default: `1`).
- `MIN_ERROR_EVENTS`: Minimum error count before treating a high rate as a high-severity signal (default: `5`).
- `EXCLUDE_404_FROM_4XX`: If `true`, HTTP 404 is excluded from 4xx summaries and top-path lists (default: `true`).

### Secrets

- `vercel_api_token`: Vercel bearer token with permission to read projects and deployment runtime logs (personal or team token).

## Tasks Overview

### Validate Vercel API Access and Resolve Project

Calls `GET /v9/projects/{idOrName}` to verify credentials and resolve the project. Raises issues on HTTP 401/403/404 or other API failures.

### Resolve Production Deployment for Log Analysis

Lists production deployments and picks the newest `READY` deployment. Raises an issue if none are available (for example preview-only projects).

### Summarize 5xx Server Error Rate

Counts HTTP 500–599 responses in sampled logs and compares the rate to `ERROR_RATE_THRESHOLD_PCT` and `MIN_ERROR_EVENTS`.

### Summarize 4xx Client Error Rate (incl. 400)

Counts HTTP 400–499 responses, optionally excluding 404 when `EXCLUDE_404_FROM_4XX` is true, using the same rate thresholds.

### List Top Error Paths by 5xx Count

Prints a ranked list of paths by 5xx volume for the lookback window (informational; issues only on resolution failures).

### List Top Paths by 4xx (non-404) Count

Same for 4xx, respecting `EXCLUDE_404_FROM_4XX`.
Loading