Documentation Index
Fetch the complete documentation index at: https://mintlify.com/KingPsychopath/oooc-fete-finder/llms.txt
Use this file to discover all available pages before exploring further.
Overview
OOOC Fête Finder uses structured logging for observability in development and production. Logs are human-readable in development and JSON-formatted in production for log aggregation services.
Logger model
The application uses a centralized logger:
// lib/platform/logger.ts
import { log } from "@/lib/platform/logger";
log.info("scope", "message", { context });
log.warn("scope", "message", { context });
log.error("scope", "message", { context }, error);
Human-readable logs with emoji indicators:
· [cache] Events loaded {"source":"store","count":123}
⚠ [geocoding] Using arrondissement fallback (API unavailable)
✗ [database] Connection failed {"attempt":3}
→ connect ECONNREFUSED 127.0.0.1:5432
Structured JSON logs (one per line):
{"level":"info","scope":"cache","message":"Events loaded","context":{"source":"store","count":123},"ts":"2026-02-28T10:30:00.000Z"}
{"level":"warn","scope":"geocoding","message":"Using arrondissement fallback (API unavailable)","ts":"2026-02-28T10:30:05.000Z"}
{"level":"error","scope":"database","message":"Connection failed","context":{"attempt":3},"error":{"message":"connect ECONNREFUSED","stack":"..."},"ts":"2026-02-28T10:30:10.000Z"}
What is logged
The application logs the following events:
Startup and runtime mode
log.info("startup", "Data mode configured", { mode: "remote" });
log.info("startup", "Database pool initialized", { maxConnections: 3 });
log.info("startup", "Geocoding API available", { provider: "google-maps" });
Runtime read operations
log.info("cache", "Events loaded from store", {
source: "postgres-store",
count: 123,
cached: false
});
log.warn("cache", "Store read failed, using fallback", {
source: "local-csv",
error: "Connection timeout"
});
Revalidation operations
log.info("cache", "Homepage revalidated", {
trigger: "admin-save",
eventCount: 125
});
log.error("cache", "Revalidation failed", undefined, error);
Geocoding operations
log.warn("geocoding", "API key not configured, using fallback");
log.info("geocoding", "Batch geocoding completed", {
total: 150,
cached: 140,
fetched: 10,
failed: 0
});
Authentication and rate limiting
log.warn("auth", "Rate limiter unavailable, proceeding without limit check");
log.info("auth", "Admin session created", { sessionId: "abc123" });
log.warn("auth", "Rate limit exceeded", {
ip: "192.0.2.1",
endpoint: "/api/track"
});
Database operations
log.info("database", "Event store updated", {
rowCount: 125,
updatedBy: "admin",
origin: "manual"
});
log.error("database", "Transaction failed", { operation: "save-events" }, error);
Noise controls
To reduce log spam, the logger implements deduplication:
Development info deduplication
// Development only: dedupe identical info logs within 1.2s window
const DEV_INFO_DEDUPE_WINDOW_MS = 1200;
if (IS_DEV && level === "info" && shouldSkipDevInfoLog(scope, message, context)) {
return; // Skip duplicate log
}
warn and error logs are never deduplicated. Only info logs in development are deduplicated.
Intentionally removed logs
The following logs were removed to reduce noise:
- Per-address geocoding failures: Batch summary only
- Repetitive coordinate-skip logs: Aggregated warnings
- Periodic memory dump spam: Removed entirely
- Duplicate startup messages: Deduplicated
Deduplication affects logs only, not runtime behavior. All geocoding attempts still occur even if individual failures aren’t logged.
Log levels
Info
Normal operations and successful actions:
log.info("cache", "Events loaded", { source: "store", count: 123 });
log.info("backup", "Snapshot created", { id: "snap_abc", rowCount: 125 });
log.info("admin", "Event sheet saved", { updatedBy: "admin" });
Warning
Non-critical issues that don’t prevent operation:
log.warn("geocoding", "Using fallback coordinates");
log.warn("auth", "Rate limiter unavailable");
log.warn("cache", "Stale data served, refresh failed");
Error
Critical failures requiring attention:
log.error("database", "Connection failed", undefined, error);
log.error("backup", "Snapshot creation failed", { trigger: "cron" }, error);
log.error("admin", "Event validation failed", { rowCount: 5 }, error);
Accessing logs
Vercel function logs
View real-time logs in Vercel dashboard:
Navigate to deployment
Vercel Dashboard > Deployments > Select deployment
Open logs tab
Click “Logs” tab to view function invocation logs
Filter by log level
Use search to filter:
"level":"error" for errors only
"scope":"database" for database logs
"scope":"cache" for cache operations
Local development logs
View logs in terminal where pnpm dev is running:
pnpm dev
# Output:
· [cache] Events loaded {"source":"local-csv","count":123}
· [geocoding] Using fallback coordinates
⚠ [auth] ADMIN_KEY not set, admin routes disabled
Health check script
Run diagnostics with detailed logging:
DATABASE_URL="your-url" \
ADMIN_KEY="your-key" \
BASE_URL="https://your-domain.com" \
pnpm health:check
Outputs:
=== Postgres Connectivity ===
Postgres connection: OK
=== KV Store Keys ===
- users:collection:v1 (updated 2026-02-28T10:30:00.000Z)
Key count: 1
=== Events CSV Row Counts ===
meta.rowCount: 123
raw CSV rows (excluding header): 123
metadata updatedAt: 2026-02-28T10:30:00.000Z
=== Event Tables Row Counts ===
rows table count: 123
columns table count: 17
meta row_count: 123
meta matches rows: yes
Troubleshooting pattern
When issues occur, follow this diagnostic flow:
Check environment variables
Verify required variables are set:# Essential variables
DATABASE_URL=postgresql://...
AUTH_SECRET=your-secret-here
DATA_MODE=remote
ADMIN_KEY=your-admin-key
See Environment Variables for complete list. Check data manager source
From /admin/operations, review “Live Runtime Snapshot”:
- Data source (should be
postgres-store)
- Event count
- Last updated timestamp
- Any error messages
Validate database health
Call the health endpoint:curl https://your-domain.com/api/admin/health \
-H "x-admin-key: your-admin-key"
Expected response:{
"status": "healthy",
"database": "connected",
"dataMode": "remote",
"eventCount": 123
}
Re-run publish flow
From /admin/operations:
- Click “Backup Now” (safety snapshot)
- Navigate to
/admin/content
- Open “Event Sheet Editor”
- Return to
/admin/operations
- Click “Save and Revalidate Homepage”
- Verify “Live Runtime Snapshot” updates
See Admin Workflow for details.
Common log patterns
Successful event load
· [cache] Events loaded {"source":"postgres-store","count":123,"cached":false}
Meaning: Fresh data loaded from PostgreSQL successfully.
Database fallback
⚠ [cache] Store read failed, using fallback {"source":"local-csv","error":"Connection timeout"}
Meaning: PostgreSQL unavailable, falling back to local CSV. Check DATABASE_URL.
Geocoding API unavailable
⚠ [geocoding] Using arrondissement fallback (API unavailable)
Meaning: GOOGLE_MAPS_API_KEY not set or quota exceeded. Using district center coordinates.
Rate limiter unavailable
⚠ [auth] Rate limiter unavailable, proceeding without limit check
Meaning: Redis/KV store unavailable for rate limiting. Requests proceed without rate limiting.
Cron job execution
· [backup] Snapshot created {"id":"backup_20260228","rowCount":123,"prunedCount":5}
Meaning: Daily backup cron ran successfully, created snapshot, pruned 5 old backups.
Log aggregation
For production monitoring, integrate with log aggregation services:
Vercel Log Drains
Configure in Vercel dashboard:
Choose log drain service
Options:
- Datadog
- LogDNA
- Logtail
- Axiom
- Custom HTTPS endpoint
Configure drain
Project Settings > Log Drains > Add Log Drain
Query structured logs
Use service’s query language to filter logs:-- Example: Datadog query
@level:error @scope:database
-- Example: LogDNA query
level:error scope:cache
Custom queries
Example queries for common investigations:
-- All database errors in last hour
@level:error @scope:database @ts:>now-1h
-- Cache operations by source
@scope:cache | count by @context.source
-- Geocoding fallback frequency
@scope:geocoding @message:"Using arrondissement fallback"
Alerting
Set up alerts for critical issues:
Database connectivity
Alert when: @level:error @scope:database @message:"Connection failed"
Threshold: > 3 occurrences in 5 minutes
Action: Page on-call engineer
Backup failures
Alert when: @level:error @scope:backup @message:"Snapshot creation failed"
Threshold: > 1 occurrence
Action: Slack notification to ops channel
High error rate
Alert when: @level:error
Threshold: > 10 errors per minute
Action: PagerDuty alert
Debug mode
For intensive debugging, temporarily increase log verbosity:
// lib/platform/logger.ts
// Disable deduplication temporarily
const DEV_INFO_DEDUPE_WINDOW_MS = 0; // Set to 0
// Or add temporary debug logs
log.info("debug", "Variable state", { foo, bar, baz });
Remember to remove debug logs before committing. Use git diff to review changes.
Logging overhead is minimal:
- Development: ~0.1-0.5ms per log (includes console formatting)
- Production: ~0.05-0.2ms per log (JSON serialization only)
- Deduplication: O(1) lookup in Map (negligible)
For high-throughput operations, batch log context:
// Good: Single log with batch summary
log.info("geocoding", "Batch completed", {
total: 150,
cached: 140,
fetched: 10,
failed: 0
});
// Avoid: 150 individual logs
for (const address of addresses) {
log.info("geocoding", "Geocoded address", { address }); // Too noisy!
}
Next steps