Conversation
|
Pinging @elastic/es-core-infra |
| You can then use the example watch to retrieve and manipulate total spend | ||
| calculations for each play present in the example data set. | ||
|
|
||
| The watcher condition can be used in two places, and below are examples of each. |
There was a problem hiding this comment.
I dont really like this sentence, and would like advice on whether its needed.
|
I hope this is in the right direction. I would love some feedback from the docs team and @jdconrad on whether this is good or not. Next up is transform, and I will be doing something similar to this for transform. Feedback welcome!!! |
|
Adding @debadair for docs review. |
|
@hub-cap Thanks for the work so far! Much appreciated. |
|
while munching a sandwich at lunch I decided I did not like these docs. I think they should be structured differently. Give me some time to formulate, but lets not worry about review for now. |
|
So my thought is to consolidate both of the watcher contexts into 1 document. Both of the contexts share the same variables accessible within the context. So I figured I can use a single example to show both the transform and the condition, as well as highlight all the values within the context. Its going to take me a little while to glean all the values that the context may have, so it could be another day until I get an update here. Lets wait on any review until then. |
|
Thank you so much for these examples, they will be super useful to users trying to orient themselves. For completeness I have a similar (in functionality) pattern that I find using over an over in watchers that collect potentially multiple events (which is vast majority in many use cases): def events = [];
for (def host: ctx.payload.aggregations.hosts.buckets) {
if (host.max_cpu.value > 90) {
events.add([
// add generic metadata about the event
'_id': ctx.watch_id + '-' + host.key,
'watch': ctx.watch_id,
'@timestamp': ctx.trigger.triggered_time,
// and all the values that contributed to it being an event
'host': host.key,
'cpu': host.max_cpu.value
]);
}
}
ctx.payload.events = events;
return events.size() > 0;I store the resulting list on the Because the stream API is not as well known among people not fluent in Java I purposefully avoid it and stick with the super basic |
Refactor out the variables, and reuse them in the 2 contexts, as well as adding a complete example to each of the actual docs.
|
@honzakral im considering adding this for entry, i just need to find out where is a good place for it. Maybe I can add it in the "complete examples" section. @debadair and @jdconrad, I have restructured it such that the variables section now has its own file and that is imported into both of the context examples. They also both have a "complete example" imported in at the end so the user can actually understand a full watch example with both conditions and transforms. I think this is probably a good place to put the "for loop" example from honza above, as well. As is, I think its ready for ripping my horrible use of the english language apart. |
jdconrad
left a comment
There was a problem hiding this comment.
Looks good to me from the tech side. Left a few comments on wording and such. Thanks so much for doing this! I really appreciate you going through the variables and adding hefty docs for them as well. This should be really helpful for our users.
| Any metadata associated with the watch. | ||
| <1> The Java Stream API is used in the condition. This API allows manipulation of | ||
| the elements of the list in a pipeline. | ||
| <2> A Stream Filter is used to remove items that do not meet the criteria within the |
There was a problem hiding this comment.
Should stream filter be capitalized?
There was a problem hiding this comment.
nope :-)
<2> The stream filter removes items that do not meet the filter criteria.
| the elements of the list in a pipeline. | ||
| <2> A Stream Filter is used to remove items that do not meet the criteria within the | ||
| filter. | ||
| <3> The collector reduces the stream back into a java.util.List |
There was a problem hiding this comment.
add back ticks to java.util.List
There was a problem hiding this comment.
And then add a period. I'd also say "reduces the stream to a" rather than "back into a".
| `ctx['trigger']['scheduled_time']` (`ZonedDateTime`, read-only):: | ||
| The scheduled trigger time for the watch. | ||
| The first example is a condition for the watch itself. This determines if any | ||
| of the actions in the watch are executed. The example aggregates the total sold |
There was a problem hiding this comment.
This may need to be re-worded as it sounds like you can select individual actions to execute for a watch based on a single condition.
There was a problem hiding this comment.
In other places, we use an "Example" label before the example intro (like Return and API).
Rather than "first" and "second", I'd just use "the following" to introduce the examples.
Example
The following watch condition script controls overall execution of the watch based on the value of the seats sold for the plays in the data set. The script aggregates the total sold seats for each play and returns true if there is at least one play that has sold under $15,000 or over $50,000.
| *Return* | ||
| The next example is a condition on an action. This determines if a distinct action | ||
| in the watch are executed. The example aggregates the total sold seats for each play | ||
| in the data set. The action condition validates that there is at least one play that |
There was a problem hiding this comment.
Can you be more descriptive here about the aggregation being executed? Aggregates the total seats how?
There was a problem hiding this comment.
This is a bit redundant. I'd used the pattern from the watch condition intro:
The following action condition script controls execution of the my_log action based on the value of the seats sold for the plays in the data set. The script aggregates the total sold seats for each play and returns true if there is at least one play that has sold over $50,000.
| @@ -0,0 +1,112 @@ | |||
| ==== Complete Example | |||
|
|
|||
| While these examples are contrived, a more complete watch shown below contains | |||
There was a problem hiding this comment.
Don't think you need to call out the example as contrived as that makes it sound like it's not really useful. Short examples often don't represent real world scenarios.
There was a problem hiding this comment.
Yeah, we generally avoid "meta info" like that as much as possible.
|
|
||
| ==== Time values in a watch | ||
|
|
||
| There are 3 time values that are available as part of the context. The |
|
@spinscale if you would like to take a look as well, id be delighted :) |
spinscale
left a comment
There was a problem hiding this comment.
I left a few comments for possible improvements, nothing major though
| "script" : | ||
| """ | ||
| return ctx.payload.aggregations.theatres.buckets.stream() <1> | ||
| .filter(t -> t.money.value < 15000 || t.money.value > 50000) <2> |
There was a problem hiding this comment.
maybe replace the t with threatre or bucket?
| return ctx.payload.aggregations.theatres.buckets.stream() <1> | ||
| .filter(t -> t.money.value < 15000 || t.money.value > 50000) <2> | ||
| .collect(Collectors.toList()) <3> | ||
| .size() > 0 <4> |
There was a problem hiding this comment.
no need to create a list first and then use size, just use .count()?
| """ | ||
| return ctx.payload.aggregations.theatres.buckets.stream() | ||
| .filter(t -> t.money.value > 50000) <2> | ||
| .collect(Collectors.toList()) |
There was a problem hiding this comment.
hm, you don't even need .count(). You can use return ctx.payload.aggregations.theatres.buckets.stream().anyMatch(b -> b.money.value > 50000)`
| .filter(t -> t.money.value < ctx.metadata.low_threshold || | ||
| t.money.value > ctx.metadata.high_threshold) | ||
| .collect(Collectors.toList()) | ||
| .size() > 0 |
There was a problem hiding this comment.
again, use Stream.anyMatch()
| 'msg': ctx.payload.money_makers.stream() | ||
| .map(t-> formatter.format(t.total_value) + ' for the play ' + t.play) | ||
| .collect(Collectors.toList()) | ||
| .join(", ") |
There was a problem hiding this comment.
just do Collectors.joining(' FOO ') instead of collect and join?
| ==== Time values in a watch | ||
|
|
||
| There are 3 time values that are available as part of the context. The | ||
| execution_time is the actual time the watch is executed. The other two |
There was a problem hiding this comment.
backticks around execution time?
| "transform" : { | ||
| "script": | ||
| """ | ||
| return [ 'elements': ctx.payload.aggregations.theatres.buckets.size() ] |
There was a problem hiding this comment.
this transform is also not needed, one could call {{ctx.payload.aggregations.theatres.buckets.size}} to get the same result.
| } | ||
| }, | ||
| "actions" : { | ||
| "mod_log" : { |
There was a problem hiding this comment.
maybe use the long form for the action names here?
| "text" : "The output of the payload was transformed to: {{ctx.payload.msg}}" | ||
| } | ||
| }, | ||
| "unmod_log" : { <2> |
| 'msg': ctx.payload.aggregations.theatres.buckets.stream() | ||
| .map(t-> formatter.format(t.money.value) + ' for the play ' + t.key) | ||
| .collect(Collectors.toList()) | ||
| .join(", ") |
There was a problem hiding this comment.
Collectors.joining(', ')?
| will return a `boolean` value to determine if the condition was met. A | ||
| condition can be used to short circuit an entire watch or within an action | ||
| to determine execution of said action. | ||
|
|
There was a problem hiding this comment.
In general, we prefer present tense and active voice. I'd also consistently use either "watch condition" rather than flip-flopping between it and "Watcher condition". The last sentence and the first are largely redundant. I'd probably go with:
Use a Painless script as a {xpack-ref}/condition-script.html[watch condition]
that determines whether to execute a watch or a particular action within a watch.
Condition scripts return a Boolean value to indicate the status of the condition.
I'd bump this up to follow the Watch condition context heading, before the context variables.
| User-defined parameters passed in as part of the query. | ||
| `boolean`:: | ||
| Expects `true` if the condition is met, and `false` otherwise. | ||
|
|
There was a problem hiding this comment.
I'd say "Returns true if the condition is met, false if it is not."
| @@ -0,0 +1,112 @@ | |||
| ==== Complete Example | |||
|
|
|||
| While these examples are contrived, a more complete watch shown below contains | |||
There was a problem hiding this comment.
Yeah, we generally avoid "meta info" like that as much as possible.
| `ctx['trigger']['scheduled_time']` (`ZonedDateTime`, read-only):: | ||
| The scheduled trigger time for the watch. | ||
| The first example is a condition for the watch itself. This determines if any | ||
| of the actions in the watch are executed. The example aggregates the total sold |
There was a problem hiding this comment.
In other places, we use an "Example" label before the example intro (like Return and API).
Rather than "first" and "second", I'd just use "the following" to introduce the examples.
Example
The following watch condition script controls overall execution of the watch based on the value of the seats sold for the plays in the data set. The script aggregates the total sold seats for each play and returns true if there is at least one play that has sold under $15,000 or over $50,000.
| Any metadata associated with the watch. | ||
| <1> The Java Stream API is used in the condition. This API allows manipulation of | ||
| the elements of the list in a pipeline. | ||
| <2> A Stream Filter is used to remove items that do not meet the criteria within the |
There was a problem hiding this comment.
nope :-)
<2> The stream filter removes items that do not meet the filter criteria.
| *Return* | ||
| The next example is a condition on an action. This determines if a distinct action | ||
| in the watch are executed. The example aggregates the total sold seats for each play | ||
| in the data set. The action condition validates that there is at least one play that |
There was a problem hiding this comment.
This is a bit redundant. I'd used the pattern from the watch condition intro:
The following action condition script controls execution of the my_log action based on the value of the seats sold for the plays in the data set. The script aggregates the total sold seats for each play and returns true if there is at least one play that has sold over $50,000.
| @@ -0,0 +1,112 @@ | |||
| ==== Complete Example | |||
There was a problem hiding this comment.
I'd remove the heading & just have this as part of the Example section.
| both <<painless-watcher-condition-context, conditions>> and | ||
| <<painless-watcher-transform-context, transforms>>, and is the basis of the | ||
| above examples. It is shown for completeness. | ||
|
|
There was a problem hiding this comment.
Maybe: The following example shows scripted watch and action conditions within the context of a complete watch. This watch also uses a scripted <<painless-watcher-transform-context, transform>>.
I wouldn't link back to the top of this topic.
| "condition" : { | ||
| "script" : | ||
| """ | ||
| return ctx.metadata.high_threshold == 50000 <1> |
There was a problem hiding this comment.
This and the time values examples seem overly-heavyweight to simply show how to access these values. I'd incorporate the info/example snippet into the context variable descriptions and maybe mention in the intro that condition scripts can access watch metadata and timestamps.
| @@ -1,39 +1,162 @@ | |||
| [[painless-watcher-transform-context]] | |||
| === Watcher transform context | |||
|
|
|||
There was a problem hiding this comment.
Pretty much the same set of comments applies to the transform context. :-)
|
Thanks to everyone for the reviews! Im going to get on these ASAP tomorrow! |
|
I have updated the docs based on the feedback. thanks to @jdconrad @spinscale and @debadair. the biggest "change" that i did that was not just following update comments was to move all of the common examples (metadata/time values/payload) into their own example. I just stuck it at the end, after the other example. Id like to still show some date formatting in the example, but its not strictly necessary if it does not fit the rest of the flow. Id be happy to remove it if it does not make sense there. |
* master: Reformat some classes in the index universe [DOCS] Add watcher context examples (elastic#36565)
No description provided.