Back to Kibana

@kbn/core-user-activity-server

src/core/packages/user-activity/server/README.md

9.4.012.8 KB
Original Source

@kbn/core-user-activity-server

This package contains the public types for Core's server-side user activity service.


Technical Reference

Usage

Use trackUserAction to record user actions:

ts
core.userActivity.trackUserAction({
  event: {
    action: 'create_alerting_rule',
    type: 'creation',
    start: new Date().toISOString(),
    end: new Date().toISOString(),
    duration: 250000000, // 250ms in ns
  },
  object: { id: 'production-rule', name: 'My rule', type: 'rule', tags: ['production'] },
});

You can optionally provide a custom message and metadata:

ts
core.userActivity.trackUserAction({
  message: 'User snoozed an alerting rule',
  event: { action: 'snooze_alerting_rule', type: 'change' },
  object: { id: 'rule-456', name: 'CPU usage threshold', type: 'rule', tags: ['production'] },
  metadata: {
    ui_surface: 'rules_table',
    interaction_id: 'snooze_rule_flyout',
  },
});

Registering new actions

Every action must be registered in userActivityActions (src/user_activity_actions.ts). Each entry requires a description, an ownerTeam (GitHub team handle), and a versionAddedAt (Stack version when the action was introduced).

ts
export const userActivityActions = {
  // ... existing actions ...
  create_cases_case: {
    description: 'Create a case',
    ownerTeam: '@elastic/kibana-cases',
    groupName: 'Cases',
    versionAddedAt: '9.3',
  },
} as const satisfies Record<string, UserActivityActionDefinition>;

When an action is removed, move it from userActivityActions to removedUserActivityActions and add versionRemovedAt.

After adding an action, regenerate the docs snippet by running node scripts/generate user-activity-actions-docs. This updates the action list shown in the docs.

Configuration

Configure the service in kibana.yml:

yaml
user_activity:
  enabled: true
  appenders:
    # If you don't provide any appender, this is the default we'll use if enabled 
    console:
      type: console
      layout:
        type: json
    # Example: write to file
    file:
      type: file
      fileName: /var/log/kibana/user_activity.log
      layout:
        type: json
  filters:
    - policy: keep
      actions: [create_security_rule]

The appenders option uses the same schema as the core logging service.

Filters

You can optionally configure user_activity.filters to control which event.action values are logged.

For an activity to be logged, its event.action must pass all configured filters:

  • policy: keep logs only the actions listed in actions
  • policy: drop logs all actions except those listed in actions

If filters is not configured (or empty), all actions are eligible to be logged.

Injected Context

The following context is automatically added to every log entry by Kibana's HTTP middleware:

FieldDescription
user.idUser's profile UID
user.nameUsername
user.emailEmail address
user.rolesArray of roles
client.ipIP address
client.addressIP address (OTel compliance)
session.idSession ID
kibana.space.idCurrent space ID
http.request.referrerReferrer

Log schema

Here's the current schema reference: docs/reference/user-activity.md.

Some of the fields in the schema come from:

  • trackUserAction() params (for example message, event.*, object.*, metadata.*)
  • Injected context (for example user.*, session.*, client.*, kibana.space.id, and http.request.referrer)
  • Fields automatically added by the logging system / JSON layout (for example @timestamp)

Important

If you need to extend this schema, reach out to the Core team (@elastic/kibana-core).


Instrumentation Guidelines

The sections below are aimed at teams deciding what to instrument and how to name it. They complement the technical API reference above and apply to everyone contributing actions to userActivityActions.

1. What to Instrument

The user activity log captures deliberate user decisions, not system behavior or passive navigation. Every event must answer yes to this question: If a user saw this entry in their own activity log, would they recognize it as something they consciously did? Check if an action already exist before instrumenting a new one.

Instrument these

CategoryExamples
Intentional create / update / delete actionsCreating a rule, deleting a dashboard, editing a connector
State-changing configurationUpdating alert severity, changing case status
Lifecycle transitionsEscalating a case, closing an alert, snoozing a rule
High-intent navigationRefresh a dashboard, launching the anomaly explorer
AI and assistant interactionsSubmitting a prompt, adding a knowledge base entry
Bulk operationsBulk-deleting alerts, bulk-enabling rules
Integration triggersPushing a case to Jira, running a connector action

Do not instrument these

Anti-patternReason
Passive page viewsNo actionable signal; use product analytics for funnel analysis
Polling and auto-refreshSystem-initiated, not user-initiated
Internal framework operationsNot meaningful to a human reading the log
Autosave / draft state savesNot a user decision
Read-only list fetches on page loadNo user intent
Redundant sub-eventsIf the parent event covers the action, don't also emit the child
System-generated actionsrule_auto_recovered, session_expired

2. Event Naming Format

Base Structure: {context}_{noun}_{verb}

PartRoleConstraints
contextKibana feature areaCanonical plugin name, no invented abbreviations
nounThe object type acted onSingular, lowercase, matches the product name for the entity
verbThe action the user tookMust come from the approved verb list (Section 3)

All lowercase, snake_case. No camelCase, no hyphens.

For bulk variants, append _bulk to the noun: cases_comment_bulk_delete.

Examples

