Use of runtime values on host templates

Hi,

I’m defining a template of the form

template Host "my-template-a" {  
check_command = "hostalive4"
vars.numericoffset=globals.notification_interval_function()
 }

globals.numericoffset=function() {
var node_name="$host.name$"
return len(node_name)
}

When I do the import:

object Host "my-hostname-2.lab.internal" { import "my-template-a" }

Icinga does not render the expected

host.vars.numericoffset = 26 #the length off the object Host

but instead it renders

host.vars.numericoffset = 11 #the length off the string “$host.name$”

Is there a way to access the Object Hostname, (or any equivalent runtime variable for already imported templates) at configuration time ??

Thanks in advance

Hi,

I don’t understand these code parts.

There’s vars.numericoffset as host custom var, setting a function object as value (likely not intended).
There’s also globals.numericoffset registering a function.

globals.notification_interval_function() is not defined anywhere.

Aside from that, var node_name is a pure string and the len() call just returns the string length.
There’s no macro resolution in place.

Question remains, what’s the purpose of vars.numericoffset and where would you want to access that? Based on that answer we may recommend possible solutions.

Cheers,
Michael

Hi @mfriedrich, I have confused the definitions (faulty code simplification)
code:

 template Host "my-template-a" {  
check_command = "hostalive4"
vars.my_desired_variable=globals.numericoffset()
 }

globals.numericoffset=function() {
var node_name="$host.name$"
return len(node_name)
}

object Host "my-hostname-2.lab.internal" { import "my-template-a" }

outcome when querying host attributes (via api):

vars.my_desired_variable = 11 #the length off the string “$host.name$”

instead of my desired:
vars.my_desired_variable = 26 #the length off the object Host

I only got the right question, about if there’s any attribute from already imported templates/ or even the object name, available for using either as a function parameter or within the global function during the update/generation of the object in icinga

< I understand, the marco is not availabla unless at runtime , but i need it at object-generation time

The macro function can be used to resolve runtime macro strings into their values. The returned value depends on the attribute value which is resolved from the specified runtime macro.

I just want to know the purpose of this calculated value. If you for example say that you want its value being used inside the Grafana module for some calculations, we need a different route.

If you want to use it for functionality inside the objects themselves, another approach might be applicable.

The more ideas you share, the better answers you get. Right now, I don’t know what would fit here.

Cheers,
Michael

Hi,

let’s get some context

information/ConfigItem: Instantiated 190632 Notifications.
information/ConfigItem: Instantiated 6278 Hosts.
information/ConfigItem: Instantiated 94349 Services.

I’m using A calculated value, to “randomly spread notifications” in time, as to avoid icinga getting OOM killed/stalled due to excessive notifications being sent simultaneously.

Actual function:

    globals.notification_interval_function=function(base_notification_interval,randon_notification_delay_range) {
      var b=Math.ceil(randon_notification_delay_range*Math.random())
      return (base_notification_interval+b)
    } 

Is used to set the notification interval; in example:

apply Notification "service-prod" to Service {
  import "z"
  interval = globals.notification_interval_function(PRODUCTION_NOTIFICATION_FREQUENCY, PRODUCTION_MAX_NOTIFICATION_DELAY)
  users = [ "x" ]
  assign where host.vars.production
  ignore where service.vars.disable_notifications
}

That way, I prevent All notifications being sent at once, this however causes the following issue:

  • upon configuration reload/update, Icinga sends nearly 15 minutes of inserts/deletes commands to mysql backend, causing the ido_mysql queues to skyrocket from avg 1000 items in queue up to 2.1 M items in queue. Issue is that notifications, and state information will only catch up in nearly after 45 minutes (that is 45 minutes without alerting !!!)

Since I suspect the variation of this value during configuration updates is somehow being persisted on the database, I was trying to migrate the function to something based on the “host” vars; i.e. “address” or “host.name” so that the function can be updated to some hashing value (like len of host.name or 10xsqrt(host.name)) and the performance hit is fully removed; but this in turn needs the object attributes and/or vars to be available during object creation (not really on api timing).

At the begining of the post; the function was addes as host.vars.notification_frequency; at the moment is being added to the notification object instead…

Do you think the problem has stated in a better manner now?

Is this notification.interval value trully being persisted somehow to database backend?

best regards,

Hi, I have just made the notification interval inmutable for each notification object, fixing the time required by database to update the field notification_interval on services and hosts table.

I’ll be closing the ticket.

Now, Is it possible to provide a hashmode function,

i.e
math.hashmod (some_string, modulus)
where given a string to hash, the outcome is a to the modulus of a hash of the said string, between 0 and the modulus integer? pretty much like prometheus “hashmod” function ?

Thanks in advance,

Hi,

interval = globals.notification_interval_function(PRODUCTION_NOTIFICATION_FREQUENCY, PRODUCTION_MAX_NOTIFICATION_DELAY)

defined in the notification object will be calculated at config compile time, not at runtime.

If you want to pass in the host name into the function, apply rules have access to the host and service virtual identifier.

Something like

interval = globals.notification_interval_function(PRODUCTION_NOTIFICATION_FREQUENCY, PRODUCTION_MAX_NOTIFICATION_DELAY, host.name)

could then be used in that function

   globals.notification_interval_function=function(base_notification_interval,randon_notification_delay_range, host_name) {
      var b=Math.ceil(randon_notification_delay_range*Math.random())

      var offset = len(host_name)

      return (base_notification_interval+b+offset)
    } 

Though I am not sure if that helps with the original problem of making the notification scheduler go nuts.

Prometheus’ hashmod sounds interesting, also in terms of scheduling checks @elippmann


At the moment we don’t expose any hashing algorithm functions to the user via DSL, but I am open for a feature request on GitHub here.

Cheers,
Michael