JOINing multiple streams

The documentation for the JoinNode says “Joins the data from any number of nodes,” but I’m stumped on how to join more than once. Wherever I put the a second join() method, I end up with missing values.

Are there any examples that show how to do this?

We have a measurement that includes values for execution time (duration) and a Boolean on whether it’s an error. We’re successfully creating a totalRecords variable with the total count, and joining that a total errors variable that gets the totalErrors, which we can then use to compute the rate. That works, but we also want to alert on whether the average response time exceeds a value. How would we join that in, too?

var data = stream
        |from()
     		.database(database)
     		.retentionPolicy(retentionPolicy)
     		.measurement('api_detail')
        |where(lambda: "api" == targetApi)
        |window()
     		.period(period)
     		.every(every)
        |log().prefix('initial stream: ').level('DEBUG')
        
// Don't have a way to reference this...        
var totalDuration = data
 		|mean('duration')
 			.as('executionTime')
		|log().prefix('totalDuration: ').level('DEBUG') 			

var totalRecords = data
        |count('duration')
        |log().prefix('totalRecords: ').level('DEBUG')


var totalErrors = data
        |where(lambda: "error" == 'true')
        |log().prefix('totalErrors (pre-count): ').level('DEBUG')
        |count('duration')
        |log().prefix('totalErrors (post-count): ').level('DEBUG')

totalErrors
        |log().prefix('pre-join: ').level('DEBUG')
        |join(totalRecords)
                .fill(0)
                .as('totalErrors','totals')
        |eval(lambda: float("totalErrors.count") / float("totals.count" + 1)  )
                .as('rate')
                .keep()
        |log().prefix('pre-alert: ').level('DEBUG')
        |alert()
                .id('{{ .Name }}')
                .message('Count: {{ index .Fields "totals.count" }}; Errors: {{ index .Fields "totalErrors.count" }} Rate: {{ index .Fields "rate" }} ')
                //.crit(lambda: TRUE)
                .crit(lambda: "rate" > errorPercentage OR "totalErrors.count" > errorAbsolute)
                // Whenever we get an alert write it to a file.
                .log('/tmp/alerts.log')
                .sensu()

If you are trying to join all three total vars do something along these lines:


totalErrors
        |join(totalRecords, totalDurations)
                .as('totalErrors','totals', 'totalDurations')

Thanks. That seems to do the trick.