Sentry Sentinel Theme

Beautiful web syntax highlighter themes for Prism.js and Highlight.js

Use the dropdowns below to switch between themes and programming languages. Compare how each theme looks in both Prism.js and Highlight.js side by side.

View the project on GitHub

Code Examples

JavaScript

// Sentry error tracking example
import * as Sentry from '@sentry/browser';

Sentry.init({
  dsn: "https://example@sentry.io/123456",
  environment: "production",
  integrations: [
    new Sentry.BrowserTracing(),
  ],
  tracesSampleRate: 1.0,
});

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    Sentry.captureException(error, { 
      contexts: { react: { componentStack: errorInfo.componentStack } }
    });
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}
// Sentry error tracking example
import * as Sentry from '@sentry/browser';

Sentry.init({
  dsn: "https://example@sentry.io/123456",
  environment: "production",
  integrations: [
    new Sentry.BrowserTracing(),
  ],
  tracesSampleRate: 1.0,
});

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    Sentry.captureException(error, { 
      contexts: { react: { componentStack: errorInfo.componentStack } }
    });
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

TypeScript

interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
}

type AsyncResult = Promise<{ data: T; error?: never } | { data?: never; error: Error }>;

async function fetchUser(id: string): AsyncResult {
  try {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    return { data };
  } catch (error) {
    return { error: error instanceof Error ? error : new Error('Unknown error') };
  }
}

const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes

class UserCache {
  private cache = new Map();

  get(id: string): User | null {
    const cached = this.cache.get(id);
    if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
      return cached.user;
    }
    return null;
  }

  set(id: string, user: User): void {
    this.cache.set(id, { user, timestamp: Date.now() });
  }
}
interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
}

type AsyncResult = Promise<{ data: T; error?: never } | { data?: never; error: Error }>;

async function fetchUser(id: string): AsyncResult {
  try {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    return { data };
  } catch (error) {
    return { error: error instanceof Error ? error : new Error('Unknown error') };
  }
}

const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes

class UserCache {
  private cache = new Map();

  get(id: string): User | null {
    const cached = this.cache.get(id);
    if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
      return cached.user;
    }
    return null;
  }

  set(id: string, user: User): void {
    this.cache.set(id, { user, timestamp: Date.now() });
  }
}

Python

import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from typing import Optional, Dict, Any
import functools
import time

sentry_sdk.init(
    dsn="https://example@sentry.io/123456",
    integrations=[DjangoIntegration()],
    traces_sample_rate=1.0,
    send_default_pii=True
)

def performance_monitor(func):
    """Decorator to monitor function performance with Sentry."""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        with sentry_sdk.start_transaction(op="function", name=func.__name__) as transaction:
            start_time = time.time()
            try:
                result = func(*args, **kwargs)
                transaction.set_status("ok")
                return result
            except Exception as e:
                transaction.set_status("internal_error")
                sentry_sdk.capture_exception(e)
                raise
            finally:
                duration = time.time() - start_time
                transaction.set_data("duration", duration)
    return wrapper

class DataProcessor:
    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.cache: Dict[str, Any] = {}
    
    @performance_monitor
    def process_batch(self, items: list) -> Optional[Dict[str, Any]]:
        """Process a batch of items with error handling."""
        results = []
        for item in items:
            try:
                processed = self._process_single(item)
                results.append(processed)
            except ValueError as e:
                sentry_sdk.capture_message(f"Invalid item: {item}", level="warning")
                continue
        
        return {"processed": len(results), "failed": len(items) - len(results)}
    
    def _process_single(self, item: Any) -> Any:
        """Process a single item."""
        if not isinstance(item, dict):
            raise ValueError(f"Expected dict, got {type(item)}")
        
        # Simulate processing
        return {**item, "processed": True, "timestamp": time.time()}
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from typing import Optional, Dict, Any
import functools
import time

sentry_sdk.init(
    dsn="https://example@sentry.io/123456",
    integrations=[DjangoIntegration()],
    traces_sample_rate=1.0,
    send_default_pii=True
)

def performance_monitor(func):
    """Decorator to monitor function performance with Sentry."""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        with sentry_sdk.start_transaction(op="function", name=func.__name__) as transaction:
            start_time = time.time()
            try:
                result = func(*args, **kwargs)
                transaction.set_status("ok")
                return result
            except Exception as e:
                transaction.set_status("internal_error")
                sentry_sdk.capture_exception(e)
                raise
            finally:
                duration = time.time() - start_time
                transaction.set_data("duration", duration)
    return wrapper

