Expose a /health endpoint, configure ANS error-rate alerts, and use cf app / cf logs for incident triage.
/health endpoint from CAP for uptime monitoringcf app and cf events for first-level incident triageYou won't be watching the logs 24/7. When something breaks in production you need an alert in Slack or email within minutes, not days. Proper monitoring also tells you when your app is approaching memory limits or when a specific endpoint is suddenly slow — before a user files a ticket.
| Tool | Best for |
|---|---|
| BTP Cockpit (app overview) | CPU / memory / instance count at a glance |
cf app / cf logs |
First-level triage from CLI |
| SAP Application Logging (Kibana) | Log-level query and error search |
| SAP Alert Notification Service | Event-driven alerts to email/Slack/PagerDuty |
| SAP Cloud ALM | Cross-landscape health dashboard (enterprise) |
Custom /health endpoint |
External uptime monitors (UptimeRobot, Pingdom) |
/health endpoint in CAP// srv/server.js
const cds = require('@sap/cds');
cds.on('bootstrap', async app => {
app.get('/health', async (req, res) => {
try {
// Ping the database
const db = await cds.connect.to('db');
await db.run('SELECT 1 FROM dummy');
res.status(200).json({
status: 'UP',
timestamp: new Date().toISOString(),
version: process.env.npm_package_version
});
} catch (err) {
res.status(503).json({
status: 'DOWN',
error: err.message
});
}
});
});
The /health endpoint bypasses XSUAA (no @requires) so external uptime monitors can call it without authentication. Ensure it does not expose sensitive information — just UP/DOWN and a timestamp.
See Episode 60 for full setup. For monitoring-specific alerts:
// Alert on high error rate in a 5-minute window
// (implemented as a periodic check job — Episode 65)
const ans = await cds.connect.to('AlertNotificationService');
const errorCount = await db.run(
`SELECT COUNT(*) AS n FROM ErrorLog WHERE ts > NOW() - INTERVAL '5' MINUTE`
);
if (errorCount.n > 50) {
await ans.post('/producer/v1/resource-events', {
eventType: 'HighErrorRate',
eventTimestamp: Date.now(),
severity: 'CRITICAL',
resource: {
resourceName: 'my-cap-app',
resourceType: 'Application'
},
body: {
state: 'PROBLEM',
details: `${errorCount.n} errors in the last 5 minutes`
}
});
}
cf app for live metrics# Current memory, CPU, instances, status
cf app my-cap-app-srv
# Example output:
# Instances running: 2/2
# Memory usage: 312M / 512M
# CPU: 3.1% / 3.8%
# Disk: 423M / 1G
# Recent CF platform events (restarts, crashes)
cf events my-cap-app-srv
# Stream live logs (combine with grep for errors)
cf logs my-cap-app-srv | grep -i error
In manifest.yml or MTA:
memory: 512M
disk_quota: 1G
instances: 2
Autoscale with the CF App Autoscaler (if entitled):
# autoscaler-policy.json
{
"instance_min_count": 2,
"instance_max_count": 5,
"scaling_rules": [
{ "metric_type": "memoryused", "threshold": 400, "operator": ">=", "adjustment": "+1" },
{ "metric_type": "memoryused", "threshold": 200, "operator": "<", "adjustment": "-1" }
]
}
When an alert fires:
1. cf app my-cap-app-srv — is the app running? How many instances are UP?
2. cf logs my-cap-app-srv --recent — look for ERROR lines around the incident time
3. Kibana: filter level: ERROR AND @timestamp: [now-30m TO now]
4. cf events my-cap-app-srv — any recent crashes or restarts?
5. BTP Cockpit → HANA Cloud → Monitor — is the DB healthy?
6. If memory usage > 90% → cf scale my-cap-app-srv -m 1G to buy time
7. If stuck deploy → cf mta-ops → abort / resume
| Mistake | Fix |
|---|---|
No /health endpoint |
Uptime monitors have nothing to poll |
/health endpoint behind auth |
External monitors can't reach it — no @requires |
Not setting instances: 2 minimum |
One crash = total downtime |
| Alerting on every error | Alert on error RATE — individual errors are noise |
| Not logging the correlationId | You can't trace a specific user complaint in Kibana |
You can expose a /health endpoint that pings the database, configure ANS alerts on error rate, use cf app, cf logs, and cf events for triage, and follow a structured incident checklist from alert to resolution.