Why contexts?

In debugging a Filebeat module, I have had to dig into Painless scripts & contexts which has led to several questions:

  • Why contexts?

  • Can the same data not be accessed via _doc? (I've also seen this asked in other threads as well)

  • In the snippet below from the module I am debugging, the goal seems straightforward enough: set _temp_.time to the value of {{sophos.xg.date}} {{sophos.xg.time}}; but the if statement is where I am lost. There are similar statements all over the module but I am unable to find any reference that discusses the use question marks in context references. I'm sure there is a good reason - just can't find it...

- set:
    field: _temp_.time
    value: "{{sophos.xg.date}} {{sophos.xg.time}}"
    if: "ctx?.sophos?.xg?.date != null && ctx?.sophos?.xg?.time != null"

The ? marks are for null safety

From this page section down a bit

Incoming documents often contain object fields. If a processor script attempts to access a field whose parent object does not exist, Elasticsearch returns a NullPointerException . To avoid these exceptions, use null safe operators, such as ?. , and write your scripts to be null safe.

For example, ctx.network?.name.equalsIgnoreCase('Guest') is not null safe. ctx.network?.name can return null. Rewrite the script as 'Guest'.equalsIgnoreCase(ctx.network?.name) , which is null safe because Guest is always non-null.

If you can’t rewrite a script to be null safe, include an explicit null check.

Hi @stephenb - thanks for providing this. Now that I see it, I do believe I saw it last week when I was chatting with you about this module but that was before I started digging into Painless so it didn't register.

So using the snippet I provided:

  • Is it basically protecting against any of ctx, ctx.sophos, or ctx.sophos.xg returning NULL?

  • Also, if one knows for certain that ctx.sophos defintely exists, could this statement be used instead? ctx.sophos.xg?

Right to left protects agains sophos null, the xg null then date null

Yes probably but the ? are safer and recommended... it will crash the pipeline if you try to access a null.

I would follow the patterns shown as best practice

Understood - thank you.

Also, in trying to answer my own post asking "Why contexts?", it appears that Painless contexts are borrowed from Java but I'm not sure if I have this correct; can you confirm or deny?

I am not a painless expert... but it is related to Java... tons of docs if you really want to get into it.

Believe me, I have been. The docs definitely reference Java quite a bit but as to why contexts exist in Painless; I've haven't seen that discussed but given the relation between the two, it just makes sense that it would be borrowed.

Thanks again...

A Painless script is evaluated within a context. Each context has values that are available as local variables, an allowlist that controls the available classes, and the methods and fields within those classes (API), and if and what type of value is returned.

Painless scripts typically run within one of the contexts in the following table. Before using a Painless context, configure the example data. Each context example is configured to operate on this data.

Thats about as much as I know on the subject :wink:

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.