class DataProcessor:
    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.cache: Dict[str, Any] = {}
    
    @performance_monitor
    def process_batch(self, items: list) -> Optional[Dict[str, Any]]:
        """Process a batch of items with error handling."""
        results = []
        for item in items:
            try:
                processed = self._process_single(item)
                results.append(processed)
            except ValueError as e:
                sentry_sdk.capture_message(f"Invalid item: {item}", level="warning")
                continue
        
        return {"processed": len(results), "failed": len(items) - len(results)}
    
    def _process_single(self, item: Any) -> Any:
        """Process a single item."""
        if not isinstance(item, dict):
            raise ValueError(f"Expected dict, got {type(item)}")
        
        # Simulate processing
        return {**item, "processed": True, "timestamp": time.time()}

React JSX

import React, { useState, useEffect } from 'react';
import { ErrorBoundary } from '@sentry/react';

const UserProfile = ({ userId }) => {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUser = async () => {
      try {
        setLoading(true);
        const response = await fetch(`/api/users/${userId}`);
        if (!response.ok) throw new Error('Failed to fetch user');
        const data = await response.json();
        setUser(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchUser();
  }, [userId]);

  if (loading) return <div className="spinner">Loading...</div>;
  if (error) return <div className="error">Error: {error}</div>;

  return (
    <ErrorBoundary fallback={<div>Something went wrong</div>} showDialog>
      <div className="user-profile">
        <img src={user.avatar} alt={user.name} />
        <h2>{user.name}</h2>
        <p>{user.email}</p>
        <div className="stats">
          <span>Joined: {new Date(user.joinedAt).toLocaleDateString()}</span>
          <span>Posts: {user.postCount}</span>
        </div>
      </div>
    </ErrorBoundary>
  );
};

export default UserProfile;
import React, { useState, useEffect } from 'react';
import { ErrorBoundary } from '@sentry/react';

const UserProfile = ({ userId }) => {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUser = async () => {
      try {
        setLoading(true);
        const response = await fetch(`/api/users/${userId}`);
        if (!response.ok) throw new Error('Failed to fetch user');
        const data = await response.json();
        setUser(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchUser();
  }, [userId]);

  if (loading) return <div className="spinner">Loading...</div>;
  if (error) return <div className="error">Error: {error}</div>;

  return (
    <ErrorBoundary fallback={<div>Something went wrong</div>} showDialog>
      <div className="user-profile">
        <img src={user.avatar} alt={user.name} />
        <h2>{user.name}</h2>
        <p>{user.email}</p>
        <div className="stats">
          <span>Joined: {new Date(user.joinedAt).toLocaleDateString()}</span>
          <span>Posts: {user.postCount}</span>
        </div>
      </div>
    </ErrorBoundary>
  );
};

export default UserProfile;

CSS

/* Sentry-themed button styles */
.btn-sentry {
  --primary: var(--purple-primary);
  --primary-hover: var(--purple-tertiary);
  --accent: #FF45A8;
  
  display: inline-flex;
  align-items: center;
  padding: 0.75rem 1.5rem;
  font-weight: 500;
  font-size: 1rem;
  line-height: 1.5;
  color: white;
  background-color: var(--primary);
  border: 2px solid transparent;
  border-radius: 8px;
  transition: all 0.2s ease-in-out;
  cursor: pointer;
  text-decoration: none;
}

.btn-sentry:hover {
  background-color: var(--primary-hover);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(54, 22, 107, 0.3);
}

.btn-sentry:active {
  transform: translateY(0);
  box-shadow: 0 2px 4px rgba(54, 22, 107, 0.2);
}

.btn-sentry--accent {
  background-color: var(--accent);
}

.btn-sentry--accent:hover {
  background-color: #FF70BC;
}

@media (prefers-reduced-motion: reduce) {
  .btn-sentry {
    transition: none;
  }
}
/* Sentry-themed button styles */
.btn-sentry {
  --primary: var(--purple-primary);
  --primary-hover: var(--purple-tertiary);
  --accent: #FF45A8;
  
  display: inline-flex;
  align-items: center;
  padding: 0.75rem 1.5rem;
  font-weight: 500;
  font-size: 1rem;
  line-height: 1.5;
  color: white;
  background-color: var(--primary);
  border: 2px solid transparent;
  border-radius: 8px;
  transition: all 0.2s ease-in-out;
  cursor: pointer;
  text-decoration: none;
}

.btn-sentry:hover {
  background-color: var(--primary-hover);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(54, 22, 107, 0.3);
}

.btn-sentry:active {
  transform: translateY(0);
  box-shadow: 0 2px 4px rgba(54, 22, 107, 0.2);
}

.btn-sentry--accent {
  background-color: var(--accent);
}

.btn-sentry--accent:hover {
  background-color: #FF70BC;
}

@media (prefers-reduced-motion: reduce) {
  .btn-sentry {
    transition: none;
  }
}

JSON

{
  "name": "sentry-sentinel-theme",
  "version": "1.0.0",
  "description": "Official Sentry theme for syntax highlighting",
  "author": "Sentry",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/getsentry/sentinel"
  },
  "keywords": [
    "sentry",
    "theme",
    "syntax-highlighting",
    "prism",
    "highlight.js"
  ],
  "themes": {
    "light": {
      "primary": "var(--purple-primary)",
      "secondary": "var(--purple-secondary)",
      "accent": "#FF45A8"
    },
    "dark": {
      "primary": "#9E86FF",
      "secondary": "#FF70BC",
      "accent": "#C0ED49"
    }
  },
  "scripts": {
    "test": "node test.js",
    "build": "node build.js"
  }
}
{
  "name": "sentry-sentinel-theme",
  "version": "1.0.0",
  "description": "Official Sentry theme for syntax highlighting",
  "author": "Sentry",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/getsentry/sentinel"
  },
  "keywords": [
    "sentry",
    "theme",
    "syntax-highlighting",
    "prism",
    "highlight.js"
  ],
  "themes": {
    "light": {
      "primary": "var(--purple-primary)",
      "secondary": "var(--purple-secondary)",
      "accent": "#FF45A8"
    },
    "dark": {
      "primary": "#9E86FF",
      "secondary": "#FF70BC",
      "accent": "#C0ED49"
    }
  },
  "scripts": {
    "test": "node test.js",
    "build": "node build.js"
  }
}

