Skip to content

Logging

New: V5.4.0

What is logged

Cavaliba records events: who did what, to which object, and whether it worked.

Field Example
action instance.update, user.impersonate, load.run, mail.send
outcome success, failure, denied
reason not_found, permission_denied, readonly_key, invalid_form
target site:ANCON, task:<uuid>
actor the user, or API:<key> for an API key; impersonated user shown separately
channel web, api, cli, celery, system
client IP, request id, count, duration, message, extra

Events are stored in the database (Logs page, API) and can also be sent to stdout or a file.

Besides events, Cavaliba produces two other kinds of log lines, never stored in the database:

  • debug: detailed traces for troubleshooting, off by default
  • system: Django, Celery and library messages (errors, tracebacks, startup)

Logs page

Sidebar Logs. Requires p_log_view.

  • Filters: minimum level (INFO by default), outcome, channel, domain, action (prefix, e.g. instance.), actor, target (site:ANCON, or site: for a whole schema), date range, free text (message, target, reason).
  • Click a row to open the event detail. From there, events of this request and events on this target show related events.
  • Export: the current filters as CSV or JSON (up to 100,000 events).
  • Purge (p_log_admin): apply retention now, or delete all events.

Examples:

  • Who changed site ANCON? Target site:ANCON, action instance..
  • Refused accesses this week? Outcome denied, From <date>.
  • What did an API key do? Actor API:<key>.

The same searches are available from the API (/api/log/) and from cavctl log.

Sending logs out

Set in the .env file (see System Configuration, Logging). Defaults: events go to the database (all levels) and to stdout as text (INFO and above), debug goes nowhere, system messages go to stdout from INFO.

Docker, with a log collector (Filebeat, Fluent Bit, Vector) reading the container output:

CAVALIBA_LOG_STDOUT=json

Every line Cavaliba writes is then one JSON object using the Elastic Common Schema field names (event.action, event.outcome, user.name, client.ip, …). The labels.stream field tells event, debug and system lines apart.

The container output still has a few plain text lines: Gunicorn’s own access and error lines, and Celery’s startup banner. Configure the collector to keep non-JSON lines as plain messages, and drop Gunicorn’s access log (remove --access-logfile '-' from GUNICORN_CMD_ARGS): nginx already logs every request.

Less noise from Django and Celery:

CAVALIBA_LOG_SYSTEM_LEVEL=WARNING

Events to a file, for a log shipper:

CAVALIBA_LOG_FILE=/var/log/cavaliba/event.json
CAVALIBA_LOG_EVENT_TO=file

Rotate the file with logrotate; Cavaliba reopens it after rotation.

Troubleshooting authentication, debug traces of one module in their own file:

CAVALIBA_LOG_DEBUG_TO=file
CAVALIBA_LOG_DEBUG_FILE=/var/log/cavaliba/debug.log
CAVALIBA_LOG_DEBUG_MODULES=app_data.aaa

CAVALIBA_LOG_EVENT_LEVEL only filters what is sent out: every event is still stored in the database.

Retention

Set in the Configuration page (home):

  • LOG_KEEP_DAYS_DEBUG / INFO / WARNING / ERROR / CRITICAL: days kept per level
  • LOG_MAX_ENTRIES: maximum number of stored events
  • LOG_EXCLUDED_IP: client IPs whose events are not stored (e.g. monitoring probes)

Retention is applied by the daily housekeeping, or on demand from the Logs page or Admin tools (Log retention purge).

Keep a few weeks in the database for the Logs page; for long-term storage, send events to a log collector.