Skip to content

Commit 6993c7e

Browse files
authored
[XState] Enable XState inspector conditionally (#237503)
## 📓 Summary This PR addresses the issue of noisy XState console logging in development mode by introducing runtime toggling functionality. Previously, the XState inspector logged all state machine events directly to the console, which interfered with debugging other application features. https://github.com/user-attachments/assets/1412afef-2eae-4329-aabd-0c877f54cd9b ## 🎯 Problem As discussed in [the team thread](https://elastic.slack.com/archives/C081J8HAZ50/p1757590000481899), the XState console inspector was always active in dev mode, causing excessive console noise. The original implementation used: ```typescript const log = console.info.bind(console); ``` This meant all XState state machine events, transitions, and snapshots were logged unconditionally, making it difficult for developers to debug non-XState-related issues when the console was cluttered with state machine information. **Context from discussion:** - XState v5 no longer supports the Redux DevTools extension, requiring a custom observable inspector - The console inspector was created as a replacement, but lacked conditional control - Developers needed a way to enable/disable logging without code changes - Browser-side toggling was preferred over environment variables (which are harder to forward to the browser) ## 🔧 Solution & Usage **To enable XState logging:** 1. Open your browser's DevTools console 2. Run: `toggleXstateInspector()` 3. You'll see: `ℹ️ XState inspector enabled` 4. All XState events will now be logged to the console **To disable XState logging:** 1. Run `toggleXstateInspector()` again 2. You'll see: `ℹ️ XState inspector disabled` 3. Console logging stops immediately **On page load:** - You'll see a one-time help message: `ℹ️ To toggle the XState inspector, for advanced debugging, run toggleXstateInspector() on your browser console.` - XState logging is **disabled by default** - The console remains clean unless you explicitly enable it ## 💡 Technical Notes - **Opt-in by default:** Logging is disabled on initialization, keeping the console clean - **Dev mode only:** The inspector is only available when `isDevMode()` returns `true` - **Persistence:** The toggle state is persisted across page reloads - **No code changes needed:** Developers can enable/disable logging at runtime without modifying source code or rebuilding
1 parent a77afb9 commit 6993c7e

File tree

1 file changed

+40
-2
lines changed

1 file changed

+40
-2
lines changed

src/platform/packages/shared/kbn-xstate-utils/src/console_inspector.ts

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
* License v3.0 only", or the "Server Side Public License, v 1".
88
*/
99

10+
/* eslint-disable no-console */
11+
12+
/* eslint-disable no-var */
13+
1014
import type {
1115
ActorRefLike,
1216
AnyActorRef,
@@ -17,13 +21,47 @@ import type {
1721
} from 'xstate5';
1822
import { isDevMode } from './dev_tools';
1923

24+
declare global {
25+
var __XSTATE_LOGGER_ENABLED__: boolean;
26+
var toggleXstateInspector: () => void;
27+
}
28+
29+
let isHelpMessageLogged = false;
30+
const setupDevToolsInspector = () => {
31+
if (!isHelpMessageLogged) {
32+
console.info(
33+
`ℹ️ To toggle the XState inspector, for advanced debugging, run toggleXstateInspector() on your browser console.`
34+
);
35+
isHelpMessageLogged = true;
36+
37+
const isEnabled = localStorage.getItem('__XSTATE_LOGGER_ENABLED__') === 'true';
38+
39+
globalThis.__XSTATE_LOGGER_ENABLED__ = isEnabled;
40+
globalThis.toggleXstateInspector = toggleXstateInspector;
41+
}
42+
};
43+
44+
const toggleXstateInspector = () => {
45+
globalThis.__XSTATE_LOGGER_ENABLED__ = !globalThis.__XSTATE_LOGGER_ENABLED__;
46+
localStorage.setItem(
47+
'__XSTATE_LOGGER_ENABLED__',
48+
globalThis.__XSTATE_LOGGER_ENABLED__.toString()
49+
);
50+
51+
console.info(
52+
`ℹ️ XState inspector ${globalThis.__XSTATE_LOGGER_ENABLED__ ? 'enabled' : 'disabled'}`
53+
);
54+
};
55+
2056
export const createConsoleInspector = () => {
2157
if (!isDevMode()) {
2258
return () => {};
2359
}
2460

25-
// eslint-disable-next-line no-console
26-
const log = console.info.bind(console);
61+
setupDevToolsInspector();
62+
63+
const log = (...args: Parameters<typeof console.info>) =>
64+
globalThis.__XSTATE_LOGGER_ENABLED__ ? console.info(...args) : undefined;
2765

2866
const logActorEvent = (actorEvent: InspectedActorEvent) => {
2967
if (isActorRef(actorEvent.actorRef)) {

0 commit comments

Comments
 (0)