I'm trying to track the duration of user sessions to a server. I want to know WHICH users are connecting, and for how long each session is. The problem is, with multiple users, I'm having nested transactions happen , where USER001 joins, but USER004 Leaves, and that creates an event. I want it to ONLY look at only scenarios in which the same user that Joins, Leaves. I can't seem to get it to do this.
Eventcode=44 is the event code for these particular events I want to track
UserXXID is a Field Extraction I've built to show each userID, as it is not a standard username that Splunk automatically understood.
The two primary types of logs I'm looking for is when they've "joined" or "left" the event.
Here is the command I'm using -
host="XXComputer04" EventCode=44 | transaction startswith="joined" endswith="left"
|eval Hours=duration/3600
|timechart count by UserXXID
Sample of the log entry I'm trying to parse.
LogName=Application
EventCode=120
EventType=44
ComputerName=XXcomputer004
SourceName=EventXService
Type=Information RecordNumber=1234427
Keywords=Classic
TaskCategory=State Transition
OpCode=Info
Message= [0x0x]::ProcessLeave() (xxUSER002xx) left event33001
---------
I have also tried simply - |transaction USERXXID to keep unique userID's together - and while that works, it then somehow ignores ALL "left event" messages and only shows "joined" for any given user.
Any help would be appreciated!
Thank you for the quick response! This looks like a great solution - however the reason I was using transaction is because we have new users all the time and I can't pre-add every possible username. I know people say that transaction is awful but for the life of me I've never had a single problem using it.
Hi @Crabbok
You shouldnt need to specify a hard-coded list of users, that was just me creating some test data. Assuming the Message field is available to run the regex you should just be able to do:
| rex field=Message "has (?<action>[a-zA-Z]+) the event session"
| eval {action}_time=_time
| sort UserXXID
| streamstats count as userEventNum min(joined_time) as session_joined_time, max(left_time) as session_left_time by UserXXID reset_after="action=\"left\""
| eval action_time=strptime(_time, "%Y-%m-%d %H:%M:%S")
| stats range(action_time) as sessionDurationSeconds, values(action) as actions, max(_time) as session_left_time by UserXXID session_joined_time
If UserXXID is not a field then you can use rex to get this too.
If you want to stick to using transactions, try adding *keepevicted=true* to your transaction command as I think this might keep the non-completed transaction events.
🌟 Did this answer help you? If so, please consider:
Your feedback encourages the volunteers in this community to continue contributing
Hi @Crabbok
Check out the following - I think this should solve your usecase here, note that I have avoided transaction because its a pretty terrible command to use - I'd only recommend it if you absolutely have to! Instead we can leverage stats.
Ive applied some further logic here to split events into individual sessions, so that if a user joins and leaves multiple times in the search window then it will show multiple sessions - see the example below:
The full SPL for this for you to try is:
| makeresults format=csv data="Message,UserXXID,_time
Info: User USER001 has joined the event session.,USER001,2025-05-06 22:20:03
Info: User USER002 has joined the event session.,USER002,2025-05-06 22:21:43
Info: User USER001 has left the event session.,USER001,2025-05-06 22:36:43
Info: User USER003 has joined the event session.,USER003,2025-05-06 22:40:03
Info: User USER002 has left the event session.,USER002,2025-05-06 22:53:23
Info: User USER003 has left the event session.,USER003,2025-05-06 23:01:43
Info: User USER001 has joined the event session.,USER001,2025-05-06 23:18:23"
| rex field=Message "has (?<action>[a-zA-Z]+) the event session"
| eval {action}_time=_time
| sort UserXXID
| streamstats count as userEventNum min(joined_time) as session_joined_time, max(left_time) as session_left_time by UserXXID reset_after="action=\"left\""
| eval action_time=strptime(_time, "%Y-%m-%d %H:%M:%S")
| stats range(action_time) as sessionDurationSeconds, values(action) as actions, max(_time) as session_left_time by UserXXID session_joined_time
🌟 Did this answer help you? If so, please consider:
Your feedback encourages the volunteers in this community to continue contributing