Any lua is computationally expensive relative to C++, so it'll depend on how often you call it - once per player per turn is not going to kill the system. Just make sure that if the specific civ isn't in play not to hook the event(s).
"Tenuous best" - loop all players, call an api to get a number of text strings, loop strings checking for non-empty ones and count them ... when there's a C++ method that does it for you. Not what I'd call "best"!
V76 of my DLL (not out yet) exposes that method to the Lua API
If you want to know when a caravan passes through a city, use the UnitSetXY event handler, check for the plot being a city, check for the unit being a caravan, if both true, do something. Again, make sure you only hook the event if the civ is in play as UnitSetXY can get called many hundreds of times per turn mid to late game.
If you want to add gold for worked improvements, you can loop all the city plots at the start of the civ players turn, check if it's worked, check for the improvement, and just add gold to the treasury - there'd be no tooltip info, but that may or may not be a big deal - you could always send a notification "You received X gold from taxes on trading-posts"