Event nameContextNounVerb
alerting_rule_createalertingrulecreate
cases_comment_deletecasescommentdelete
security_rule_enablesecurityruleenable
cases_case_pushcasescasepush
ai_assistant_prompt_submitai_assistantpromptsubmit
fleet_integration_installfleetintegrationinstall

3. Approved Verb List

Use only verbs from this list. If a new verb is genuinely needed, propose it with the Kibana Core team.

VerbWhen to useDo not use instead
createUser creates a new persisted objectadd, new, make
updateUser modifies an existing objectedit, change, modify, save
deleteUser permanently removes an objectremove, destroy
viewHigh-intent governed read (use sparingly)open, read, access
refreshHigh-intent governed refresh (use sparingly)load, reload, reopen
enableUser activates an inactive objectactivate, turn_on
disableUser deactivates an active objectdeactivate, turn_off
stopUser stops a running processpause, halt
openUser transitions a workflow object to activereopen, resume
closeUser closes or resolves a workflow objectresolve, finish
assignUser assigns an object to a personlink_user, add_assignee
unassignUser removes an assignmentremove_assignee
pushUser sends an object to an external systemexport_to, sync, send
exportUser exports data to a file or downloaddownload, extract
importUser imports data from a fileupload
installUser installs a package or integrationadd_integration, deploy
uninstallUser removes a package or integrationremove_integration
muteUser silences notificationssilence, suppress
unmuteUser re-enables notificationsunsuppress
snoozeUser suppresses for a time windowpause_notifications, defer
unsnoozeUser cancels a snooze early
acknowledgeUser acknowledges an alert or workflow itemconfirm, accept
escalateUser escalates severity or routingpromote, raise
tagUser applies a tagadd_tag, label
untagUser removes a tagremove_tag
shareUser shares an object to a spaceadd_to_space, publish
unshareUser removes sharingremove_from_space
cloneUser duplicates an objectcopy, duplicate
submitUser submits a prompt or form for processingsend, run (for AI prompts)
runUser manually triggers an on-demand executionexecute, fire
scheduleUser schedules a future or recurring actionautomate
log_inUser logs inauthenticate,logged in
log_outUser logs outunauthenticate,logged out

4. Language for Human-Readable Fields

The message field

Format: {Subject} {past-tense verb} {object} [{qualifier}].

Rules:

  • Write in third person using "User" as the subject: User created a rule. not You created a rule.
  • Use past tense for completed actions: User deleted the dashboard.
  • Use present progressive only for in-flight operations logged before the outcome is known: User is creating a connector.
  • Include the object name (quoted) and ID when available: User enabled rule "High CPU Alert" (id: abc123).
  • Use the product name for objects, not internal type keys: User created a detection rule. not User created a siem.queryRule.
  • Use active voice, sentence case, end with a period.

Tense matches outcome

event.outcomeTenseExample
unknownPresent progressiveUser is creating a connector.
successSimple pastUser created a connector.
failureSimple past with reasonUser failed to create a connector. Reason: Not authorized.

Qualifier patterns

  • Object name and ID: "My Rule" (id: abc123)
  • Bulk count: User deleted 14 alerts.
  • Target system: User pushed case "Login Failure Spike" to ServiceNow (id: case-xyz).
  • Failure reason: Reason: Rule contains invalid query syntax.

Other fields

FieldRule
event.actionSnake_case action key only, never a sentence
Object name in qualifiersAlways quoted: "My Dashboard"
Error reasonCapital first letter, no period: Reason: Not authorized to delete this object
Outcome labels in UITitle case, no verb: Rule Created, Case Escalated

5. Kibana-Specific Examples

Alerting

Event actionOutcomemessage
alerting_rule_createunknownUser is creating a rule.
alerting_rule_createsuccessUser created rule "High CPU Alert" (id: 1a2b3c).
alerting_rule_createfailureUser failed to create a rule. Reason: Not authorized.
alerting_rule_snoozeunknownUser is snoozing rule "High CPU Alert" (id: 1a2b3c) for 8 hours.
alerting_rule_runsuccessUser ran rule "High CPU Alert" (id: 1a2b3c) on demand.

Cases

Event actionOutcomemessage
cases_case_createsuccessUser created case "Login Failure Spike" (id: case-001).
cases_status_updatesuccessUser updated status of case "Login Failure Spike" (id: case-001) to "in-progress".
cases_case_pushunknownUser is pushing case "Login Failure Spike" (id: case-001) to ServiceNow.
cases_case_closesuccessUser closed case "Login Failure Spike" (id: case-001).

Security / Detection

Event actionOutcomemessage
security_rule_createsuccessUser created detection rule "Potential Credential Dumping" (id: rule-sec-001).
security_rule_enableunknownUser is enabling detection rule "Potential Credential Dumping" (id: rule-sec-001).
security_alert_acknowledgesuccessUser acknowledged alert (id: alert-sec-999) for rule "Potential Credential Dumping".

6. Pre-Ship Checklist

  • The action is user-initiated, not system-triggered or auto-fired
  • The action changes state or represents a high-intent interaction, not a passive read
  • Event name follows {context}_{noun}_{verb} in snake_case
  • Verb is from the approved list
  • Context matches the canonical Kibana plugin name
  • message uses correct tense relative to event.outcome
  • message includes the object name (quoted) and ID where available
  • message uses "User" as the subject in active voice
  • No duplicate sub-event is emitted for the same user action
  • Bulk operations, append _bulk to the noun