It does have the overhead of requiring an action to do the tracking, unless the tracking is primarily performed by the existing actions that do the installs and uninstalls.
In my tests the client log parsing is less than 1 second. Not super fast, but not slow either.
You can actually slow down the reevaluation of applicability relevance to make it lighter weight by using the x-relevance-evaluation-period
which is probably a good idea for this use case anyway. You can basically have it only evaluate if the software should be uninstalled once every X hours instead of every evaluation loop, and in a way, this is also part of what you are trying to achieve. (that said, I’m not 100% sure how the applicability relevance evaluation is handled once it is an action and no longer just the fixlet)
See this example: bigfix-content/fixlet/Test Fixlet Evaluation-Period.bes at main · jgstew/bigfix-content · GitHub
That is a challenge for any approach I think.
You would need to use local users of active directories
since you are no longer concerned with the currently logged on user, but the recent logged on users compared to the active directory cached users.
Something I’m noticing is that names of local users of active directories
is only giving me 1 result despite the fact that I see many AD users cached here: C:\Program Files (x86)\BigFix Enterprise\BES Client\__BESData\__Global\ADCache
Ideally, this relevance:
names of local users of active directories
would match the output of this relevance:
node values of xpaths "/User/Name/text()" of xml documents of files whose(name of it starts with "ADObjectUser_" AND name of it as lowercase ends with ".xml") of folders "__Global\ADCache" of data folders of clients
but at least in my case, it does not.
This will give the names of the cached AD users that have login records in the bigfix client logs:
elements of intersections of ( sets of node values of xpaths "/User/Name/text()" of xml documents of files whose(name of it starts with "ADObjectUser_" AND name of it as lowercase ends with ".xml") of folders "__Global\ADCache" of data folders of clients ; sets of unique values of (preceding text of first "'" of it | it) of following texts of firsts "User interface process started for user '" of locked lines containing "User interface process started for user '" of files whose(12=length of name of it AND name of it as lowercase ends with ".log") of folders "Logs" of folders "__Global" of data folders of client )
Also, I’m noticing this relevance is much faster when run from the client than through QnA in terms of reported execution time. (like 100x faster)
It would potentially be even more efficient to rely on the last modified time of the AD user cache data as a proxy for last login, but I don’t know if that is always going to be accurate, plus then you can’t also filter based upon number of logins, which I could with the relevance above.
This returns all of the AD groups of all of the cached AD users with logins recorded in the BigFix Client Logs:
unique values of node values of xpaths "/User/Groups/Group/Name/text()" of items 1 of (intersections of ( sets of node values of xpaths "/User/Name/text()" of xml documents of files whose(name of it starts with "ADObjectUser_" AND name of it as lowercase ends with ".xml") of folders "__Global\ADCache" of data folders of clients ; sets of unique values of (preceding text of first "'" of it | it) of following texts of firsts "User interface process started for user '" of locked lines containing "User interface process started for user '" of files whose(12=length of name of it AND name of it as lowercase ends with ".log") of folders "Logs" of folders "__Global" of data folders of client ), xml documents of files whose(name of it starts with "ADObjectUser_" AND name of it as lowercase ends with ".xml") of folders "__Global\ADCache" of data folders of clients) whose( exists (elements of item 0 of it, node values of xpaths "/User/Name/text()" of item 1 of it) whose(item 0 of it = item 1 of it) )
Then, putting it all together:
elements of intersections of ( it; sets of ("AD_GROUP_A";"AD_GROUP_B") ) of sets of node values of xpaths "/User/Groups/Group/Name/text()" of items 1 of (intersections of ( sets of node values of xpaths "/User/Name/text()" of xml documents of files whose(name of it starts with "ADObjectUser_" AND name of it as lowercase ends with ".xml") of folders "__Global\ADCache" of data folders of clients ; sets of unique values of (preceding text of first "'" of it | it) of following texts of firsts "User interface process started for user '" of locked lines containing "User interface process started for user '" of files whose(12=length of name of it AND name of it as lowercase ends with ".log") of folders "Logs" of folders "__Global" of data folders of client ), xml documents of files whose(name of it starts with "ADObjectUser_" AND name of it as lowercase ends with ".xml") of folders "__Global\ADCache" of data folders of clients) whose( exists (elements of item 0 of it, node values of xpaths "/User/Name/text()" of item 1 of it) whose(item 0 of it = item 1 of it) )
QnA reports that this takes about 200ms while when done through client eval, it reports less than 1ms of evaluation time. I did write this to be fairly efficient, but not sure why it is that fast honestly. My test system has 31 client logs, but they are rather small. I am only parsing the client logs once in the relevance though, so much larger log files should not have a massive impact on this. This relevance does read the AD User Cache XML twice, which might be able to be reduced to once with some effort. The relevance is also written to minimize “tuple expansion” by having at least one side be a single set.