App Logs
View real-time logs from your running App. Debug requests, errors, and tool calls as they happen.
mctx streams live logs from your App directly to the dashboard. Logs are real-time only — there is no log history or retention. No configuration required.
Accessing Logs
- Navigate to your App detail page (
/dev/servers/[id]) - Click View Logs in the Server Information section
- The log modal opens and begins streaming immediately
- Trigger a request to your App to see logs appear
Requirement: Your App must be in Live status. Logs are not available for Apps that are not live.
What Gets Logged
Any console.* call in your App code appears in the log stream:
| Method | Level | Use Case |
|---|---|---|
console.log() | Info | General operational events |
console.info() | Info | Informational messages |
console.warn() | Warn | Warnings and potential issues |
console.error() | Error | Errors and failures |
console.debug() | Debug | Detailed debugging info |
export default {
async fetch(request: Request, env: Env): Promise<Response> {
console.log(`[INFO] ${request.method} ${request.url}`);
try {
const result = await processRequest(request, env);
console.log("[INFO] Request processed successfully");
return result;
} catch (error) {
console.error(`[ERROR] Request failed: ${error.message}`);
throw error;
}
},
};No Retention
Logs are not stored. They are only visible while the log modal is open. Closing the modal discards all buffered output — you cannot retrieve past logs.
If you need to review logs after the fact, send them to an external service (see Persistent Logging below).
Log Best Practices
Use consistent prefixes
Prefixes make it easy to filter and scan logs in the modal:
console.log("[INFO] Tool called: weather-lookup");
console.log("[DEBUG] Parameters: " + JSON.stringify(params));
console.warn("[WARN] Rate limit approaching: " + remaining + " requests left");
console.error("[ERROR] API call failed: " + error.message);Log the request lifecycle
console.log("[INFO] " + request.method + " request received");
console.log("[INFO] Tool: " + toolName + ", Params: " + JSON.stringify(params));
console.log("[INFO] External API: " + apiUrl);
console.log("[INFO] Response status: " + response.status);Never log secret values
// Bad — exposes the secret
console.log("Using API key: " + env.API_KEY);
// Good — confirms it is present without revealing it
console.log("Using API key: " + env.API_KEY.slice(0, 4) + "...");Add timing to spot bottlenecks
const start = Date.now();
const result = await callExternalApi(query);
console.log("[INFO] API call completed in " + (Date.now() - start) + "ms");Choose the right level
| Level | When to Use |
|---|---|
DEBUG | Detailed information for troubleshooting |
INFO | Normal operational events |
WARN | Something unexpected but not an error |
ERROR | Error conditions that should be investigated |
Persistent Logging
For logs you need to keep, send them to an external service from your App code:
async function logToExternal(message: string, level: string, env: Env) {
await fetch("https://logs.example.com/ingest", {
method: "POST",
headers: {
Authorization: `Bearer ${env.LOGGING_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
timestamp: Date.now(),
level,
message,
}),
});
}Services that work well with Cloudflare Workers:
- Axiom — High-volume log analytics
- Datadog — Full observability platform
- Better Stack (Logtail) — Developer-focused logging
- New Relic — Application performance monitoring
See Also
- App Requirements — Adding logging to your App code
- Environment Variables — Storing API keys for external logging services
See something wrong? Report it or suggest an improvement — your feedback helps make these docs better.
Versioning
How versioned endpoints work on mctx. URL format, semantic versioning, version lifecycle, routing, and multiple concurrent versions.
Slug Reservation & Cooling-Off Period
How mctx reserves subdomains after App deletion. 7-day cooling-off period on production, DNS hijacking protection, and test environment behavior.