Include more context in Event Rules #9130

Open
opened 2025-12-29 20:46:03 +01:00 by adam · 8 comments
Owner

Originally created by @llamafilm on GitHub (Jan 23, 2024).

NetBox version

v3.7.0

Feature type

Change to existing functionality

Proposed functionality

When triggering a Python script using Event Rule, I'd like to have access to more context, just like Webhooks have. Currently the script only gets the data object. Webhooks also have:

  • event
  • username
  • model
  • snapshots

Use case

I want to log the username to have an audit trail. I also want to log whether the script was run manually or by an event rule.
I want to use the snapshot data to build more complex conditions into the script. For example, the event rule triggers on every device update, and the script updates my monitoring system. But I only want it to run if certain key fields were changed, like the name or status. Because other fields like airflow are irrelevant for monitoring.

Database changes

No response

External dependencies

No response

Originally created by @llamafilm on GitHub (Jan 23, 2024). ### NetBox version v3.7.0 ### Feature type Change to existing functionality ### Proposed functionality When triggering a Python script using Event Rule, I'd like to have access to more context, just like Webhooks have. Currently the script only gets the `data` object. Webhooks also have: - event - username - model - snapshots ### Use case I want to log the `username` to have an audit trail. I also want to log whether the script was run manually or by an event rule. I want to use the `snapshot` data to build more complex conditions into the script. For example, the event rule triggers on every device update, and the script updates my monitoring system. But I only want it to run if certain key fields were changed, like the name or status. Because other fields like airflow are irrelevant for monitoring. ### Database changes _No response_ ### External dependencies _No response_
adam added the type: featurestatus: blockednetboxtopic: event rules labels 2025-12-29 20:46:04 +01:00
Author
Owner

@renatoalmeidaoliveira commented on GitHub (Jan 23, 2024):

I think its related to #14884

@renatoalmeidaoliveira commented on GitHub (Jan 23, 2024): I think its related to #14884
Author
Owner

@llamafilm commented on GitHub (Jan 23, 2024):

Yep, essentially the same request. Since you beat me to it, do you want to incorporate details from this request into yours and then close this one?

@llamafilm commented on GitHub (Jan 23, 2024): Yep, essentially the same request. Since you beat me to it, do you want to incorporate details from this request into yours and then close this one?
Author
Owner

@jeremystretch commented on GitHub (Feb 14, 2024):

This needs to remain a separate FR. #14884 specifically addresses passing an event rule's action data to a script, whereas this FR deals more generally with context.

I'm going to mark this as blocked by #14884; once that has been resolved we can look at opening it up to include additional context.

@jeremystretch commented on GitHub (Feb 14, 2024): This needs to remain a separate FR. #14884 specifically addresses passing an event rule's action data to a script, whereas this FR deals more generally with context. I'm going to mark this as blocked by #14884; once that has been resolved we can look at opening it up to include additional context.
Author
Owner

@SaschaSchwarzK commented on GitHub (Jun 20, 2024):

It would be cool is the pre/post change data would be available in the conditions. Or a diff object that contains the changes. I currently face a problem that I get thousands of jobs as the condition in the event rules cannot look it down to a specific field that changed the value. So every time the item is changed, no matter what changed, the script is run.

@SaschaSchwarzK commented on GitHub (Jun 20, 2024): It would be cool is the pre/post change data would be available in the conditions. Or a diff object that contains the changes. I currently face a problem that I get thousands of jobs as the condition in the event rules cannot look it down to a specific field that changed the value. So every time the item is changed, no matter what changed, the script is run.
Author
Owner

@jeremystretch commented on GitHub (Jul 14, 2025):

Per #19043 we should consider what other request data to include as context.

@jeremystretch commented on GitHub (Jul 14, 2025): Per #19043 we should consider what other request data to include as context.
Author
Owner

@aj2s commented on GitHub (Oct 21, 2025):

#14884 was just closed as not planned. I could really use this feature for logging whose change triggered an event rule, so hopefully this one gets accepted

@aj2s commented on GitHub (Oct 21, 2025): #14884 was just closed as not planned. I could really use this feature for logging whose change triggered an event rule, so hopefully this one gets accepted
Author
Owner

@pheus commented on GitHub (Oct 23, 2025):

Hi! I’d like to pick this up.

I reviewed the FR and conversation. The goal is to give Script actions the same core event context that webhooks already receive. Today, event‑triggered scripts run in a worker with no request object; the username is available as a string, but request_id isn’t currently threaded through event processing, which makes correlation hard.

Proposal (core fields only)

Expose the following core event context to scripts executed by Event Rules:

  • event — event type (e.g. object_created, object_updated, object_deleted)
  • username — actor’s username (string; may be null)
  • model<app_label>.<model> for the changed object
  • request_id — request correlation ID (may be null)
  • snapshots — pre/post change state (optional; mirrors webhook behavior)

Scope note: We can consider additional request metadata later. This proposal stays focused on the core fields above to move this forward.

Payload shape — three options

Do you have a preference? I can implement any of these.

Option A — namespaced dict (no underscores inside the dict)

# One discoverable key; easy to extend without top-level sprawl.
event_data["event_info"] = {
    "event":      event_type,
    "username":   username,     # may be None
    "model":      model_label,  # e.g. "dcim.device"
    "request_id": request_id,   # may be None
    "snapshots":  snapshots,    # optional dict with pre/post
}

Option B — underscore‑prefixed top‑level keys (flatter to consume)

