Logging and monitoring

Enterprise Studio writes structured, machine-parseable logs to standard output.

Log output destination

All logs are written to stdout.

  • Binary: redirect stdout to a file and use an external tool such as logrotate. Enterprise Studio does not rotate logs internally.

  • Docker: logs are available through docker logs and forwarded to the configured Docker logging driver.

  • Kubernetes: container stdout is collected by the kubelet and available through kubectl logs. Use a log aggregator such as Fluentd, Fluent Bit, or Promtail to ship logs to a centralized system (for example Loki, Elasticsearch, or Splunk).

Log format

Every JSON log entry contains the following top-level fields:

Field Description

time

ISO 8601 timestamp of the log event.

level

Log level: debug, info, warn, or error.

msg

Human-readable log message.

component

The internal subsystem that produced the entry (for example server, storageApi, config).

request_id

UUID generated per incoming HTTP request, useful for correlating log entries.

user

Object containing username, roles, and deployment of the authenticated user (present on request-scoped log entries).

error

Error details (present only when an error occurred).

Example JSON log entry:

{
  "time": "2025-06-10T14:32:01.456Z",
  "level": "INFO",
  "msg": "POST /api/shared-storage/v1/cypher 200 34ms",
  "component": "storageApi",
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "user": {
    "username": "[email protected]",
    "roles": ["editor"],
    "deployment": "production"
  }
}

Two output formats are available, controlled by the logs.format setting: json (default) produces structured JSON with one object per line; pretty produces colorized human-readable lines for local development. See Configuration → Logging for details.

At debug level, every Cypher® query and its parameters are logged, which significantly increases volume. Use info in production and switch to debug only for targeted troubleshooting.

Access logs

When assetStore.default.logs.requestLogs.enabled is true (the default), Enterprise Studio writes a structured log entry for every Storage API HTTP request.

Example access log entry:

{
  "time": "2025-06-10T14:35:12.789Z",
  "level": "INFO",
  "msg": "GET /api/shared-storage/v1/artifacts 200 12ms",
  "component": "storageApi",
  "request_id": "f7e6d5c4-b3a2-1098-fedc-ba9876543210",
  "protocol": "HTTP/1.1",
  "remote_ip": "10.0.0.5",
  "method": "GET",
  "uri": "/api/shared-storage/v1/artifacts",
  "status_code": 200,
  "latency": "12ms",
  "response_size": 4096,
  "user_agent": "Mozilla/5.0"
}

Compared to a standard log entry, access log entries add the protocol, remote_ip, method, uri, status_code, latency, response_size, and user_agent fields.

Since every request-scoped log entry includes the authenticated username, roles, and deployment, access logs provide an audit trail out of the box.

Health check endpoint

Enterprise Studio exposes a health check endpoint for use with load balancers and container orchestration platforms:

Method Path Response

GET

/health

200 OK with body OK.

This is a simple liveness check that confirms the HTTP server is running. It does not verify backend connectivity (for example to the storage database).

Storage API query profiling

The Storage API performs Cypher queries on the storage database. Enabling query profiling adds execution statistics to query logs, which can help diagnose slow operations.

To enable query profiling, set assetStore.default.queryProfiling.enabled to true. This setting is disabled by default. When enabled, Storage API data queries use the Cypher PROFILE keyword and the resulting metrics are added to log entries.

Query profiling logs are written at debug level. Set logs.level to debug to see them.

The following metrics are added to the profile_debug_stats object:

Metric Description

total_database_db_hits

Total database hits. See Cypher Manual → Database hits for more information.

records_returned

Number of records returned by the query.

documents_scanned

Database rows scanned for leaf operators in the query profile.

used_indexes

Indexes used by the query.

Example log entry with profiling enabled:

{
  "time": "2025-06-10T14:32:01.789Z",
  "level": "DEBUG",
  "msg": "Execute Cypher Query",
  "component": "storageApi",
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "profile_debug_stats": {
    "documents_scanned": "2",
    "records_returned": "1",
    "total_database_db_hits": "22",
    "used_indexes": [
      {"name": "used_index_1"},
      {"name": "used_index_2"}
    ]
  }
}

Redaction

Passwords and SSO client secrets are replaced with [REDACTED] in log output. Usernames, IP addresses, user agent strings, and Cypher query parameters (at debug level) are not redacted. To remove these from stored logs, mask them in your log pipeline before long-term storage.

Error responses

The Storage API returns error responses using the RFC 9457 problem details format. Each response contains a type (machine-readable identifier), title (human-readable summary), and optionally detail and errors (for batch failures).

{
  "type": "not-found",
  "title": "resource 'dashboard/abc-123' not found"
}

The type field distinguishes errors that share the same HTTP status code — for example not-found vs not-found-parent (both 404), or validation-error (422) vs json-syntax-error (400). These values are stable and can be used in alerting rules. The same type value appears in the corresponding structured log entry.