YAML

# Sentry configuration
sentry:
  dsn: https://example@sentry.io/123456
  environment: production
  traces_sample_rate: 1.0
  
  integrations:
    - name: BrowserTracing
      options:
        routingInstrumentation: vue
    - name: Replay
      options:
        maskAllText: false
        blockAllMedia: false

app:
  name: My Application
  version: 1.2.3
  features:
    - authentication
    - real-time-updates
    - error-tracking
  
  database:
    host: localhost
    port: 5432
    name: myapp_prod
    ssl: true
    
  cache:
    provider: redis
    ttl: 3600
    max_entries: 10000
# Sentry configuration
sentry:
  dsn: https://example@sentry.io/123456
  environment: production
  traces_sample_rate: 1.0
  
  integrations:
    - name: BrowserTracing
      options:
        routingInstrumentation: vue
    - name: Replay
      options:
        maskAllText: false
        blockAllMedia: false

app:
  name: My Application
  version: 1.2.3
  features:
    - authentication
    - real-time-updates
    - error-tracking
  
  database:
    host: localhost
    port: 5432
    name: myapp_prod
    ssl: true
    
  cache:
    provider: redis
    ttl: 3600
    max_entries: 10000

SQL

-- Get user activity with error tracking
WITH user_errors AS (
  SELECT 
    u.user_id,
    u.username,
    COUNT(e.error_id) as error_count,
    MAX(e.occurred_at) as last_error
  FROM users u
  LEFT JOIN errors e ON u.user_id = e.user_id
  WHERE e.occurred_at >= NOW() - INTERVAL '7 days'
  GROUP BY u.user_id, u.username
)
SELECT 
  ue.*,
  COALESCE(s.session_count, 0) as sessions_last_week,
  CASE 
    WHEN ue.error_count > 10 THEN 'high'
    WHEN ue.error_count > 5 THEN 'medium'
    ELSE 'low'
  END as error_severity
FROM user_errors ue
LEFT JOIN (
  SELECT user_id, COUNT(*) as session_count
  FROM sessions
  WHERE created_at >= NOW() - INTERVAL '7 days'
  GROUP BY user_id
) s ON ue.user_id = s.user_id
ORDER BY ue.error_count DESC
LIMIT 100;
-- Get user activity with error tracking
WITH user_errors AS (
  SELECT 
    u.user_id,
    u.username,
    COUNT(e.error_id) as error_count,
    MAX(e.occurred_at) as last_error
  FROM users u
  LEFT JOIN errors e ON u.user_id = e.user_id
  WHERE e.occurred_at >= NOW() - INTERVAL '7 days'
  GROUP BY u.user_id, u.username
)
SELECT 
  ue.*,
  COALESCE(s.session_count, 0) as sessions_last_week,
  CASE 
    WHEN ue.error_count > 10 THEN 'high'
    WHEN ue.error_count > 5 THEN 'medium'
    ELSE 'low'
  END as error_severity
FROM user_errors ue
LEFT JOIN (
  SELECT user_id, COUNT(*) as session_count
  FROM sessions
  WHERE created_at >= NOW() - INTERVAL '7 days'
  GROUP BY user_id
) s ON ue.user_id = s.user_id
ORDER BY ue.error_count DESC
LIMIT 100;

Go

package main

import (
    "context"
    "fmt"
    "log"
    "time"
    
    "github.com/getsentry/sentry-go"
)

type ErrorHandler struct {
    client *sentry.Client
}

