Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[alerting] add a toString() to context variables whose values are objects #82044

Closed
pmuellr opened this issue Oct 29, 2020 · 6 comments
Closed
Assignees
Labels
Feature:Alerting good first issue low hanging fruit Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams)

Comments

@pmuellr
Copy link
Member

pmuellr commented Oct 29, 2020

For context variables provided by an alert, to be used in action parameters, usually the values of the variables are strings or other primitive values. However, they can be objects as well. The metrics alert makes use of this for it's grouping (I believe).

When a customer uses these object-valued variables directly as a mustache "variable", mustache will render these values as the following, which isn't very useful.

[Object object]

It's possible to add a toString() method to these object values, which would then get invoked when the object is used as a "variable". So one could be added that returned eg JSON.stringify(this). It's unlikely to be the form a customer would want to use directly, but it is better than what currently happens, and should provide the info to the customer to refine the variable references while fine-tuning alert actions.

Alert executors can do this themselves, and I've proposed that before, but I'm wondering if we should just do this automagically in alerting. We could also add one on the top-level context, so you could use {{context}} to see the full context - again, mainly for diagnostic purposes, seems like it could be useful.

I suppose we'd "walk" the context provided by the alert, probably deep clone it (since we'll be modifying it), and then for every "object" in the graph, add the relevant toString() method to the object, if there's not already a toString property.

@pmuellr pmuellr added Feature:Alerting Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) labels Oct 29, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-alerting-services (Team:Alerting Services)

@mikecote mikecote added the good first issue low hanging fruit label Nov 3, 2020
@pmuellr
Copy link
Member Author

pmuellr commented Nov 3, 2020

This may be a DUP of issue #75601, haven't looked closely

@ChristopherShih
Copy link

Hello, I am new to contributing but would like to help. Would this problem be reasonable to start with? Any information on where I should start looking (files this logic is located) would be appreciated. Thanks in advance!

@pmuellr
Copy link
Member Author

pmuellr commented Nov 18, 2020

👋 @ChristopherShih

it might be reasonable! I'll let you decide.

The relevant code, is here:

const result = cloneDeepWith(actionParams, (value: unknown) => {
if (!isString(value)) return;
// when the list of variables we pass in here changes,
// the UI will need to be updated as well; see:
// x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.ts
const variables = {
alertId,
alertName,
spaceId,
tags,
alertInstanceId,
context,
state,
params: alertParams,
};
return Mustache.render(value, variables);
});
// The return type signature for `cloneDeep()` ends up taking the return
// type signature for the customizer, but rather than pollute the customizer
// with casts, seemed better to just do it in one place, here.
return (result as unknown) as AlertActionParams;
}

I think the trick is going to be to walk the variables object, recursively, and for any property that isn't a primitive, add a function to it, I think a toString() function, which would return the JSON.stringify()d version of that object. At the top-level, that's context, state and params. It may get a bit complicated with arrays, as arrays of primitives get rendered good enough by mustache already, but arrays of non-primiitve objects will look like [Object object], [Object object], etc. So we don't want to add the function to arrays, but do want to add it to non-primitive array elements.

The way you'd test this is to create an alert, add an action like a server log, trying using a variable like context directly in the message action parameter as {{context}}. Right now, that should render when the message is logged by the action, as [Object object]. Once we "fix" this, you would see { ... }, which would list all of the properties of the context, recursively.

I'm not sure why we have that variables variable set within the cloneDeepWith() call - it looks like it can probably be moved outside of the function, before cloneDeepWith() is invoked. Be worth a shot trying, I think it would make the function a little more readable.

@pmuellr
Copy link
Member Author

pmuellr commented Nov 24, 2020

As noted in #82044 (comment), this is a DUP of #75601 . And I have an implementation of this in not-yet-merged-ATM PR #83919, since I was already mucking around in that code, and this was easy enough to add.

@pmuellr pmuellr closed this as completed Nov 24, 2020
@kobelb kobelb added the needs-team Issues missing a team label label Jan 31, 2022
@botelastic botelastic bot removed the needs-team Issues missing a team label label Jan 31, 2022
@chadnormanimpact
Copy link

has anyone been able to surface something like user.email in Alerts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Alerting good first issue low hanging fruit Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams)
Projects
None yet
Development

No branches or pull requests

6 participants