Usage of dictionaries for oracle_health and tablespace_usage

Hi all,

I try to monitor an Oracle database with “oracle_health” and various checks reading from a dictionary. This works fine for those checks which do not need an additional argument e.g. tnsping. For checks which need additional arguments like “tablespace_usage” one has to define additional variables. I did it in the host object but the check use the last tablespace name only. What’s wrong?

The service is like:

 apply Service "ORACLE: " for (mode => config in host.vars.oracle_health) {
  import "generic-service"
  check_command = "oracle_health"

  vars.oracle_home = "/usr/lib/oracle/12.1/client64"
  vars.oracle_ld_library_path = "/usr/lib/oracle/12.1/client64"
  vars.oracle_tns_admin = "/usr/lib/oracle/12.1/client64/network/admin"

  vars.oracle_health_mode = mode

  vars += config

  vars.oracle_health_connect = "$host.name$"
  vars.oracle_health_username = "<USER>"
  vars.oracle_health_password = "<PASSWORD>"

  #assign where match ("slesora-dev.*", host.name)
  assign where match ("slesora*", host.name)
}

The variables are defined in the host object:

  vars.oracle_health["connected-users"] = {}
  vars.oracle_health["session-usage"] = {}
  vars.oracle_health["process-usage"] = {}
  vars.oracle_health["connection-time"] = {}
  vars.oracle_health["flash-recovery-area-usage"] = {}
  vars.oracle_health["invalid-objects"] = {}
  vars.oracle_health["tnsping"] = {}
  vars.oracle_health["rman-backup-problems"] = {}

  vars.oracle_health["tablespace-usage"] = {
    oracle_health_name = [ "SYSTEM", "USERS" ]
  }

The object looks like:

root@ucsnetmon2:/etc/icinga2/conf.d/local.d# icinga2 object list --name "ORACLE: tablespace-usage"
Object 'slesora.ltbbg1.lvnbb.de!ORACLE: tablespace-usage' of type 'Service':
  % declared in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 290:1-290:72
  * __name = "slesora.ltbbg1.lvnbb.de!ORACLE: tablespace-usage"
  * action_url = ""
  * check_command = "oracle_health"
    % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 292:3-292:33
  * check_interval = 600
    % = modified in '/etc/icinga2/conf.d/templates.conf', lines 28:3-28:22
  * check_period = ""
  * check_timeout = null
  * command_endpoint = ""
  * display_name = "ORACLE: tablespace-usage"
  * enable_active_checks = true
  * enable_event_handler = true
  * enable_flapping = false
  * enable_notifications = true
  * enable_passive_checks = true
  * enable_perfdata = true
  * event_command = ""
  * flapping_threshold = 0
  * flapping_threshold_high = 30
  * flapping_threshold_low = 25
  * groups = [ ]
  * host_name = "slesora.ltbbg1.lvnbb.de"
    % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 290:1-290:72
  * icon_image = ""
  * icon_image_alt = ""
  * max_check_attempts = 5
    % = modified in '/etc/icinga2/conf.d/templates.conf', lines 27:3-27:24
  * name = "ORACLE: tablespace-usage"
    % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 290:1-290:72
  * notes = ""
  * notes_url = ""
  * package = "_etc"
    % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 290:1-290:72
  * retry_interval = 60
    % = modified in '/etc/icinga2/conf.d/templates.conf', lines 29:3-29:21
  * source_location
    * first_column = 1
    * first_line = 290
    * last_column = 72
    * last_line = 290
    * path = "/etc/icinga2/conf.d/local.d/elvis2.conf"
  * templates = [ "ORACLE: tablespace-usage", "generic-service" ]
    % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 290:1-290:72
    % = modified in '/etc/icinga2/conf.d/templates.conf', lines 26:1-26:34
  * type = "Service"
  * vars
    % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 300:3-300:16
    * oracle_health_connect = "$host.name$"
      % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 302:3-302:44
    * oracle_health_mode = "tablespace-usage"
      % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 298:3-298:32
    * oracle_health_name = [ "SYSTEM", "USERS" ]
    * oracle_health_password = "<PASSWORD>"
      % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 304:3-304:46
    * oracle_health_username = "<USER>"
      % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 303:3-303:40
    * oracle_home = "/usr/lib/oracle/12.1/client64"
      % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 294:3-294:52
    * oracle_ld_library_path = "/usr/lib/oracle/12.1/client64"
      % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 295:3-295:63
    * oracle_tns_admin = "/usr/lib/oracle/12.1/client64/network/admin"
      % = modified in '/etc/icinga2/conf.d/local.d/elvis2.conf', lines 296:3-296:71
  * volatile = false
  * zone = ""

Regards and Thanks
Stephan

Hi,

  vars.oracle_health["tablespace-usage"] = {
    oracle_health_name = [ "SYSTEM", "USERS" ]
  }

creates a nested condition - you want services for

  • tablespace-usage with SYSTEM
  • tablespace-usage with USERS

The current apply for look only names tablespace-usage as loop key, and doesn’t know how to access the inner additional tablespace names.

There’s two solutions for this:

Either you create unique key-names inside the host object for vars.oracle_health, like

  vars.oracle_health["tablespace-usage-system"] = {
    oracle_health_name = "SYSTEM"
  }
  vars.oracle_health["tablespace-usage-users"] = {
    oracle_health_name = "USERS"
  }

and cut the mode inside the apply for loop, like

  if (match("tablespace-usage*", mode)) {
     vars.oracle_health_mode = "tablespace-usage"
  } else {
     vars.oracle_health_mode = mode
  }

or you’ll follow this howto to flatten specific nested arrays. Keep in mind that this may not work with the other keys in vars.oracle_health then.

The main problem is that oracle_health_name only takes a single tablespace name, not arrays or lists.

Cheers,
Michael

Thanks a lot Michael for quick help - the first solution works perfectly!

Cheers,
Stephan