This guide walks you through setting up Baselime for error monitoring and observability in myimageupscaler.com.
- Overview
- Prerequisites
- Account Setup
- Environment Variables
- How It Works
- Using the Server Logger
- Testing
- Production Deployment
- Dashboard & Alerts
- Troubleshooting
Baselime provides:
- Client-side Real User Monitoring (RUM) - Captures browser errors and Web Vitals
- Server-side Edge Logging - Captures API route errors and logs
- Automatic Error Tracking - Unhandled exceptions are reported automatically
- Web Vitals - LCP, FID, CLS metrics for performance monitoring
Browser (React) Server (API Routes)
│ │
▼ ▼
BaselimeRum BaselimeLogger
│ │
└──────────┬─────────────────┘
▼
Baselime Console
(Logs, Errors, Metrics)
- Baselime Account: Sign up for free
- Project Setup: myimageupscaler.com with packages installed:
@baselime/react-rum(client-side)@baselime/edge-logger(server-side)
- Go to console.baselime.io
- Sign up with GitHub or email
- Create a new environment (e.g., "myimageupscaler.com-production")
- Go to Settings > API Keys
- Create a new API key or use the default one
- Copy the API key (you'll use this for both client and server)
Note: Baselime uses the same API key for both client RUM and server logging. The client key is safe to expose as it only allows sending data, not reading it.
This project uses split environment files:
.env (public variables):
# Baselime monitoring (client-side RUM)
NEXT_PUBLIC_BASELIME_KEY=your-api-key-here.env.prod (server-side secrets):
# Baselime monitoring (server-side)
BASELIME_API_KEY=your-api-key-hereNote: Both keys can be the same value from Baselime Console. The client key is safe to expose as it only allows sending data.
- Go to Workers & Pages > Your Project > Settings > Environment Variables
- Add:
NEXT_PUBLIC_BASELIME_KEY(can be plaintext)BASELIME_API_KEY(mark as secret/encrypted)
The BaselimeProvider component in src/components/monitoring/BaselimeProvider.tsx wraps your app and automatically:
- Captures unhandled JavaScript errors
- Reports Web Vitals (LCP, FID, CLS)
- Tracks page loads and sessions
- Skips monitoring in development mode
// Already configured in src/components/ClientProviders.tsx
<BaselimeProvider>{children}</BaselimeProvider>Use the logger utility in API routes for structured logging and error capture.
import { createLogger } from '@/lib/monitoring/logger';
export async function POST(request: Request) {
const logger = createLogger(request, 'upscale-api');
try {
logger.info('Processing upscale request', {
userId: 'user-123',
imageSize: 1024,
});
// Your logic here...
logger.info('Upscale completed successfully');
return Response.json({ success: true });
} catch (error) {
logger.error('Upscale failed', {
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
});
return Response.json({ error: 'Failed' }, { status: 500 });
} finally {
// IMPORTANT: Always flush logs before response completes
await logger.flush();
}
}The withLogging wrapper handles error capture and flushing automatically:
import { withLogging } from '@/lib/monitoring/logger';
export const POST = withLogging('upscale-api', async (request, logger) => {
logger.info('Processing request');
const body = await request.json();
logger.info('Request body parsed', { imageCount: body.images?.length });
// Your logic here...
return Response.json({ success: true });
});logger.info('Informational message', { context: 'data' });
logger.warn('Warning message', { issue: 'something' });
logger.error('Error message', { error: 'details' });
logger.debug('Debug message', { verbose: 'data' });const logger = createLogger(request, 'checkout-api', {
userId: user.id,
requestId: crypto.randomUUID(),
tier: user.subscription?.tier,
});-
Add a test error in any component:
useEffect(() => { throw new Error('Test Baselime error'); }, []);
-
Check Baselime Console for the error
- Add logging to an API route
- Make a request to that endpoint
- Check Baselime Console for logs
In development, logs are printed to console instead of sent to Baselime:
# You'll see logs like:
[baselime] info: Processing request { imageSize: 1024 }- Add
NEXT_PUBLIC_BASELIME_KEYto Cloudflare Pages - Add
BASELIME_API_KEYto Cloudflare Pages (as secret) - Deploy and verify logs appear in Baselime Console
- Set up alert notifications (Slack/email)
- Visit your production site
- Open browser DevTools > Network
- Look for requests to
rum.baselime.io - Check Baselime Console for incoming data
- Go to Baselime Console > Alerts
- Create alerts for:
- Error rate spike: Alert when errors exceed threshold
- New error: Alert on first occurrence of new errors
- Web Vitals: Alert when LCP/CLS degrades
| Alert | Condition | Channel |
|---|---|---|
| High error rate | >10 errors in 5 min | Slack |
| New error type | First occurrence | |
| LCP degradation | LCP > 4s | Slack |
| API failure | 5xx errors > 5/min | Slack |
- Go to Settings > Integrations
- Add Slack workspace
- Select channel for alerts
- Check API key: Verify
BASELIME_API_KEYis set correctly - Check flush: Ensure
logger.flush()is called - Check environment: Logs are only sent when API key is present
- Check key: Verify
NEXT_PUBLIC_BASELIME_KEYis set - Check network: Look for blocked requests to
rum.baselime.io - Check provider: Ensure
BaselimeProviderwraps your app
In development (NODE_ENV=development), Baselime is disabled by default. To enable:
// In BaselimeProvider.tsx, remove the development check:
if (!apiKey) {
// Remove: || process.env.NODE_ENV === 'development'
return <>{children}</>;
}Baselime free tier includes generous limits. If exceeded:
- Check for log spam (reduce verbose logging)
- Filter out non-critical logs
- Upgrade plan if needed
Creates a new logger instance.
| Parameter | Type | Description |
|---|---|---|
request |
Request |
The incoming request object |
namespace |
string |
Identifier for the log source (e.g., 'upscale-api') |
context |
object |
Optional additional context to include in all logs |
Wraps an API handler with automatic logging.
| Parameter | Type | Description |
|---|---|---|
namespace |
string |
Identifier for the log source |
handler |
function |
(request, logger) => Promise<Response> |