Β· English Β· Korean
-
π Simple and flexible action logger for Pinia
-
π¦ Includes/excludes/filter actions to log
-
π‘ Supports custom logger and log style
-
π· Store name and timestamp in log title
-
β±οΈ Action duration tracking for performance monitoring
-
π Deep clone support for accurate nested object tracking
-
π‘ Error logging with clear visibility
-
π Store-level logger configuration possible
-
π¨ Visual state change indicators (β /βͺ/β)
-
π§ State transformer for sensitive data masking
$ npm install --save pinia-plugin-loggerimport { createPinia } from "pinia";
import piniaPluginLogger from "pinia-plugin-logger";
const pinia = createPinia();
const logger = piniaPluginLogger({
enabled: true, // Activate the logger
expanded: true, // Expand the console group
showStoreName: true, // Show the store name in the console
showTimestamp: true, // Show the timestamp in the console
showDuration: true, // Show action execution time
showErrors: true, // Show errors in the console
deepClone: false, // Use deep clone for state snapshots
maxDepth: Infinity, // Maximum depth for state logging
includeActions: [], // Only log these actions (if defined)
excludeActions: [], // Exclude these actions from logging
filter: () => true, // Custom filter function
logger: console, // Custom logger object
stateTransformer: undefined, // Transform state before logging
});
pinia.use(logger);
export default pinia;import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state: () => ({
count: 0,
user: {
name: "Guest",
preferences: { theme: "light" }
}
}),
actions: {
increment() {
this.count++;
},
async fetchData() {
// Async action with duration tracking
await fetch('/api/data');
}
},
logger: {
enabled: true,
expanded: false,
showDuration: true,
deepClone: true,
includeActions: ["increment", "fetchData"],
},
});| Option | Type | Default | Description |
|---|---|---|---|
| enabled | boolean | true | Activate the logger plugin |
| expanded | boolean | true | Expand the console group |
| showStoreName | boolean | true | Show the store name in the log title |
| showTimestamp | boolean | true | Show time of action in the log title |
| showDuration | boolean | false | Show action execution time |
| showErrors | boolean | true | Show error logs in the console |
| deepClone | boolean | false | Use deep clone for state snapshots (performance impact) |
| maxDepth | number | Infinity | Maximum depth for state logging |
| includeActions | string[] | [] | Only log actions in this list |
| excludeActions | string[] | [] | Exclude actions in this list |
| filter | function | () => true | Custom filter function for action logging |
| logger | object | console | Custom logger object (log/group support) |
| stateTransformer | (state: any) => any | undefined | Transform state before logging (e.g., mask sensitive data) |
| logLevel | 'debug' | 'info' | 'warn' | 'error' | 'debug' | Log level (for future use) |
// Basic action with state change
action π [counter] increment @15:42:13:123 (2ms) β
prev state { count: 0, history: [] }
action { type: 'increment', store: 'counter', duration: '2ms' }
next state { count: 1, history: [1] }
// Async action with duration tracking
action π [user] fetchUser @15:43:22:212 (1045ms) β
prev state { loading: false, data: null }
action { type: 'fetchUser', args: { id: 1 }, store: 'user', duration: '1045ms' }
next state { loading: false, data: { id: 1, name: 'John' } }
// Action with error
action π [user] fetchUser @15:43:23:221 (523ms) β
prev state { loading: true, data: null }
action { type: 'fetchUser', args: { id: 1 }, store: 'user', duration: '523ms', error: Error: Failed to fetch }
next state { loading: false, data: null }
// Action without state change
action π [settings] validateInput @15:44:10:456 (1ms) βͺ
prev state { valid: true }
action { type: 'validateInput', store: 'settings', duration: '1ms' }
next state { valid: true }
βΉοΈ No state changes- β Green: State changed successfully
- βͺ Gray: No state changes
- β Red: Error occurred
const logger = piniaPluginLogger({
deepClone: true, // Enable deep cloning
maxDepth: 5, // Limit depth to 5 levels
});Benefits: Accurately tracks changes in nested objects, arrays, Maps, and Sets. Trade-off: Slightly slower performance (recommended for development only).
const logger = piniaPluginLogger({
stateTransformer: (state) => {
// Mask sensitive information
if (state.user?.password) {
return {
...state,
user: { ...state.user, password: '***' }
};
}
return state;
}
});const logger = piniaPluginLogger({
// Only in development
enabled: import.meta.env.DEV,
// Only log specific actions
includeActions: ['increment', 'fetchUser'],
// Or exclude specific actions
excludeActions: ['debugAction'],
// Custom filter
filter: (action) => {
// Only log when count > 10
return action.store.$state.count > 10;
}
});const logger = piniaPluginLogger({
showDuration: true,
filter: (action) => {
// Log only slow actions (> 100ms)
const startTime = Date.now();
action.after(() => {
const duration = Date.now() - startTime;
return duration > 100;
});
}
});Check out the example app for a complete demonstration of all features:
cd examples/vue-app
pnpm install
pnpm run devFeatures demonstrated:
- Basic counter with state tracking
- Async actions with duration measurement
- Nested object mutations (deep clone)
- Error handling
- History tracking
Important: Disable the logger in production to avoid performance overhead.
const logger = piniaPluginLogger({
enabled: import.meta.env.DEV, // Only in development
});Or use conditional plugin registration:
const pinia = createPinia();
if (import.meta.env.DEV) {
pinia.use(piniaPluginLogger());
}This plugin comes with full TypeScript support:
import type { PiniaLoggerOptions } from 'pinia-plugin-logger';
const loggerOptions: PiniaLoggerOptions = {
enabled: true,
deepClone: true,
// ... with autocomplete and type checking
};Contributions are always welcome! Please feel free to open an issue or submit a pull request.
Made with β€οΈ by AGUMON π¦
