[ZBXNEXT-2047] Improved Media Type support for scripts, xml, and json data Created: 2013 Nov 28  Updated: 2015 Sep 01

Status: Open
Project: ZABBIX FEATURE REQUESTS
Component/s: Server (S)
Affects Version/s: 2.0.9
Fix Version/s: None

Type: New Feature Request Priority: Minor
Reporter: Todd Ebersviller Assignee: Unassigned
Resolution: Unresolved Votes: 9
Labels: actions, json, mediatypes, xml
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
is duplicated by ZBXNEXT-2712 Extra variables for alert scripts Closed

 Description   

I would like to see an improvement to media types to enable us to pass Zabbix macros to scripts in a more structured way. Today scripts that are called are passed three arguments. I would instead like to see that number be dynamic and we could choose to map up Zabbix macros to certain named arguments. Then our scripts like Python could pull those arguments in a more structured form such as dictionaries.

As a more sophisticated alternative you could pass macros in to XML or JSON encoded formats for us to then load and customize as needed. You could even allow us to do a POST of this data to the URL of our choosing without the need to write a custom script to accomplish that.

For example in actions today you can do something like this to try and structure something as JSON:

{
"event": [
{ "name":"{TRIGGER.NAME}" },
{ "trigger_name":"{TRIGGER.TEMPLATE.NAME}" },
{ "trigger_group":"{TRIGGER.HOSTGROUP.NAME}" },
{ "trigger_description":"{TRIGGER.DESCRIPTION}" },
{ "id":"{TRIGGER.ID}" },
{ "item_name":"{ITEM.NAME}" },
{ "reference_url":"http://hostname/zabbix/tr_events.php?triggerid={TRIGGER.ID}&eventid={EVENT.ID}" },
{ "hostname":"{HOSTNAME}" },
{ "ip":"{IPADDRESS}" },
{ "value":"{TRIGGER.VALUE}" },
{ "event_id":"{EVENT.ID}" },
{ "severity":"{TRIGGER.SEVERITY}" },
{ "datetime":"{EVENT.DATE} {EVENT.TIME}" }
]
}

Something like this works and then you can use your language of choice to import this object, manipulate it as needed, and pass it along to your other systems. However, if you want to pass in something like ITEM.LASTVALUE it could be a log entry that contains multiple lines or characters that would make this structure invalid. That issue then forces you to use hacks such as creating your own unique delimiter and splitting values based off that. It works, but it would be much cleaner if we could simply bind macros of our choosing to named positional arguments or if you had a XML or JSON option. As users integrate Zabbix in to more third party systems the more this type of functionality becomes valuable.



 Comments   
Comment by Volker Fröhlich [ 2015 Jan 10 ]

It should be fairly easy to add a 4th positional argument into the server code that returns all defined macros.

Comment by Justin Martin [ 2015 Jan 10 ]

My solution: https://gist.github.com/TheFrozenFire/2e4dbcd05e570ca86721

Comment by Justin Martin [ 2015 Jan 10 ]

Native support should be implemented as a setting on the remote command which specifies whether to pass the structured data (preferably JSON) via STDIN. Passing it as a positional parameter subjects the data to shell escaping, which can only cause problems.

Comment by Ryan Armstrong [ 2015 Mar 13 ]

This is a valid solution to the problem I've raised in ZBXNEXT-2712.

Comment by Todd Ebersviller [ 2015 Mar 13 ]

In the end I just updated the action so it would pass in K/V info split by a double pipe || so that it could handle multiline items such as log entries.

Meaning you'd setup an action similar to this:
"event_id"="

{EVENT.ID}"||
"severity"="{TRIGGER.SEVERITY}"||
"datetime_item_cst"="{ITEM.LOG.DATE} {ITEM.LOG.TIME}"||
"datetime_cst"="{EVENT.DATE} {EVENT.TIME}"||
"sourceid"="{EVENT.ID}

"

Then here is the relevant snippet of the Python code used.
#!/usr/bin/env python
import datetime, sys, logging, simplejson, requests
data=sys.argv[3]
data=data.split('||')
datadictionary = {}
for item in data:
key, val = item.split("=", 1)
k=(key.replace('"',"").strip())
v=((val.replace('"',"").strip())).replace('\n',"<br>")
datadictionary[ k ] = v
datadictionary['datetime_insert_utc'] = str(datetime.datetime.utcnow())
datajson = simplejson.dumps(datadictionary)

At that point you have a nice K/V relationship that you can do whatever you'd like to. This work around is fine for my needs. Hopefully it helps someone else as well.

Comment by Ryan Armstrong [ 2015 Aug 31 ]

Other monitoring tools (can I name them?) achieve this by passing all available macros as Environment Variable to all script commands.

This way, no JSON/other decoding is required. The script can just read ${EVENT_ID} or whatever...
Working on a patch for this today.

Comment by Ryan Armstrong [ 2015 Aug 31 ]

Well.... That patch won't be easily forthcoming. It is achievable, but not with my current priorities.
Here's what I found before calling it quits:

  • zbx_popen() needs to use execle() instead of execl() and accept a char *[] envp parameter
  • zbx_execute() needs to be updated with an envp parameter and all functions that call it (easy)
  • A fields need to be added to the DB_ALERT struct to store the extra variables
  • The alerts table schema needs to be updated to store the extra variables
Generated at Sat Apr 20 05:10:39 EEST 2024 using Jira 9.12.4#9120004-sha1:625303b708afdb767e17cb2838290c41888e9ff0.