Skip to content

Custom event tracking - #286

Open
marksmith wants to merge 4 commits into
mainfrom
custom-event-tracking
Open

Custom event tracking#286
marksmith wants to merge 4 commits into
mainfrom
custom-event-tracking

Conversation

@marksmith

@marksmith marksmith commented May 27, 2026

Copy link
Copy Markdown
Collaborator

This change adds support for tracking named user events, sent from application code using Aikido::Zen.track_user_event. User events include the event name, user ID, and IP address.

This change extends and should be reviewed after #285.

Summary by Aikido

Security Issues: 0 🔍 Quality Issues: 4 Resolved Issues: 0

🚀 New Features

  • Added user event tracking end-to-end with API and agent integration

⚡ Enhancements

  • Handled empty API responses and adjusted event send endpoint

More info

@marksmith
marksmith requested review from hansott and tomaisthorpe May 27, 2026 15:06
Comment thread lib/aikido/zen/agent.rb Outdated
@marksmith
marksmith force-pushed the custom-event-tracking branch 2 times, most recently from 17f3482 to 23ffc5f Compare May 28, 2026 08:21
@codecov

codecov Bot commented May 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.66667% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
lib/aikido/zen/api_client.rb 56.25% 6 Missing and 1 partial ⚠️
lib/aikido/zen/agent.rb 50.00% 1 Missing and 2 partials ⚠️
lib/aikido/zen.rb 71.42% 0 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

@marksmith
marksmith force-pushed the custom-event-tracking branch from 23ffc5f to 29ebef3 Compare May 29, 2026 11:22
@marksmith
marksmith force-pushed the custom-event-tracking branch 4 times, most recently from 925d1bd to 03c8326 Compare June 19, 2026 15:42
@marksmith
marksmith requested a review from timokoessler June 19, 2026 15:57
Comment thread docs/track.md
Comment thread lib/aikido/zen.rb

@config.logger.debug("Reporting #{event_type.upcase} event")

req = Net::HTTP::Post.new("/api/runtime/events", default_headers)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These events can only be sent to zen.aikido.dev, the old runtime API does not support this.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's quite an important point for the other agents too. If the agent is unable to connect to zen.aikido.dev, we need to make it really clear that the user events aren't going to work. I wonder if we need a log here, @timokoessler?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, makes sense. Maybe log if user calls the track() API for the first time? cc. @hansott.

def send_user_event(event)
event_type = "user_event"

if @rate_limiter.throttle?(event_type)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As these events are not send to Aikido Core, maybe not re-use the same rate limiter? (I think this is the case)

@marksmith
marksmith force-pushed the custom-event-tracking branch 3 times, most recently from 03c8326 to a13654a Compare June 26, 2026 12:20
Comment thread lib/aikido/zen.rb
@marksmith
marksmith force-pushed the custom-event-tracking branch 2 times, most recently from 8bf6fbd to 306b86f Compare June 30, 2026 08:43
@marksmith
marksmith force-pushed the custom-event-tracking branch from c71014a to e32b408 Compare July 15, 2026 07:55
response = http.request(request)

case response
when Net::HTTPNoContent

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty when Net::HTTPNoContent branch is verbose; combine Net::HTTPNoContent with Net::HTTPSuccess in the same when clause or explicitly return nil to simplify the case handling.

Details

✨ AI Reasoning
​In the request method an explicit when branch for Net::HTTPNoContent is added with an empty body. This is more verbose than necessary: treating Net::HTTPNoContent together with Net::HTTPSuccess (and handling the empty-body case by returning nil) is a simpler, equally readable approach. Combining them would reduce the number of case arms and clarify intent.

🔧 How do I fix it?
Rewrite the snippet in the simpler, behavior-equivalent form: return a boolean expression directly instead of if cond return true else return false, avoid using lists when they are guaranteed to contain one element, etc.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

raise
end

def send_user_event(event)

@aikido-pr-checks aikido-pr-checks Bot Jul 15, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APIClient#send_user_event overlaps in name with APIClient#report but uses a different endpoint and behavior; clarify intent or rename to reflect the specialized behavior (e.g., post_user_event_to_realtime).

Suggested change
def send_user_event(event)
# Posts a user event to the realtime settings updates endpoint, using
# separate rate limiting from standard event reporting.
def send_user_event(event)
Details

✨ AI Reasoning
​APIClient#send_user_event was added to send user events but its behavior differs from APIClient#report (different rate-limiter key, different base_url). The method name closely resembles report, making the distinct responsibilities unclear without inspecting implementation.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

Comment thread lib/aikido/zen/agent.rb
end
end

# @param event [Aikido::Zen::Tracked]

@aikido-pr-checks aikido-pr-checks Bot Jul 15, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent#send_user_event purpose is unclear relative to Agent#report. Clarify how it differs (intent, lifecycle, and expected callers) and fix the incorrect/undefined doc type Aikido::Zen::Tracked.

Show fix
Suggested change
# @param event [Aikido::Zen::Tracked]
# Asynchronously sends user-triggered events to Aikido, skipping enqueue
# if reporting is disabled.
#
# @param event [Object] a user event payload.
Details

✨ AI Reasoning
​A method was added that enqueues and sends user events from the Agent layer. Its name send_user_event overlaps with the existing report method, and the doc annotation references Aikido::Zen::Tracked (not defined here). It's not obvious how send_user_event differs from report or when to use one vs the other without reading its implementation.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

Comment thread lib/aikido/zen/event.rb
end
end

class UserEvent

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Todo: This event needs to be updated to follow new spec: https://github.com/AikidoSec/zen-specs/blob/main/features/custom_event_tracking.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants