This is a feature request for the ability to specify custom JSON output for the Alert Post and HttpPost nodes. As it stands now there is no control over how the JSON looks and adding additional elements to it is not a trivial task.
In thinking how this might be implemented I could see a parameter that might point to a template file that could perform the mapping:
.template(String template, Boolean appendUnusedValues)
templateFIle -- The path and name pf the template file or a string with the template definition. This would allow you to specify the template in the TICK script as a var or separately as a file
appendUnusedValues -- If true would append any remaining tags or fields to the end of the json. This would provide the ability to transform certain tags or fields while retaining many of the original tags and fields. If false only the tag or field values specified in the template will be in the output json
stream
|httpPost()
.template('myTemplate.tmpl', true)
.endpoint('example')
Where the template file might look like:
{
"myParam1": {{tag.tagName}},
"myParam2": {{field.fieldName}}
}
Thoughts?
This new feature would be greatly improved if could also use the Tick variables on the template as requested in (https://github.com/influxdata/kapacitor/issues/894)
I think this is now currently possible via https://github.com/influxdata/kapacitor/pull/1572
@rbetts This is complete already in the #1572 as noted above. Closing....
@nathanielc, would it be possible to have an example as to how to achieve JSON mapping with TICK DSL?
Hi,
I will try to explain my trial on defining a post to an endpoint on my script, with custom json using an alert-template-file.
First, we'll need to edit the kapacitor config (.../kapacitor/kapacitor.conf) to configure the endpoint, url, headers and the path to the template:
[[httpPost]]
endpoint = "test" -> We will need to pass this on the tick like .post().endpoint('test')
url = "www.test.com" -> URL to post our templated json. Obviously, the one needed!
headers = { Content-Type = "application/json; charset=UTF-8" }
basic-auth = { username = "", password = "" }
alert-template-file = "/path/to/template"
Second, lets define the template. We use tmpl for testing and works fine. The template looks like:
{
"id": "{{.ID}}",
"message": "{{.Message}}",
"details": "{{.Details}}",
"time": "{{.Time}}",
"duration": "{{ .Duration}}",
"level": "{{.Level}}",
"recoverable": {{.Recoverable}},
"data": {{ .Data }}
}
Last, we need to fire from our tick script. As stated above, the only need to configure on the tick is on the alert make:
.post()
.endpoint('test')
With all this done, the results look like:
POST / HTTP/1.1
Host: 192.168.1.40:9999
User-Agent: Go-http-client/1.1
Content-Length: 447
Content-Type: application/json; charset=UTF-8
Accept-Encoding: gzip
{
"id": "use cpu:host=amondelo",
"message": " use cpu:host=amondelo cpu chronograf-v1-1742046d-72f3-4c2e-a4f5-4273ce2ddae3 host=amondelo 2.5",
"details": "Valor 2.5",
"time": "2018-10-26 07:56:49 +0000 UTC",
"duration": "10s",
"level": "CRITICAL",
"recoverable": "true",
"data": {"series":[{"name":"cpu","tags":{"cpu":"cpu0","host":"amondelo"},"columns":["time","value"],"values":[["2018-10-26T07:56:49Z",2.5]]}]}
}
Hope this can help others (like me...) trying to use this useful way to send alerts to other systems!
@arturo-mondelo this is a good example in the right direction.
I have few questions and points of clarification, perhaps it will be an help for others too.
Can i use this using Chronograf?
I did not understand what you meant by "tmpl".
will the alert-template-file a .yml?
What will be the ticksript look like? Do i need to pass .message field in ticksript, am not sure since we are defining the alert body in the alert-template-file.
Hi @ashishkaransingh
Sure, i try to answer those...
Yes, you can use it from chronograph...Just add to the tick:
.post()
.endpoint('endpoint_name_on_the_kapacitor_config')
About tmpl, we choose that one. You can use any other supported (html for instance...) but i just uploaded my tests; and i defined the template as .tmpl
Yes, you need to define the message and the details on the tickscript. Also, you can define a custom id, and that will be sent...The rest (level, data, time...) are provided and no action is required by your side (neither id; it have the default one so no need to make your own!)
Hope this solve your doubts!
Regards
PD: I can upload my test tickscript if you want a working example with the configuration mentioned, made using chronograf.
Hi @ashishkaransingh
Sure, i try to answer those...
Yes, you can use it from chronograph...Just add to the tick:
.post()
.endpoint('endpoint_name_on_the_kapacitor_config')About tmpl, we choose that one. You can use any other supported (html for instance...) but i just uploaded my tests; and i defined the template as .tmpl
Yes, you need to define the message and the details on the tickscript. Also, you can define a custom id, and that will be sent...The rest (level, data, time...) are provided and no action is required by your side (neither id; it have the default one so no need to make your own!)
Hope this solve your doubts!
Regards
PD: I can upload my test tickscript if you want a working example with the configuration mentioned, made using chronograf.
Thanks a lot for your reply!
Yes a sample test tickscript would be great.
@arturo-mondelo So currently this is the piece of kapacitor.conf for HTTPPOST
[[httppost]]
endpoint = "test"
url = "https://testapi.com"
headers = {Content-Type = "application/json; charset=UTF-8"}
#basic-auth = { username = "my-user", password = "my-pass" }
alert-template-file = "C:/temp/tmpl.yml"
And Tickscript:
(it is incomplete, as i did not define message being unsure of how to use the template)
var db = 'testinfluxdb'
var rp = 'seven_days_only'
var measurement = 'Process'
var groupBy = []
var whereFilter = lambda: ("instance" == 'telegraf' OR "instance" == 'winlogbeat')
var name = 'Test_Test008'
var idVar = name
var idTag = 'alertID'
var levelTag = 'level'
var messageField = 'message'
var durationField = 'duration'
var outputDB = 'chronograf'
var outputRP = 'autogen'
var outputMeasurement = 'alerts'
var triggerType = 'threshold'
var crit = 0
var data = stream
|from()
.database(db)
.retentionPolicy(rp)
.measurement(measurement)
.groupBy(groupBy)
.where(whereFilter)
|eval(lambda: "Percent_Processor_Time")
.as('value')
var trigger = data
|alert()
.crit(lambda: "value" > crit)
.message(message)
//.id(idVar)
//.idTag(idTag)
//.levelTag(levelTag)
//.messageField(messageField)
//.durationField(durationField)
.post()
.endpoint('test')
.log('C:\temp\process.log')
trigger
|eval(lambda: float("value"))
.as('value')
.keep()
|influxDBOut()
.create()
.database(outputDB)
.retentionPolicy(outputRP)
.measurement(outputMeasurement)
.tag('alertName', name)
.tag('triggerType', triggerType)
trigger
|httpOut('output')
Well actually i don't get why you are using yaml file. Attending to the documenation:
https://docs.influxdata.com/kapacitor/v1.5/event_handlers/post/#alert-templates
"Alert templates are used to construct a custom HTTP body"
Try with an .html or .tmpl extension even with mine (save it c:/tmp/post.tmpl):
{
"id": "{{.ID}}",
"message": "{{.Message}}",
"details": "{{.Details}}",
"time": "{{.Time}}",
"duration": "{{ .Duration}}",
"level": "{{.Level}}",
"recoverable": {{.Recoverable}},
"data": {{ .Data }}
}
And i'm pretty sure you have this working!
I tried using .html and .tmpl, once i start tickscript i do see logs but nothing gets posted.
I will change it back to .htmlm and try again.
It would be helpful if you can share a working example of tickscript.
looking forward for your working example with chronograf.
Ok
Yes i will upload the script used on this trial later (i don't have the one used on this computer!)
But is just a quick test (don't expect much!) script, and yes, generated on chronograf directly.
Ok
Yes i will upload the script used on this trial later (i don't have the one used on this computer!)
But is just a quick test (don't expect much!) script, and yes, generated on chronograf directly.
Sure, that would help!
This is my chronograf generated tick script (in our environments use custom ones). But, for this test, it works just fine:
var db = 'telegraf'
var rp = 'autogen'
var measurement = 'cpu'
var groupBy = ['host']
var whereFilter = lambda: TRUE
var name = 'use cpu'
var idVar = name + ':{{.Group}}'
var message = ' {{.ID}} {{.Name}} {{.TaskName}} {{.Group}} {{ index .Fields "value" }}'
var idTag = 'alertID'
var levelTag = 'level'
var messageField = 'message'
var durationField = 'duration'
var outputDB = 'chronograf'
var outputRP = 'autogen'
var outputMeasurement = 'alerts'
var triggerType = 'threshold'
var details = 'Valor {{ index .Fields "value" }}'
var crit = 20
var data = stream
|from()
.database(db)
.retentionPolicy(rp)
.measurement(measurement)
.groupBy(groupBy)
.where(whereFilter)
|eval(lambda: "usage_user")
.as('value')
var trigger = data
|alert()
.crit(lambda: "value" > crit)
.message(message)
.id(idVar)
.idTag(idTag)
.levelTag(levelTag)
.messageField(messageField)
.durationField(durationField)
.details(details)
.post()
.endpoint('ejemplo')
trigger
|eval(lambda: float("value"))
.as('value')
.keep()
|influxDBOut()
.create()
.database(outputDB)
.retentionPolicy(outputRP)
.measurement(outputMeasurement)
.tag('alertName', name)
.tag('triggerType', triggerType)
trigger
|httpOut('output')
Thank you very much for the example.
so far everything is at its place, but I am getting an error when running kapacitor with config file.
Command
kapacitord.exe -config "C:\kapacitor-1.5.0_windows_amd64\kapacitor-1.5.0-1\kapacitor.conf"
Error:
create server: invalid configuration: httppost: must use an absolute path for alert-template-file.
I tried configuring different paths for alert-template-file.
not sure why I was reluctant to use this on windows but below path worked
"/temp/template/post.html"
Hi,
I will try to explain my trial on defining a post to an endpoint on my script, with custom json using an alert-template-file.
First, we'll need to edit the kapacitor config (.../kapacitor/kapacitor.conf) to configure the endpoint, url, headers and the path to the template:
[[httpPost]]
endpoint = "test" -> We will need to pass this on the tick like .post().endpoint('test')
url = "www.test.com" -> URL to post our templated json. Obviously, the one needed!
headers = { Content-Type = "application/json; charset=UTF-8" }
basic-auth = { username = "", password = "" }
alert-template-file = "/path/to/template"Second, lets define the template. We use tmpl for testing and works fine. The template looks like:
{
"id": "{{.ID}}",
"message": "{{.Message}}",
"details": "{{.Details}}",
"time": "{{.Time}}",
"duration": "{{ .Duration}}",
"level": "{{.Level}}",
"recoverable": {{.Recoverable}},
"data": {{ .Data }}
}Last, we need to fire from our tick script. As stated above, the only need to configure on the tick is on the alert make:
.post()
.endpoint('test')With all this done, the results look like:
POST / HTTP/1.1
Host: 192.168.1.40:9999
User-Agent: Go-http-client/1.1
Content-Length: 447
Content-Type: application/json; charset=UTF-8
Accept-Encoding: gzip{
"id": "use cpu:host=amondelo", "message": " use cpu:host=amondelo cpu chronograf-v1-1742046d-72f3-4c2e-a4f5-4273ce2ddae3 host=amondelo 2.5", "details": "Valor 2.5", "time": "2018-10-26 07:56:49 +0000 UTC", "duration": "10s", "level": "CRITICAL", "recoverable": "true", "data": {"series":[{"name":"cpu","tags":{"cpu":"cpu0","host":"amondelo"},"columns":["time","value"],"values":[["2018-10-26T07:56:49Z",2.5]]}]}}
Hope this can help others (like me...) trying to use this useful way to send alerts to other systems!
Hi, Does it work?
Does this work the same with row-templates?
@ednjv I have only tried with alert-template-file
@arturo-mondelo any idea on https://github.com/influxdata/kapacitor/pull/1572
Most helpful comment
Hi,
I will try to explain my trial on defining a post to an endpoint on my script, with custom json using an alert-template-file.
First, we'll need to edit the kapacitor config (.../kapacitor/kapacitor.conf) to configure the endpoint, url, headers and the path to the template:
[[httpPost]]
endpoint = "test" -> We will need to pass this on the tick like .post().endpoint('test')
url = "www.test.com" -> URL to post our templated json. Obviously, the one needed!
headers = { Content-Type = "application/json; charset=UTF-8" }
basic-auth = { username = "", password = "" }
alert-template-file = "/path/to/template"
Second, lets define the template. We use tmpl for testing and works fine. The template looks like:
{
"id": "{{.ID}}",
"message": "{{.Message}}",
"details": "{{.Details}}",
"time": "{{.Time}}",
"duration": "{{ .Duration}}",
"level": "{{.Level}}",
"recoverable": {{.Recoverable}},
"data": {{ .Data }}
}
Last, we need to fire from our tick script. As stated above, the only need to configure on the tick is on the alert make:
.post()
.endpoint('test')
With all this done, the results look like:
POST / HTTP/1.1
Host: 192.168.1.40:9999
User-Agent: Go-http-client/1.1
Content-Length: 447
Content-Type: application/json; charset=UTF-8
Accept-Encoding: gzip
{
}
Hope this can help others (like me...) trying to use this useful way to send alerts to other systems!