If I understand the question correctly, you have a group of actors, some locations, and two cancelling acts. You want to capture the events in which the act is not cancelled out by a subsequent act. The concept is eventstats. To apply it, I want to differentiate between the actual application and the algorithm somewhat. In the application you described, if users are real persons (who cannot be in two rooms at the same time), all you need to do is to count whether actions against a room is even or odd. But if I just wanted to answer the question as you described: whether a user entered a room and hasn't exited. Assuming each event contains three fields, room, action, and userID, where action enumerates into "Exit" or "Go to". This is a proof of concept: | eventstats count latest(_time) as lastact by room action userID
| eval exitcount = if(action == "Exit", count, 0), gotocount = if(action != "Exit", count, 0)
| where gotocount > exitcount AND _time == lastact
| fields - count, exitcount, gotocount, lastact To test this, I use the following to generate an event sequence. | makeresults count=30
| streamstats count
| eval _time = now() + count * 30, userID = 120 + random() % 3, action = if(count % 2 == 0, "Exit", "Go to"), room = 23 + (random() % 4)
| fields - count Sample vents can look like _time action room userID 2021-05-22 01:31:07 Go to 23 122 2021-05-22 01:31:37 Exit 23 122 2021-05-22 01:32:07 Go to 23 120 2021-05-22 01:32:37 Exit 24 122 2021-05-22 01:33:07 Go to 23 120 2021-05-22 01:33:37 Exit 23 120 2021-05-22 01:34:07 Go to 23 122 2021-05-22 01:34:37 Exit 25 122 2021-05-22 01:35:07 Go to 26 121 (Obviously because I'm assigning actions randomly, data will look like a bunch of drunk ghosts.) If I put the event generator and the PoC code together, | makeresults count=30
| streamstats count
| eval _time = now() + count * 30, userID = 120 + random() % 3, action = if(count % 2 == 0, "Exit", "Go to"), room = 23 + (random() % 4)
| fields - count
| eventstats count latest(_time) as lastact by room action userID
| eval exitcount = if(action == "Exit", count, 0), gotocount = if(action != "Exit", count, 0)
| where gotocount > exitcount AND _time == lastact
| fields - count, exitcount, gotocount, lastact it will capture the unbalanced last act: _time action userID room 2021-05-22 00:52:50 Go to 25 122 2021-05-22 00:54:50 Go to 23 120 2021-05-22 00:56:50 Go to 25 121 2021-05-22 00:59:50 Go to 24 120 2021-05-22 01:00:50 Go to 26 121 2021-05-22 01:02:50 Go to 25 120 2021-05-22 01:03:50 Go to 23 121 2021-05-22 01:04:50 Go to 26 120 2021-05-22 01:05:50 Go to 24 121 (Because the generator is random, these results are not based on the sample given above.) Cancelling acts are probably not what you are really after. But I think you can use eventstats to do the math you needed.
... View more