Claude
Skills
Sign in
Back

sentry-desktop-setup

Included with Lifetime
$97 forever

Configure Sentry for comprehensive desktop application crash reporting, error monitoring, performance tracking, and release health for Electron and native desktop apps

Data & Analyticsdesktopmonitoringcrash-reportingsentryelectronobservability

What this skill does


# sentry-desktop-setup

Configure Sentry for comprehensive desktop application monitoring including crash reporting, error tracking, performance monitoring, and release health. This skill sets up Sentry SDK integration for Electron and native desktop applications with source maps, session tracking, and custom instrumentation.

## Capabilities

- Configure Sentry SDK for Electron (main + renderer processes)
- Set up native crash reporting with minidump support
- Configure source map uploads for readable stack traces
- Implement performance monitoring and tracing
- Set up release tracking with commit integration
- Configure session tracking for release health
- Implement custom error boundaries and handlers
- Set up user feedback collection
- Configure environment-specific DSNs and sampling

## Input Schema

```json
{
  "type": "object",
  "properties": {
    "projectPath": {
      "type": "string",
      "description": "Path to the desktop application project"
    },
    "framework": {
      "enum": ["electron", "tauri", "qt", "wpf", "macos-native"],
      "default": "electron"
    },
    "sentryConfig": {
      "type": "object",
      "properties": {
        "dsn": { "type": "string", "description": "Sentry DSN (or use env variable)" },
        "organization": { "type": "string" },
        "project": { "type": "string" },
        "environment": { "type": "string", "default": "production" }
      },
      "required": ["organization", "project"]
    },
    "features": {
      "type": "array",
      "items": {
        "enum": [
          "crashReporting",
          "errorTracking",
          "performanceMonitoring",
          "sessionTracking",
          "releaseHealth",
          "sourceMaps",
          "userFeedback",
          "customContext",
          "breadcrumbs",
          "nativeCrashes"
        ]
      },
      "default": ["crashReporting", "errorTracking", "performanceMonitoring", "sourceMaps"]
    },
    "sampling": {
      "type": "object",
      "properties": {
        "tracesSampleRate": { "type": "number", "default": 0.1 },
        "errorSampleRate": { "type": "number", "default": 1.0 },
        "profilesSampleRate": { "type": "number", "default": 0.1 }
      }
    },
    "privacy": {
      "type": "object",
      "properties": {
        "scrubData": { "type": "boolean", "default": true },
        "scrubFields": { "type": "array", "items": { "type": "string" } },
        "ipAddress": { "enum": ["auto", "off"], "default": "off" }
      }
    },
    "ci": {
      "type": "object",
      "properties": {
        "generateWorkflow": { "type": "boolean", "default": true },
        "provider": { "enum": ["github-actions", "azure-devops", "circleci"] }
      }
    }
  },
  "required": ["projectPath", "sentryConfig"]
}
```

## Output Schema

```json
{
  "type": "object",
  "properties": {
    "success": { "type": "boolean" },
    "files": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "path": { "type": "string" },
          "type": { "enum": ["config", "main", "renderer", "utils", "ci"] }
        }
      }
    },
    "commands": {
      "type": "object",
      "properties": {
        "uploadSourceMaps": { "type": "string" },
        "createRelease": { "type": "string" },
        "testIntegration": { "type": "string" }
      }
    },
    "envVariables": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "description": { "type": "string" }
        }
      }
    }
  },
  "required": ["success", "files"]
}
```

## Generated File Structure

```
src/
  main/
    sentry/
      sentry-main.ts       # Main process Sentry init
      crash-reporter.ts    # Native crash handling
      ipc-handlers.ts      # Sentry IPC handlers
  renderer/
    sentry/
      sentry-renderer.ts   # Renderer Sentry init
      error-boundary.tsx   # React error boundary
      user-feedback.ts     # Feedback dialog
  shared/
    sentry-config.ts       # Shared configuration
    context-utils.ts       # Context helpers
scripts/
  sentry-release.js        # Release script
.github/workflows/
  sentry-release.yml       # CI workflow
```

