Skip to main content

Activity Log

Most create, update, and delete operations are recorded, and request-driven writes capture the HTTP request context (path, user agent, IP) that triggered them. Coverage is not universal. The generic inline quick-edit path does not log name, description, or metadata edits; it is used by the simpler entities (Tag, Category, Query, Note Type, Series, Resource Category, Template Partial, group relations, and group relation types) and also by the inline quick-edits on Notes, Groups, and Resources (though the full create and update paths for Notes, Groups, and Resources still log normally); plugin and background-worker writes log without request context; the hash and thumbnail workers log at batch granularity or not at all; and some bulk operations record a single aggregate entry. Log entries are written synchronously but with fire-and-forget error handling -- errors during log writes are printed to stdout but never propagate to break the original operation.

Activity log showing recent entity changes

Log Entry Properties

PropertyTypeDescription
levelstringinfo, warning, or error
actionstringcreate, update, delete, system, progress, plugin, reset, or error
entityTypestringEntity kind: resource, note, group, etc.
entityIduintID of the affected entity (nullable)
entityNamestringName of the entity at the time of the action
messagestringHuman-readable description
detailsJSONAdditional context as a JSON object
requestPathstringHTTP path that triggered the action
userAgentstringClient user agent
ipAddressstringClient IP address

Log Levels

LevelUsage
infoNormal operations -- entity creation, updates, deletions
warningNon-critical issues that may need attention
errorFailed operations or system errors

Log Actions

ActionDescription
createA new entity was created
updateAn existing entity was modified
deleteAn entity was deleted
systemSystem-level events (startup, migration, configuration)
progressLong-running operation progress updates
pluginPlugin hook or action execution events
resetA runtime setting was reset to its default
errorAn error condition (e.g., emitted by the background hash worker)

Viewing Logs

Administrator only

With -auth enabled, the activity log page and the /v1/log* endpoints are administrator-only. Editors, users and guests receive 403.

In the UI

Navigate to /logs to see a chronological list of all logged operations. Each entry shows the level, action, entity link, message, and timestamp, and links to /log?id=N for the full entry.

Entity detail pages also display recent log entries for that specific entity.

Filtering

Filter log entries by combining any of these parameters:

ParameterTypeDescription
levelstringFilter by level: info, warning, error
actionstringFilter by action: create, update, delete, system, progress, plugin, reset, error
entityTypestringFilter by entity kind
entityIduintFilter by specific entity ID
MessagestringSearch by log message
RequestPathstringFilter by HTTP request path
CreatedBeforetimestampEntries created before this time
CreatedAftertimestampEntries created after this time
SortBystring[]Sort field(s)

Configuration

Log Cleanup

Old log entries can be deleted automatically at startup:

FlagEnv VariableDefaultDescription
-cleanup-logs-daysCLEANUP_LOGS_DAYS0 (disabled)Delete entries older than N days on startup
./mahresources -cleanup-logs-days=90 ...

Set to 0 (default) to retain all log entries indefinitely.

API Endpoints

List Log Entries

GET /v1/logs
ParameterTypeDescription
levelstringFilter by log level
actionstringFilter by action type
entityTypestringFilter by entity kind
entityIduintFilter by entity ID
MessagestringSearch by log message
RequestPathstringFilter by HTTP request path
CreatedBeforetimestampEntries before this time
CreatedAftertimestampEntries after this time
SortBystring[]Sort field(s)
pageintPage number, 1-based (default 1). 50 entries per page.
curl "http://localhost:8181/v1/logs?level=error"
{
"logs": [
{
"id": 42,
"createdAt": "2025-03-01T10:30:00Z",
"level": "error",
"action": "system",
"entityType": "",
"entityName": "",
"message": "Failed to generate thumbnail",
"details": {"resourceId": 1234},
"requestPath": "/v1/resource/preview",
"userAgent": "Mozilla/5.0",
"ipAddress": "127.0.0.1"
}
],
"totalCount": 1,
"page": 1,
"perPage": 50
}

Get Single Log Entry

GET /v1/log
ParameterTypeDescription
iduintLog entry ID
curl "http://localhost:8181/v1/log?id=42"

Get Logs for a Specific Entity

GET /v1/logs/entity
ParameterTypeDescription
entityTypestringEntity kind (e.g., resource, note)
entityIduintEntity ID
pageintPage number, 1-based (default 1). 50 entries per page.
curl "http://localhost:8181/v1/logs/entity?entityType=resource&entityId=123"

Returns log entries for the specified entity, most recent first, 50 per page. The response carries totalCount, page and perPage.

Troubleshooting

Log table growing too large

Enable automatic cleanup at startup:

./mahresources -cleanup-logs-days=30 ...

Missing log entries

Log writes are fire-and-forget -- if the database insert fails (e.g., disk full, connection lost), the error is printed to stdout but the original operation still succeeds. Check stdout output for write failures.