# Flat structure; slightly more ergonomic but uses more top-level names.
event_data.update({
    "_event":      event_type,
    "_username":   username,     # may be None
    "_model":      model_label,  # e.g. "dcim.device"
    "_request_id": request_id,   # may be None
    "_snapshots":  snapshots,    # optional dict with pre/post
})

Option C — underscore‑prefixed, namespaced dict (hybrid)

# Keeps context grouped under a single reserved key and signals "meta" via underscore.
event_data["_event_info"] = {
    "event":      event_type,
    "username":   username,     # may be None
    "model":      model_label,  # e.g. "dcim.device"
    "request_id": request_id,   # may be None
    "snapshots":  snapshots,    # optional dict with pre/post
}

Trade‑offs:

  • A (dict): minimal collision risk, clean names; scripts read data["event_info"]["event"].
  • B (flat): simplest consumption (data["_event"]), but grows the top‑level namespace.
  • C (underscored dict): combines A’s grouping with a reserved underscore key to clearly mark the payload as system/meta data (data["_event_info"]["event"]), while avoiding top‑level sprawl.

Implementation notes (minimal & backward‑compatible)

  • Thread request_id from the event queue into rule processing:
    • process_event_queue(...) → pass request_id to process_event_rules(...).
    • Update process_event_rules(..., request_id=None).
  • In the SCRIPT branch of process_event_rules(...):
    • Merge existing object data and action_data as today.
    • Attach the chosen context shape (Option A, B, or C).
  • Continue not passing a full request into Script jobs (unchanged behavior).
  • Add a unit test that patches ScriptJob.enqueue and asserts the enriched payload while preserving original object fields.

If there’s no strong preference, I’m inclined to proceed with Option C (_event_info dict) as a good balance between ergonomics and future extensibility. Happy to adjust based on maintainer guidance.

@pheus commented on GitHub (Oct 23, 2025): Hi! I’d like to pick this up. I reviewed the FR and conversation. The goal is to give **Script** actions the same core event context that webhooks already receive. Today, event‑triggered scripts run in a worker with **no request object**; the **username** is available as a string, but **`request_id`** isn’t currently threaded through event processing, which makes correlation hard. ## Proposal (core fields only) Expose the following **core event context** to scripts executed by Event Rules: - `event` — event type (e.g. `object_created`, `object_updated`, `object_deleted`) - `username` — actor’s username (string; may be `null`) - `model` — `<app_label>.<model>` for the changed object - `request_id` — request correlation ID (may be `null`) - `snapshots` — pre/post change state (optional; mirrors webhook behavior) > Scope note: We can consider additional request metadata later. This proposal stays focused on the **core** fields above to move this forward. ## Payload shape — three options Do you have a preference? I can implement any of these. ### Option A — namespaced dict (no underscores inside the dict) ```python # One discoverable key; easy to extend without top-level sprawl. event_data["event_info"] = { "event": event_type, "username": username, # may be None "model": model_label, # e.g. "dcim.device" "request_id": request_id, # may be None "snapshots": snapshots, # optional dict with pre/post } ``` ### Option B — underscore‑prefixed top‑level keys (flatter to consume) ```python # Flat structure; slightly more ergonomic but uses more top-level names. event_data.update({ "_event": event_type, "_username": username, # may be None "_model": model_label, # e.g. "dcim.device" "_request_id": request_id, # may be None "_snapshots": snapshots, # optional dict with pre/post }) ``` ### Option C — underscore‑prefixed, namespaced dict (hybrid) ```python # Keeps context grouped under a single reserved key and signals "meta" via underscore. event_data["_event_info"] = { "event": event_type, "username": username, # may be None "model": model_label, # e.g. "dcim.device" "request_id": request_id, # may be None "snapshots": snapshots, # optional dict with pre/post } ``` **Trade‑offs:** - **A (dict):** minimal collision risk, clean names; scripts read `data["event_info"]["event"]`. - **B (flat):** simplest consumption (`data["_event"]`), but grows the top‑level namespace. - **C (underscored dict):** combines A’s grouping with a reserved underscore key to clearly mark the payload as system/meta data (`data["_event_info"]["event"]`), while avoiding top‑level sprawl. ## Implementation notes (minimal & backward‑compatible) - Thread `request_id` from the event queue into rule processing: - `process_event_queue(...)` → pass `request_id` to `process_event_rules(...)`. - Update `process_event_rules(..., request_id=None)`. - In the `SCRIPT` branch of `process_event_rules(...)`: - Merge existing object `data` and `action_data` as today. - Attach the chosen context shape (Option A, B, or C). - Continue **not** passing a full `request` into Script jobs (unchanged behavior). - Add a unit test that patches `ScriptJob.enqueue` and asserts the enriched payload while preserving original object fields. If there’s no strong preference, I’m inclined to proceed with **Option C** (`_event_info` dict) as a good balance between ergonomics and future extensibility. Happy to adjust based on maintainer guidance.
Author
Owner

@llamafilm commented on GitHub (Dec 7, 2025):

Thanks for picking this up! I like Option C, making it clear that these fields are not part of the model.
Nit: I'd prefer calling it _event instead of _event_info just to make scripts less verbose.

@llamafilm commented on GitHub (Dec 7, 2025): Thanks for picking this up! I like Option C, making it clear that these fields are not part of the model. Nit: I'd prefer calling it `_event` instead of `_event_info` just to make scripts less verbose.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#9130