2

I have a JMS feed that provides messages with the following JSON structure:

{ String:currentSessions, Long:duration, Long:rows, Long:fill, Long:execute, String:source, String:category, String:url, String:hostname }

What I would like to do is a define a stream similar to the following that would provide a moving average by hostname via a rich-gauge:

stream create duration_gauge --definition "tap:stream:interceptor > object-to-json | transform --expression=#jsonPath(payload,'$.duration') | rich-gauge --nameExpression=#jsonPath(payload,'$.hostname')" --deploy

Obviously, this does not work as the payload has already been transformed and no longer includes the hostname field.

Questions:

  1. Is there a way to save part of the payload between pipes? I've read about custom headers, but I don't see a documented way to create and access them.
  2. It seems that the only way to accomplish I would like to do is create a stream/rich-gauge per hostname. Is that the best solution?

Thanks!

delewis
  • 131
  • 1
  • 8

1 Answers1

2

I think this case should be easier. We should add --valueExpression to rich-gauge. Meanwhile, you could go with either of the two alternatives you suggest. (2) does not require any customization and should be simple if there are only a few known hosts and not likely to change often. To implement (1) you can create a custom processor module to implement a Spring Integration header-enricher and install it into the custom-modules directory. In this case I think it is simpler to use a groovy script, something like:

import groovy.json.JsonSlurper
import org.springframework.messaging.support.MessageBuilder

def slurper = new JsonSlurper()
def json = slurper.parseText(payload)
def enriched = [:]
enriched.putAll(headers)
enriched['hostName'] = json.hostName
return MessageBuilder.withPayload(payload).copyHeaders(enriched).build()

and save it as [XD_INSTALL_DIR]/xd/modules/processor/scripts/headerEnricher.groovy. (NOTE that payload and headers variables are automatically bound to the message contents). Next create and deploy a stream. I used this to test:

xd:> stream create test --definition "http | enrich:transform --script=headerEnricher.groovy | extract:transform --expression=#jsonPath(payload,'$.duration') |  rich-gauge --nameExpression=headers['hostName']" --deploy

and post some data:

xd:>http post --target http://localhost:9000 --data {"hostName":"someHost","duration":2.90}
xd:>http post --target http://localhost:9000 --data {"hostName":"someHost","duration":1.50}
xd:>http post --target http://localhost:9000 --data {"hostName":"anotherHost","duration":1.33}
xd:>http post --target http://localhost:9000 --data {"hostName":"anotherHost","duration":2.345}

Display the results:

 xd:>rich-gauge display someHost
 xd:>rich-gauge display anotherHost
dturanski
  • 1,723
  • 1
  • 13
  • 8
  • This is a much better answer than I expected. Thanks for your help and submitting the JIRA request on my behalf. We'll look at implementing the header-enricher, as we have a large number of hostnames that submit data. Marking this as the answer. – delewis May 08 '15 at 14:21