Reference

Audit

Activity logging and audit trail in dnax Framework.

Every database operation is automatically logged as an activity in the _activities_ collection of each tenant's database. You can also query these logs programmatically via rest.audit.

Activity Structure

Each activity document follows the ActivityInput type:

{
  internal: boolean;
  trace: {
    id: string;
    comment?: string;
    tag?: string;
    version?: string;
  };
  request?: {
    ip?: string;
    user_agent?: string;
    headers?: Record<string, string>;
    method?: string;
    path?: string;
    query?: Record<string, any>;
  };
  meta: {
    environment?: string;
    hostname?: string;
    core_version?: string;
    platform?: string;
  };
  operation: {
    tenant: string;
    action: string;
    collection: string;
    status: "success" | "error";
    input: any;
    result: any;
    error: { message: string; code: string } | null;
    duration: number;
    transaction: boolean;
    token?: { value: string | null; decoded: Record<string, unknown> | null };
  };
  ts: Date;
}

Top-Level Fields

FieldTypeDescription
internalbooleantrue when triggered from server-side code, false for external API calls
trace.idstringUnique identifier to correlate related activities across a request
trace.commentstringOptional comment for the trace
trace.tagstringOptional tag for filtering traces
trace.versionstringOptional version identifier

Request

FieldTypeDescription
request.ipstringClient IP address
request.user_agentstringUser-Agent header
request.headersobjectRequest headers
request.methodstringHTTP method
request.pathstringRequest path
request.queryobjectQuery parameters

Meta

FieldTypeDescription
environmentstringEnvironment name (e.g. production, development)
hostnamestringServer hostname
core_versionstringdnax core version
platformstringOS platform

Operation

FieldTypeDescription
tenantstringTenant ID
actionstringThe operation action (see table below)
collectionstringCollection or service name
status"success" | "error"Whether the operation succeeded or failed
inputanyInput data sent to the operation
resultanyResult returned by the operation
errorobject | nullError details when status is error
durationnumberExecution time in milliseconds
transactionbooleanWhether the operation was part of a transaction
tokenobject | undefinedJWT token used for the request

Recorded Actions

Every CRUD and utility operation is logged automatically with the following action values:

ActionDescription
insertOneInsert a single document
insertManyInsert multiple documents
updateOneUpdate a single document
updateManyUpdate multiple documents
deleteOneDelete a single document
deleteManyDelete multiple documents
findOneAndUpdateFind and update a document
findFind documents
findOneFind a single document
aggregateRun an aggregation pipeline
bulkWriteExecute bulk write operations
bulkUpdateExecute bulk update operations
countDocumentsCount documents
dropCollectionDrop a collection
dropIndexDrop an index
dropIndexesDrop all indexes
loginUser login
logoutUser logout
runServiceService action execution

Querying Activities

getActivities

Retrieve activity logs using MongoDB aggregation pipeline syntax:

const activities = await rest.audit.getActivities({
  $match: { "operation.collection": "users" },
  $sort: { ts: -1 },
  $limit: 50,
});
ParameterTypeDefaultDescription
optsobject{ $match: {}, $limit: 100 }Aggregation pipeline parameters

Returns: MongoDB aggregation cursor of activity documents

Examples

Get recent errors:

const errors = await rest.audit.getActivities({
  $match: { "operation.status": "error" },
  $sort: { ts: -1 },
  $limit: 20,
});

Filter by tenant, action and date range:

const logs = await rest.audit.getActivities({
  $match: {
    "operation.tenant": "v1",
    "operation.action": "insertOne",
    ts: { $gte: new Date("2025-01-01") },
  },
  $sort: { ts: -1 },
});

Get activities for a specific trace:

const trace = await rest.audit.getActivities({
  $match: { "trace.id": "550e8400-e29b-41d4-a716-446655440000" },
});

Count operations by type:

const stats = await rest.audit.getActivities({
  $match: { "operation.tenant": "v1" },
  $group: {
    _id: "$operation.action",
    count: { $sum: 1 },
    avgDuration: { $avg: "$operation.duration" },
  },
});

startTrace

Set a shared trace for all subsequent operations in the current async context. Useful for grouping activities under a common identifier.

// Auto-generated trace ID
rest.startTrace();

// Custom trace ID
rest.startTrace('my-custom-trace');

// With extra metadata
rest.startTrace('import-2024-001', {
  comment: 'Monthly data import',
  tag: 'import',
  version: '1.2',
});
ParameterTypeDescription
traceIdstringOptional custom trace ID (auto-generated if omitted)
extra.commentstringOptional comment for the trace
extra.tagstringOptional tag for filtering
extra.versionstringOptional version identifier

unsetTrace

Remove the current trace from the context. Subsequent operations will each get their own random trace.id.

rest.startTrace('batch-job');
// ... operations here share trace.id = 'batch-job'
rest.unsetTrace();
// ... operations here each get a unique trace.id

addActivities

Insert custom activity entries. Used internally but also available for manual logging:

await rest.audit.addActivities([{
  internal: false,
  trace: {
    id: crypto.randomUUID(),
    comment: "Manual import",
    tag: "bulk",
    version: "2.1",
  },
  request: {
    ip: "192.168.1.42",
    user_agent: "Mozilla/5.0 ...",
    method: "POST",
    path: "/api/v1/users/insertOne",
  },
  meta: {
    environment: "production",
    hostname: "web-01",
    core_version: "1.0.0",
    platform: "linux",
  },
  operation: {
    tenant: "v1",
    action: "insertOne",
    collection: "users",
    status: "success",
    input: { name: "John" },
    result: { _id: "...", name: "John" },
    error: null,
    duration: 12,
    transaction: false,
  },
  ts: new Date(),
}]);

Storage

Activities are stored in the _activities_ collection of each tenant's database. This collection is created automatically on first write and does not require any schema configuration.

See also

Copyright © 2026