func NewErrorHandler(dsn string) (*ErrorHandler, error) {
    client, err := sentry.NewClient(sentry.ClientOptions{
        Dsn:              dsn,
        Environment:      "production",
        TracesSampleRate: 1.0,
        BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
            if event.Level == sentry.LevelDebug {
                return nil
            }
            return event
        },
    })
    if err != nil {
        return nil, fmt.Errorf("sentry init failed: %w", err)
    }
    
    return &ErrorHandler{client: client}, nil
}

func (h *ErrorHandler) HandlePanic() {
    if r := recover(); r != nil {
        h.client.RecoverWithContext(
            context.Background(),
            r,
            &sentry.EventHint{RecoveredException: r},
        )
        h.client.Flush(2 * time.Second)
        panic(r)
    }
}

func processData(data []byte) error {
    defer sentry.StartSpan(context.Background(), "processData").Finish()
    
    if len(data) == 0 {
        return fmt.Errorf("empty data provided")
    }
    
    // Process data here
    time.Sleep(100 * time.Millisecond)
    
    return nil
}
package main

import (
    "context"
    "fmt"
    "log"
    "time"
    
    "github.com/getsentry/sentry-go"
)

type ErrorHandler struct {
    client *sentry.Client
}

func NewErrorHandler(dsn string) (*ErrorHandler, error) {
    client, err := sentry.NewClient(sentry.ClientOptions{
        Dsn:              dsn,
        Environment:      "production",
        TracesSampleRate: 1.0,
        BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
            if event.Level == sentry.LevelDebug {
                return nil
            }
            return event
        },
    })
    if err != nil {
        return nil, fmt.Errorf("sentry init failed: %w", err)
    }
    
    return &ErrorHandler{client: client}, nil
}

func (h *ErrorHandler) HandlePanic() {
    if r := recover(); r != nil {
        h.client.RecoverWithContext(
            context.Background(),
            r,
            &sentry.EventHint{RecoveredException: r},
        )
        h.client.Flush(2 * time.Second)
        panic(r)
    }
}

func processData(data []byte) error {
    defer sentry.StartSpan(context.Background(), "processData").Finish()
    
    if len(data) == 0 {
        return fmt.Errorf("empty data provided")
    }
    
    // Process data here
    time.Sleep(100 * time.Millisecond)
    
    return nil
}

Rust

use sentry::{ClientOptions, IntoDsn};
use std::error::Error;
use std::time::Duration;

#[derive(Debug, Clone)]
pub struct Config {
    pub dsn: String,
    pub environment: String,
    pub sample_rate: f32,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            dsn: String::from("https://example@sentry.io/123456"),
            environment: String::from("production"),
            sample_rate: 1.0,
        }
    }
}

pub fn init_sentry(config: Config) -> Result> {
    let guard = sentry::init((
        config.dsn.as_str(),
        ClientOptions {
            environment: Some(config.environment.into()),
            traces_sample_rate: config.sample_rate,
            ..Default::default()
        },
    ));
    
    Ok(guard)
}

#[tracing::instrument]
pub async fn process_request(id: u64) -> Result> {
    let _span = sentry::start_transaction("process_request", "http.server");
    
    // Simulate processing
    tokio::time::sleep(Duration::from_millis(100)).await;
    
    if id % 10 == 0 {
        return Err("Invalid request ID".into());
    }
    
    Ok(format!("Processed request {}", id))
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_default_config() {
        let config = Config::default();
        assert_eq!(config.environment, "production");
        assert_eq!(config.sample_rate, 1.0);
    }
}
use sentry::{ClientOptions, IntoDsn};
use std::error::Error;
use std::time::Duration;

#[derive(Debug, Clone)]
pub struct Config {
    pub dsn: String,
    pub environment: String,
    pub sample_rate: f32,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            dsn: String::from("https://example@sentry.io/123456"),
            environment: String::from("production"),
            sample_rate: 1.0,
        }
    }
}

pub fn init_sentry(config: Config) -> Result> {
    let guard = sentry::init((
        config.dsn.as_str(),
        ClientOptions {
            environment: Some(config.environment.into()),
            traces_sample_rate: config.sample_rate,
            ..Default::default()
        },
    ));
    
    Ok(guard)
}

#[tracing::instrument]
pub async fn process_request(id: u64) -> Result> {
    let _span = sentry::start_transaction("process_request", "http.server");
    
    // Simulate processing
    tokio::time::sleep(Duration::from_millis(100)).await;
    
    if id % 10 == 0 {
        return Err("Invalid request ID".into());
    }
    
    Ok(format!("Processed request {}", id))
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_default_config() {
        let config = Config::default();
        assert_eq!(config.environment, "production");
        assert_eq!(config.sample_rate, 1.0);
    }
}