## Code Templates

### Main Process Sentry Configuration

```typescript
// src/main/sentry/sentry-main.ts
import * as Sentry from '@sentry/electron/main';
import { app } from 'electron';

export function initSentryMain() {
  Sentry.init({
    dsn: process.env.SENTRY_DSN,
    environment: process.env.NODE_ENV || 'production',
    release: `${app.getName()}@${app.getVersion()}`,

    // Performance monitoring
    tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
    profilesSampleRate: 0.1,

    // Session tracking
    autoSessionTracking: true,

    // Native crash reporting
    enableNative: true,

    // Privacy
    beforeSend(event) {
      // Scrub sensitive data
      if (event.user) {
        delete event.user.ip_address;
      }
      return event;
    },

    // Integrations
    integrations: [
      Sentry.electronMinidumpIntegration(),
      Sentry.mainProcessIntegration(),
    ],
  });

  // Set app context
  Sentry.setContext('app', {
    name: app.getName(),
    version: app.getVersion(),
    platform: process.platform,
    arch: process.arch,
    electron: process.versions.electron,
  });
}

export function captureMainException(error: Error, context?: Record<string, unknown>) {
  Sentry.withScope((scope) => {
    scope.setTag('process', 'main');
    if (context) {
      scope.setExtras(context);
    }
    Sentry.captureException(error);
  });
}
```

### Renderer Process Sentry Configuration

```typescript
// src/renderer/sentry/sentry-renderer.ts
import * as Sentry from '@sentry/electron/renderer';
import { init as sentryReactInit, browserTracingIntegration } from '@sentry/react';

export function initSentryRenderer() {
  sentryReactInit({
    dsn: process.env.SENTRY_DSN,
    environment: process.env.NODE_ENV || 'production',
    release: window.electronAPI.getAppVersion(),

    // Performance
    tracesSampleRate: 0.1,

    // Integrations
    integrations: [
      browserTracingIntegration(),
      Sentry.electronRendererIntegration(),
    ],

    // Breadcrumbs
    beforeBreadcrumb(breadcrumb) {
      // Filter out noisy breadcrumbs
      if (breadcrumb.category === 'console' && breadcrumb.level === 'debug') {
        return null;
      }
      return breadcrumb;
    },
  });

  // Add custom context
  Sentry.setTag('renderer', 'main-window');
}

// React Error Boundary wrapper
export function withSentryErrorBoundary<P extends object>(
  Component: React.ComponentType<P>,
  fallback: React.ReactNode
) {
  return Sentry.withErrorBoundary(Component, {
    fallback,
    showDialog: true,
  });
}
```

### React Error Boundary

```tsx
// src/renderer/sentry/error-boundary.tsx
import React from 'react';
import * as Sentry from '@sentry/react';

interface Props {
  children: React.ReactNode;
  fallback?: React.ReactNode;
}

interface State {
  hasError: boolean;
  eventId: string | null;
}

export class ErrorBoundary extends React.Component<Props, State> {
  state: State = { hasError: false, eventId: null };

  static getDerivedStateFromError(): State {
    return { hasError: true, eventId: null };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    Sentry.withScope((scope) => {
      scope.setExtras({
        componentStack: errorInfo.componentStack,
      });
      const eventId = Sentry.captureException(error);
      this.setState({ eventId });
    });
  }

  handleReportClick = () => {
    if (this.state.eventId) {
      Sentry.showReportDialog({ eventId: this.state.eventId });
    }
  };

  handleReload = () => {
    window.location.reload();
  };

  render() {
    if (this.state.hasError) {
      return (
        this.props.fallback || (
          <div className="error-boundary">
            <h2>Something went wrong</h2>
            <p>We've been noti

Related in Data & Analytics