11 KiB
title, sidebar_position
| title | sidebar_position |
|---|---|
| Activation Events | 4 |
Activation Events
Activation events control when your extension is loaded and activated. Extensions should specify activation events to ensure they're only loaded when needed, improving Superset's startup performance.
Overview
Extensions are activated lazily - they're loaded only when certain conditions are met. This is controlled by the activationEvents field in your extension.json:
{
"activationEvents": [
"onCommand:myExtension.start",
"onView:sqllab.panels",
"onLanguage:sql"
]
}
Activation Event Types
onCommand
Activated when a specific command is invoked:
"activationEvents": [
"onCommand:myExtension.analyze",
"onCommand:myExtension.export"
]
The extension activates when any of its commands are executed, either through:
- Command palette
- Menu items
- Keyboard shortcuts
- API calls
onView
Activated when a specific view becomes visible:
"activationEvents": [
"onView:sqllab.panels",
"onView:dashboard.widgets"
]
Available Views:
sqllab.panels- SQL Lab side panelssqllab.bottomPanels- SQL Lab bottom panels
TODO: Future Views:
dashboard.widgets- Dashboard widget areaschart.toolbar- Chart toolbar viewsexplore.panels- Explore view panels
onLanguage
Activated when a file of a specific language is opened:
"activationEvents": [
"onLanguage:sql",
"onLanguage:python"
]
Useful for extensions that provide:
- Language-specific features
- Syntax highlighting
- Code completion
- Linting
workspaceContains
Activated when the workspace contains files matching a pattern:
"activationEvents": [
"workspaceContains:**/*.sql",
"workspaceContains:**/.supersetrc",
"workspaceContains:**/superset_config.py"
]
Uses glob patterns to detect:
- Configuration files
- Project types
- Specific file structures
onStartupFinished
Activated after Superset has fully started:
"activationEvents": [
"onStartupFinished"
]
Use for extensions that:
- Don't need immediate activation
- Provide background services
- Monitor system events
Star Activation (*)
Always activate (not recommended):
"activationEvents": ["*"]
⚠️ Warning: This impacts startup performance. Only use when absolutely necessary.
Extension Lifecycle
1. Registration
When Superset starts or an extension is installed:
// Extension is registered but not loaded
{
id: 'myExtension',
state: 'unloaded',
activationEvents: ['onCommand:myExtension.start']
}
2. Activation Trigger
When an activation event occurs:
// Event triggered
eventBus.emit('command:myExtension.start');
// Extension manager checks activation events
if (extension.activationEvents.includes('onCommand:myExtension.start')) {
activateExtension(extensionId);
}
3. Loading
Extension assets are loaded:
async function loadExtension(extensionId: string) {
// Load frontend assets
await loadRemoteEntry(extension.remoteEntry);
// Load backend modules (if applicable)
await loadBackendModules(extension.backendModules);
return extension;
}
4. Activation
The activate function is called:
export async function activate(context: ExtensionContext) {
console.log('Extension activating');
// Register contributions
const view = context.registerView(...);
const command = context.registerCommand(...);
// Store disposables for cleanup
context.subscriptions.push(view, command);
// Perform initialization
await initialize();
console.log('Extension activated');
}
5. Active State
Extension is fully operational:
{
id: 'myExtension',
state: 'activated',
exports: { /* exposed APIs */ }
}
6. Deactivation
When extension is disabled or Superset shuts down:
export async function deactivate() {
console.log('Extension deactivating');
// Cleanup resources
await cleanup();
// Subscriptions are automatically disposed
console.log('Extension deactivated');
}
Activation Strategies
Lazy Activation (Recommended)
Activate only when needed:
{
"activationEvents": [
"onCommand:myExtension.start",
"onView:myExtension.panel"
]
}
Benefits:
- ✅ Fast startup
- ✅ Lower memory usage
- ✅ Better performance
Eager Activation
Activate on startup for critical features:
{
"activationEvents": [
"onStartupFinished"
]
}
Use cases:
- Authentication providers
- Security extensions
- Core infrastructure
Conditional Activation
Activate based on workspace:
{
"activationEvents": [
"workspaceContains:**/superset_config.py",
"workspaceContains:**/*.sql"
]
}
Benefits:
- Context-aware activation
- Project-specific features
- Automatic detection
Multiple Activation Events
Extensions can specify multiple events (OR logic):
{
"activationEvents": [
"onCommand:myExtension.start",
"onCommand:myExtension.configure",
"onView:sqllab.panels",
"onLanguage:sql",
"workspaceContains:**/*.myext"
]
}
The extension activates when any event occurs.
Performance Considerations
Do's ✅
- Use specific activation events
"activationEvents": ["onCommand:myExtension.specific"]
- Defer heavy initialization
export async function activate(context) {
// Quick registration
context.registerCommand('myExtension.heavy', async () => {
// Heavy work only when command is used
await doHeavyWork();
});
}
- Load resources on demand
let heavyModule;
export async function activate(context) {
context.registerCommand('myExtension.feature', async () => {
// Lazy load when needed
heavyModule = heavyModule || await import('./heavy');
heavyModule.execute();
});
}
Don'ts ❌
- Avoid star activation
// Bad - activates always
"activationEvents": ["*"]
- Don't block activation
// Bad - blocks activation
export async function activate(context) {
await longRunningOperation(); // Blocks
}
// Good - defer work
export async function activate(context) {
setImmediate(() => longRunningOperation());
}
- Avoid unnecessary events
// Bad - too many events
"activationEvents": [
"onStartupFinished",
"onCommand:*",
"onView:*"
]
Testing Activation Events
Manual Testing
- Check activation timing:
export async function activate(context) {
console.time('activation');
// ... activation code
console.timeEnd('activation');
}
- Verify event triggers:
// In browser console
superset.extensions.getExtension('myExtension').state
// Should be 'unloaded' before event
// Trigger event
superset.commands.executeCommand('myExtension.start');
// Check again
superset.extensions.getExtension('myExtension').state
// Should be 'activated' after event
Automated Testing
describe('Extension Activation', () => {
it('should activate on command', async () => {
const extension = await loadExtension('myExtension');
expect(extension.state).toBe('unloaded');
await commands.executeCommand('myExtension.start');
expect(extension.state).toBe('activated');
});
it('should not activate on unrelated event', async () => {
const extension = await loadExtension('myExtension');
await commands.executeCommand('unrelated.command');
expect(extension.state).toBe('unloaded');
});
});
Debugging Activation
Enable Debug Logging
// In extension
const DEBUG = true;
export async function activate(context) {
if (DEBUG) {
console.log('[MyExtension] Activating', {
extensionId: context.extensionId,
timestamp: new Date().toISOString()
});
}
}
Monitor Activation Events
// In browser console
superset.events.on('extension:activating', (e) => {
console.log('Extension activating:', e.extensionId);
});
superset.events.on('extension:activated', (e) => {
console.log('Extension activated:', e.extensionId);
});
Common Issues
Extension not activating:
- Check activation events are correct
- Verify event is being triggered
- Check browser console for errors
- Ensure extension is enabled
Extension activating too early:
- Review activation events
- Consider using more specific events
- Check for star activation
Extension activating multiple times:
- Check for duplicate event registrations
- Verify deactivation cleanup
- Review activation logic
Best Practices
- Choose minimal activation events - Only what's necessary
- Defer expensive operations - Don't block activation
- Use specific events - Avoid broad patterns
- Test activation timing - Ensure good performance
- Document activation requirements - Help users understand
- Handle activation failures - Graceful error handling
- Clean up on deactivation - Prevent memory leaks
- Log activation in debug mode - Aid troubleshooting
- Consider user experience - Balance performance and features
- Version activation events - Plan for changes
Future Activation Events
These activation events are planned for future releases:
onUri- Custom URI schemesonWebviewPanel- Webview visibilityonFileSystem- File system providersonDebug- Debug sessionsonTaskType- Task providersonNotebook- Notebook documentsonAuthentication- Auth providersonCustomEditor- Custom editorsonTerminalProfile- Terminal profiles
Migration Guide
From Always Active to Lazy
Before (always active):
{
"activationEvents": ["*"]
}
After (lazy activation):
{
"activationEvents": [
"onCommand:myExtension.command1",
"onCommand:myExtension.command2",
"onView:myExtension.view"
]
}
Adding New Activation Events
When adding features:
{
"version": "1.0.0",
"activationEvents": [
"onCommand:myExtension.oldCommand"
]
}
// Version 1.1.0 - Added new feature
{
"version": "1.1.0",
"activationEvents": [
"onCommand:myExtension.oldCommand",
"onCommand:myExtension.newCommand", // New
"onView:myExtension.panel" // New
]
}