_private/qwestly-docs/Engineering/Monitoring/vercel-log-drain.md
Table of Contents
Vercel Log Drain Engineering Documentation
Overview
This document describes the engineering details, setup, and operational considerations for the Vercel log drain integration with the Qwestly Monitoring API. The log drain enables ingestion of Vercel platform logs into our AWS S3 bucket for monitoring, compliance, and analysis.
Architecture
- Vercel sends logs via HTTP POST to our API endpoint (
/api/vercel-log-drain). - The API authenticates requests using the
X-Vercel-Signatureheader (shared secret). - The API supports both NDJSON and JSON payloads.
- The API extracts the
projectIdfrom the first log object and stores the raw log data in S3 undervercel-logs/{projectId}/{YYYY-MM-DD}/{HHMMSS}.ndjson. - Vercel verifies endpoint ownership by sending a GET request and expecting a specific value in the response header.
Endpoint Details
URL
POST /api/vercel-log-drain
GET /api/vercel-log-drain
Authentication
- Header:
X-Vercel-Signature: <secret> - The secret is set in the API as the
VERCEL_LOG_DRAIN_SECRETenvironment variable and in the Vercel dashboard as the log drain secret.
Verification
- Header:
x-vercel-verify: <verify-value> - The value is set in the API as the
VERCEL_LOG_DRAIN_VERIFYenvironment variable and in the Vercel dashboard during log drain setup. - Vercel sends a GET request to verify the endpoint; the API responds with a 200 and the
x-vercel-verifyheader.
Payload
- Content-Type:
application/x-ndjson(preferred) orapplication/json - Body: NDJSON (newline-delimited JSON objects), a JSON array, or a single JSON object.
- The API will parse and accept all three formats.
Example NDJSON
{"projectId":"prj_abc123xyz","message":"log1"}
{"projectId":"prj_abc123xyz","message":"log2"}
Example JSON Array
[
{"projectId":"prj_abc123xyz","message":"log1"},
{"projectId":"prj_abc123xyz","message":"log2"}
]
Example JSON Object
{"projectId":"prj_abc123xyz","message":"log1"}
S3 Storage Structure
- Logs are stored in the S3 bucket defined by
AWS_S3_LOGS_BUCKET(default:qwestly-logs). - Path:
vercel-logs/{projectId}/{YYYY-MM-DD}/{HHMMSS}.ndjson - The raw request body is stored as the S3 object content.
Setup Instructions
1. API Environment Variables
VERCEL_LOG_DRAIN_SECRET: Shared secret for authenticating log drain POSTs.VERCEL_LOG_DRAIN_VERIFY: Value to return in thex-vercel-verifyheader for GET requests (provided by Vercel during setup).AWS_S3_LOGS_BUCKET,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_REGION: S3 configuration.
2. Vercel Log Drain Setup
- Go to your Vercel project dashboard.
- Navigate to Settings > Log Drains.
- Add a new log drain:
- Type: HTTP
- Endpoint:
https://<your-api-domain>/api/vercel-log-drain - Secret: (same as
VERCEL_LOG_DRAIN_SECRET) - Verification: (same as
VERCEL_LOG_DRAIN_VERIFY)
- Vercel will verify the endpoint by sending a GET request and checking the
x-vercel-verifyheader. - Once verified, Vercel will POST logs to the endpoint.
Error Handling & Edge Cases
- If the signature is missing or incorrect, the API returns 401 Unauthorized.
- If the body is empty or cannot be parsed as NDJSON/JSON, the API returns 200 with the verification header (to avoid Vercel retries/disablement).
- If
projectIdis missing, the API returns 200 with the verification header. - If S3 upload fails, the API returns 200 with the verification header.
- All POST responses include the
x-vercel-verifyheader for Vercel compatibility.
Operational Notes
- The endpoint is designed to be idempotent and always return 200 for POSTs (except for signature errors), to prevent Vercel from disabling the drain.
- Logs are stored as raw NDJSON/JSON for maximum fidelity and future flexibility.
- The endpoint is compatible with both Vercelโs log drain requirements and internal monitoring needs.
Internal: Fetching Vercel Logs from S3
Endpoint
GET /api/internal/vercel-logs
Authentication
- HTTP Basic Auth (username/password from environment variables
INTERNAL_DASHBOARD_USERandINTERNAL_DASHBOARD_PASS)
Query Parameters
project_id(required): The Vercel projectId (S3 folder)date(optional, default: today, format:YYYY-MM-DD)time(optional, format:HHMMSS)
Usage
- If
timeis omitted, the endpoint lists all log files for the given project and date. - If
timeis provided, the endpoint returns the contents of the specific log file.
Example: List all log files for a project and date
GET /api/internal/vercel-logs?project_id=prj_abc123xyz&date=2024-07-08
Example: Fetch a specific log file
GET /api/internal/vercel-logs?project_id=prj_abc123xyz&date=2024-07-08&time=153012
Response
- If listing files:
{ "project_id": "prj_abc123xyz", "date": "2024-07-08", "files": ["153012.ndjson", "153045.ndjson"] } - If fetching a file:
{ "project_id": "prj_abc123xyz", "date": "2024-07-08", "time": "153012", "log": "{\"projectId\":\"prj_abc123xyz\",...}" }