Bug: Logger not propagated to child machines from root
XState version
XState version 5
Description
In v4, when passing a custom logger to the machine options, the child machines also used to use the same logger.
In v5, they just use the default logger console.log
Expected result
Expected the log function in a child machine to use the custom logger defined in the root machine from the interpreter options
Actual result
The child machines log using the default log function
Reproduction
https://codesandbox.io/p/sandbox/logging-not-propagated-tn93jf
Additional context
No response
We should "inherit" it:
Alternatively, we could try to "inherit" it through the system.
Inheriting through the system would be super nice. Right now we have extended the logger to pass the systemId as the category. We intercept this directly on the root and forward it to our third party log service
import { AnyActorRef, enqueueActions, log as xstateLog } from 'xstate5'
export const log: typeof xstateLog = (logExp) =>
enqueueActions(({ enqueue, self }) => {
const systemId = (self as AnyActorRef & { _systemId: string })._systemId
return enqueue(
xstateLog((args) => {
// We can't pass params to the log function as they don't work with enqueue actions
if (typeof logExp === 'function') return logExp(args, {} as any)
return logExp
}, systemId),
)
})
This function sadly doesn't accept parameters but we always use logging inline in the machine anyway so not a problem
spawn() and spawnChild() seem like they should allow a logger option, yes? Maybe other options available on createActor()?
I'm just trying to use debug in place of the default logger. It works for the machine I created with createActor(), but not for any spawned machine.
My terrible hack for this:
import Debug from 'debug';
// ...stuff...
assign({
actorRef: (({spawn}) => {
const actorRef = spawn('someActor', {
id: 'someId',
// logger: Debug('someActor') <-- plz 😄
});
// @ts-expect-error
actorRef.logger = actorRef._actorScope.logger = Debug('someActor');
return actorRef;
})
})
Above, I'd rather use invoke. But invoke doesn't allow a logger option either, and I can't figure out how to get at the ActorRef to mutilate it. 😄
w/r/t
xstateinternals: would it make sense for _actorScope.logger to be a getter?