66 · SAP Application Logging Service

Bind Application Logging, configure @sap/logging middleware, emit structured JSON with correlation IDs, and query Kibana.

Episode 66 — SAP Application Logging Service

What you'll learn

Why this matters

console.log writes to stdout. On Cloud Foundry you can read stdout with cf logs, but logs disappear when the app restarts and you cannot search across instances. SAP Application Logging Service ships every log line to an Elasticsearch cluster with a Kibana UI. Structured JSON logs let you filter by tenant, user, request ID, or error level — turning a flood of text into queryable operational intelligence.

Binding the service

cf create-service application-logs standard my-app-logs
cf bind-service my-cap-app my-app-logs

MTA:

resources:
  - name: my-app-logs
    type: org.cloudfoundry.managed-service
    parameters:
      service: application-logs
      service-plan: standard

Once bound, the @sap/logging library auto-detects the binding and configures the transport — you do not need to supply credentials in code.

Installing and configuring @sap/logging

npm install @sap/logging
// srv/server.js
const logging = require('@sap/logging');
const cds     = require('@sap/cds');

cds.on('bootstrap', app => {
  // Attach the logging middleware — adds correlation ID to every request
  app.use(logging.middleware({ app }));
});

Using the logger in handlers

// srv/purchase-order-service.js
const cds    = require('@sap/cds');
const logging = require('@sap/logging');

module.exports = class PurchaseOrderService extends cds.ApplicationService {
  async init() {
    const { PurchaseOrders } = this.entities;

    this.before('CREATE', PurchaseOrders, async req => {
      // Get a logger scoped to this request (carries correlation ID automatically)
      const logger = logging.createLogger({ layer: 'purchase-order-service' });

      logger.info('Creating purchase order', {
        user:        req.user.id,
        supplier:    req.data.supplierId,
        totalAmount: req.data.totalAmount
      });

      if (req.data.totalAmount > 1_000_000) {
        logger.warn('Very large purchase order', {
          amount:   req.data.totalAmount,
          currency: req.data.currency
        });
      }
    });

    this.on('error', (err, req) => {
      const logger = logging.createLogger({ layer: 'purchase-order-service' });
      logger.error('Unhandled error in PurchaseOrderService', {
        error:   err.message,
        stack:   err.stack,
        user:    req.user?.id,
        path:    req.path
      });
    });

    await super.init();
  }
};

Log levels

Level Method When to use
DEBUG logger.debug() Verbose diagnostic — disabled in production
INFO logger.info() Normal operations — request received, entity created
WARNING logger.warn() Unexpected but recoverable — large transaction, slow query
ERROR logger.error() Caught errors that were handled — validation failure
FATAL logger.fatal() Unrecoverable errors — service cannot start

Set the minimum level via env var:

# In manifest.yml
env:
  SAP_LOG_LEVEL: warn    # only warn, error, fatal in production

Correlation IDs

Every HTTP request that goes through the logging.middleware() gets a correlation ID — either from the X-CorrelationID header (if the caller is another BTP service) or auto-generated. The ID is injected into every log line from that request, so you can trace a single user action across multiple log entries:

{
  "level": "INFO",
  "msg": "Creating purchase order",
  "correlationId": "abc-123-def",
  "layer": "purchase-order-service",
  "user": "P0012345",
  "totalAmount": 45000
}

In Kibana, filter correlationId: "abc-123-def" to see every log from that one request.

Searching in Kibana

Navigate to: BTP Cockpit → Services → Application Logging → Open Dashboard (Kibana)

Useful Kibana queries:

# All errors in the last hour
level: ERROR AND @timestamp:[now-1h TO now]

# Specific user's actions
user: "P0012345"

# Slow requests (custom field you logged)
durationMs: [500 TO *]

# By correlation ID
correlationId: "abc-123-def"

Setting up log-based alerts

In Kibana create a Watcher (Elasticsearch alerting):
1. Go to Stack Management → Watcher → Create Threshold Alert
2. Index: cap-app-logs-*
3. Condition: COUNT(level:ERROR) > 10 within 5 minutes
4. Action: send email / call webhook

Or use SAP Alert Notification Service (Episode 60) to route alerts raised from your CAP error handlers.

Common mistakes

Mistake Fix
console.log in production Use @sap/logging — console.log is not structured
Not attaching logging.middleware() Correlation IDs will not be populated
Logging sensitive data (passwords, tokens) Scrub PII before logging — GDPR applies
DEBUG level in production Set SAP_LOG_LEVEL=warn in production manifest
Logging inside a tight loop Log at entry/exit points, not per-iteration

Checkpoint ✓

You can bind SAP Application Logging Service, configure @sap/logging middleware, emit structured log entries with correlation IDs from CAP handlers, and query logs in Kibana by level, user, or correlation ID. You know how to set an appropriate log level for production.

Sign in for progress tracking & Q&A →