Files
superset2/docs/developer_portal/references/activation-events.md

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 panels
  • sqllab.bottomPanels - SQL Lab bottom panels

TODO: Future Views:

  • dashboard.widgets - Dashboard widget areas
  • chart.toolbar - Chart toolbar views
  • explore.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

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

  1. Use specific activation events
"activationEvents": ["onCommand:myExtension.specific"]
  1. Defer heavy initialization
export async function activate(context) {
  // Quick registration
  context.registerCommand('myExtension.heavy', async () => {
    // Heavy work only when command is used
    await doHeavyWork();
  });
}
  1. 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

  1. Avoid star activation
// Bad - activates always
"activationEvents": ["*"]
  1. 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());
}
  1. Avoid unnecessary events
// Bad - too many events
"activationEvents": [
  "onStartupFinished",
  "onCommand:*",
  "onView:*"
]

Testing Activation Events

Manual Testing

  1. Check activation timing:
export async function activate(context) {
  console.time('activation');
  // ... activation code
  console.timeEnd('activation');
}
  1. 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

  1. Choose minimal activation events - Only what's necessary
  2. Defer expensive operations - Don't block activation
  3. Use specific events - Avoid broad patterns
  4. Test activation timing - Ensure good performance
  5. Document activation requirements - Help users understand
  6. Handle activation failures - Graceful error handling
  7. Clean up on deactivation - Prevent memory leaks
  8. Log activation in debug mode - Aid troubleshooting
  9. Consider user experience - Balance performance and features
  10. Version activation events - Plan for changes

Future Activation Events

These activation events are planned for future releases:

  • onUri - Custom URI schemes
  • onWebviewPanel - Webview visibility
  • onFileSystem - File system providers
  • onDebug - Debug sessions
  • onTaskType - Task providers
  • onNotebook - Notebook documents
  • onAuthentication - Auth providers
  • onCustomEditor - Custom editors
  • onTerminalProfile - 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
  ]
}