That what I ended up doing. Custom, and does affect all the logic, but is getting me what I'm looking for so far.
Just to recap here for other's reference:
Regarding actions, I created a middleware to store some logging information:
preProcessor: function(data, next) {
data.log = api.utils.objClone(data.params);
data.log.clientId = data.connection.username;
data.log.reqId = api.uuid.v4();
next();
}
Then my functions have an options object passed to them as the last argument (or before the callback). Something like this in the action:
api.sessions.subscribeSession( data.params.sessionCode, { logMeta: data.log } )
Inside the initializers/middleware, I call the logs (especially any errors) with:
api.log('Words to log', level, options.logMeta );
My console logs look something like this:
2016-05-18T14:05:25.056Z - info: Get a session. sessionCode=crya accountId=1, sessionCode=crya, action=stopSession, apiVersion=1, clientId=user12, reqId=b630d2b5-a8cd-439b-bdc7-3597cbcd4c13
And Winston says that metadata is tailored for each transport.
Now with a logging service (or even `grep`!), if I see an error I can search the logs for the username to see what they were doing all alone. Or the requestId to know what chain of events blew things up. Or for more analysis, I could filter on the "sessionCode" parameter that all the clients were using for that session to get a more complete picture for that session.
It took a little groundwork, but so far so good : )