Skip to content

Beacon - Real-Time Ticket Dashboard

Port: 5001 Database: None (stateless, consumes Codex API) Repository: hivematrix-beacon Version: 1.0


Table of Contents


Overview

Beacon is HiveMatrix's real-time ticket monitoring command center. It provides at-a-glance visibility into active PSA tickets with intelligent categorization, SLA tracking, and priority highlighting to help support teams identify what needs attention immediately.

Design Philosophy

Stateless by Design: - Stores no data locally - All ticket data comes from Codex API - Never contacts PSA systems directly - Single source of truth (Codex) - Eliminates data synchronization issues

Focus on Visibility: Think of Beacon as your team's radar screen. It answers critical questions: - 🔴 What tickets need immediate attention? - 📬 Which tickets have customer replies waiting? - ⏰ What's overdue or approaching SLA breach? - 👤 How many tickets does each agent have? - 📊 What's the total active ticket count?


Architecture

Design Philosophy

Beacon follows a lightweight, stateless architecture:

PSA Systems (Freshservice, ConnectWise, etc.)
     Codex (sync & categorize)
     Beacon (display & filter)
     Users (monitor & act)

Why This Design?

  1. Single Source of Truth:
  2. Codex is the master data repository
  3. Beacon always shows current Codex data
  4. No discrepancies between services

  5. No Duplicate API Calls:

  6. Only Codex talks to PSA systems
  7. Respects API rate limits
  8. Reduces PSA load

  9. Consistent Data:

  10. All services see same ticket data
  11. Categorization logic centralized in Codex
  12. Changes to sync logic don't affect Beacon

  13. Simple Deployment:

  14. No database to manage
  15. Stateless = easy horizontal scaling
  16. Fast restarts (no data to migrate)

Technology Stack

  • Framework: Flask 3.0.0
  • UI: Server-rendered HTML with JavaScript enhancement
  • CSS: BEM classes from Nexus global.css (no local stylesheets)
  • HTTP Client: Requests (for Codex API calls)
  • Rate Limiting: Flask-Limiter
  • Logging: Structured JSON logging with correlation IDs
  • API Documentation: Flasgger (OpenAPI/Swagger)
  • Health Checks: Custom HealthChecker library

Production Features

Beacon includes enterprise-ready features introduced in version 4.1:

Per-User Rate Limiting

  • Rate limits applied per user (JWT subject) instead of IP address
  • Limits:
  • 200 requests/day
  • 50 requests/hour
  • Prevents individual user abuse
  • Suitable for shared environments

Structured Logging

  • JSON-formatted logs with correlation IDs for distributed tracing
  • Request/response logging with timing
  • Error context preservation
  • Centralized logging to Helm service
  • Configurable log levels (DEBUG, INFO, WARNING, ERROR)

RFC 7807 Problem Details

  • Standardized machine-readable error responses
  • Consistent error format across all endpoints
  • Enables automated error handling by clients

OpenAPI/Swagger Documentation

  • Auto-generated API documentation at /docs
  • Interactive API testing interface
  • Request/response schemas
  • Available at https://localhost/beacon/docs

Comprehensive Health Checks

  • Component-level health monitoring at /health
  • Checks: Disk space, Core availability, Codex availability
  • Status: healthy (200) or unhealthy/degraded (503)
  • Useful for monitoring and load balancer probes

Data Flow

Complete data flow from PSA to dashboard:

┌─────────────┐
│ PSA Systems │  (Freshservice, ConnectWise, etc.)
└──────┬──────┘
       │ 1. Codex runs sync_psa.py (cron or manual)
       │    Fetches tickets via PSA API
       │    Stores in Codex database
┌──────────────┐
│    Codex     │  Master data repository
│  (Database)  │
└──────┬───────┘
       │ 2. Beacon calls:
       │    - /api/tickets/active (categorized tickets)
       │    - /api/psa/agents (agent name mapping)
       │    - /api/psa/config (ticket URL template)
┌──────────────┐
│    Beacon    │  Display service
│  (Stateless) │
└──────┬───────┘
       │ 3. Beacon renders HTML with:
       │    - Ticket categorization (4 sections)
       │    - SLA indicators
       │    - Agent filtering
       │    - Auto-refresh capability
┌──────────────┐
│    Users     │  View dashboard
└──────────────┘

Categorization Logic: - Performed by Codex (not Beacon) - Codex /api/tickets/active returns 4 pre-categorized sections - Beacon displays sections as-is - Ensures consistency across all services

View Filtering: - Beacon filters by group_id to separate helpdesk vs professional services - Professional Services Group ID: 19000234009 (Freshservice-specific) - Configurable per PSA provider


Features

Dual Dashboard Views

Beacon provides two specialized dashboard views:

Helpdesk View

Route: /beacon/helpdesk

Purpose: General IT support tickets - Password resets - Software issues - Hardware problems - General user requests

Filtering: Excludes tickets with group_id == 19000234009


Professional Services View

Route: /beacon/professional-services

Purpose: Project and consulting work - Client projects - Implementation services - Consulting engagements - Professional services deliverables

Filtering: Only includes tickets with group_id == 19000234009


View Switching: - Tab buttons in dashboard header - Persists filter and sort when switching - Real-time count updates - Separate auto-refresh for each view


Ticket Categorization

Beacon organizes tickets into four priority-based sections:

Section 1: Open Tickets

Purpose: New tickets requiring first response

Criteria: - Status: Open - No SLA violation - Awaiting initial agent response

Typical Count: 5-20 tickets

Action Needed: Assign and provide first response

Visual: Standard priority coloring


Section 2: Customer Replied

Purpose: Tickets with customer responses awaiting agent

Criteria: - Customer has replied - Awaiting agent response - May have SLA concerns

Typical Count: 10-30 tickets

Action Needed: Review and respond to customer

Visual: SLA indicator shows urgency


Section 3: Needs Agent / Update Overdue

Purpose: Critical tickets requiring immediate action

Criteria: - SLA breached or critical - Update overdue - Priority: Urgent or High - Status indicates immediate attention needed

Typical Count: 0-5 tickets (should be minimal)

Action Needed: IMMEDIATE RESPONSE REQUIRED

Visual: Red highlighting, top of section


Section 4: Other Active Tickets

Purpose: All remaining non-closed tickets

Criteria: - On hold - Waiting on third party - Pending status - All other active states

Typical Count: 20-100 tickets

Action Needed: Monitor and update as needed

Visual: Standard display


Visual Indicators

SLA Status Colors

Beacon uses color coding to indicate urgency:

🔴 Red (Overdue/Breached): - SLA already breached - Immediate action required - Appears in Section 3

🟠 Orange (Critical): - SLA due within hours - Urgent attention needed - High risk of breach

🟡 Yellow (Warning): - SLA due within 24 hours - Plan response soon - Moderate risk

🟢 Green (On Track): - SLA is safe - No immediate concern - Standard response time


Priority Levels

From PSA system priority field:

Priority Description Typical Use
Urgent Critical business impact System down, major outage
High Significant impact Important feature broken
Medium Moderate impact Non-critical issue
Low Minimal impact Enhancement request

Visual Display: - Text badge in Priority column - Color coordinated with priority level - Sortable by priority value


Total Active Count

Location: Dashboard header (top right)

Visual Elements: - Large number display - Animated "siren" indicators (pulse on high count) - Updates in real-time with auto-refresh

Siren Activation: - Triggers when total count exceeds threshold - Visual pulse effect - Draws attention to high ticket volume

Example Display:

Total Active
   ← 47 →
Sirens pulse if count > 30


Agent Filtering

Location: Below dashboard header

Functionality: - Dropdown menu with all active agents - Default: "All Agents" - Filters all 4 sections simultaneously - Updates URL with ?agent_id=<id> parameter - Persists across page refreshes

Agent List Source: - Fetched from Codex /api/psa/agents - Only includes active agents - Sorted alphabetically by name - Maps external_id (PSA ID) to display name

Use Cases: 1. Individual Dashboard: Agent monitors own tickets 2. Team Lead Review: Manager checks specific agent's workload 3. Load Balancing: Identify uneven distribution

Example URL:

/beacon/helpdesk?agent_id=19000234567


Auto-Refresh

Interval: 60 seconds (1 minute)

Behavior: - Automatically calls /api/tickets/<view> endpoint - Updates all 4 sections without page reload - Preserves filter and sort settings - Shows "Last Sync" timestamp - Visual feedback during refresh

Last Sync Indicator: - Displays timestamp from Codex's last PSA sync - Format: "Nov 22, 2025 10:30 AM" (localized) - Updates on each auto-refresh - Helps users know data freshness

JavaScript Implementation:

window.AUTO_REFRESH_MS = 60000;  // 1 minute

setInterval(function() {
    fetch(`/api/tickets/${currentView}?agent_id=${selectedAgent}`, {
        credentials: 'same-origin'
    })
    .then(response => response.json())
    .then(data => updateDashboard(data));
}, AUTO_REFRESH_MS);

Disable Auto-Refresh: - Not currently configurable via UI - Can be disabled in browser console:

clearInterval(refreshInterval);


Sortable Tables

Sortable Columns: - ID - Subject - Requester - Agent - Priority - Action/SLA/Status - Updated - Created

Sorting Behavior: - Click column header to sort - First click: ascending - Second click: descending - Third click: reset to default - Visual indicator (↑/↓) shows current sort - Persists during auto-refresh

Default Sort Order: - Section 1: Created (oldest first) - Section 2: Updated (oldest first - needs attention) - Section 3: Priority (urgent first) → SLA (critical first) - Section 4: Updated (oldest first)


API Reference

Web Routes

GET /

Redirects to default dashboard view.

Response: 302 Redirect to /helpdesk

Example:

curl -L https://localhost/beacon/


GET /<view_slug>

Main dashboard route for specific view.

Supported Views: - helpdesk - General support tickets - professional-services - Project tickets

Query Parameters: - agent_id (optional, integer): Filter tickets by agent

Response: HTML dashboard page

Example:

# All helpdesk tickets
https://localhost/beacon/helpdesk

# Specific agent's professional services tickets
https://localhost/beacon/professional-services?agent_id=19000234567

Template Variables Rendered:

{
    's1_items': [...],  # Section 1 tickets
    's2_items': [...],  # Section 2 tickets
    's3_items': [...],  # Section 3 tickets
    's4_items': [...],  # Section 4 tickets
    'dashboard_generated_time_iso': '2025-11-22T10:30:00Z',
    'ticket_base_url': 'https://msp.freshservice.com/helpdesk/tickets/',
    'current_view_slug': 'helpdesk',
    'current_view_display': 'Helpdesk',
    'supported_views': {'helpdesk': 'Helpdesk', ...},
    'agent_mapping': {19000234567: 'John Doe', ...},
    'selected_agent_id': 19000234567,
    'auto_refresh_ms': 60000
}

Error Responses: - 404 Not Found: Unsupported view slug


API Endpoints

GET /api/tickets/<view_slug>

JSON endpoint for ticket data (used by auto-refresh).

Purpose: AJAX endpoint for dashboard refresh without page reload

Supported Views: - helpdesk - professional-services

Query Parameters: - agent_id (optional, integer): Filter tickets by agent

Response (200 OK):

{
  "s1_items": [
    {
      "id": 12345,
      "external_id": 12345,
      "subject": "Password reset request",
      "requester_name": "John Doe",
      "responder_id": 19000234567,
      "agent_name": "Jane Smith",
      "priority": 2,
      "priority_text": "Medium",
      "priority_raw": 2,
      "status": 2,
      "status_text": "Open",
      "sla_text": "Due in 3h",
      "sla_color": "orange",
      "group_id": 19000123456,
      "created_at": "2025-11-22T09:00:00Z",
      "created_at_str": "Nov 22, 09:00 AM",
      "updated_at": "2025-11-22T09:15:00Z",
      "updated_at_str": "Nov 22, 09:15 AM",
      "description": "User unable to login..."
    }
  ],
  "s2_items": [...],
  "s3_items": [...],
  "s4_items": [...],
  "total_active_items": 47,
  "dashboard_generated_time_iso": "2025-11-22T10:30:00Z",
  "view": "Helpdesk",
  "section1_name_js": "Open Helpdesk Tickets",
  "section2_name_js": "Customer Replied",
  "section3_name_js": "Needs Agent / Update Overdue",
  "section4_name_js": "Other Active Helpdesk Tickets"
}

Ticket Object Fields:

Field Type Description
id integer Codex database ID
external_id integer PSA system ticket ID
subject string Ticket subject line
requester_name string Customer/requester name
responder_id integer Assigned agent's PSA ID
agent_name string Assigned agent's display name
priority integer Priority level (1-4)
priority_text string "Urgent", "High", "Medium", "Low"
priority_raw integer Raw priority value for sorting
status integer Status code
status_text string Human-readable status
sla_text string SLA status message
sla_color string Color indicator (red, orange, yellow, green)
group_id integer PSA group/team ID
created_at string ISO timestamp
created_at_str string Formatted datetime for display
updated_at string ISO timestamp
updated_at_str string Formatted datetime for display
description string Ticket description HTML

Error Responses: - 404 Not Found: Unsupported view

Example:

curl -H "Authorization: Bearer $TOKEN" \
  https://localhost/beacon/api/tickets/helpdesk?agent_id=19000234567


Public Endpoints

GET /health

Comprehensive health check endpoint.

Checks: - Disk space usage - Core service availability - Codex service availability

Response (200 OK - Healthy):

{
  "service": "beacon",
  "status": "healthy",
  "timestamp": "2025-11-22T10:30:00.000Z",
  "checks": {
    "disk": {
      "status": "healthy",
      "usage_percent": 45.67,
      "free_gb": 123.45,
      "total_gb": 250.0
    },
    "dependencies": {
      "core": {
        "status": "healthy",
        "response_time_ms": 15
      },
      "codex": {
        "status": "healthy",
        "response_time_ms": 42
      }
    }
  }
}

Status Codes: - 200 OK: All checks healthy - 503 Service Unavailable: One or more checks unhealthy


GET /docs

Interactive OpenAPI/Swagger API documentation.

Response: HTML page with interactive API explorer

Access: https://localhost/beacon/docs


Integration

Codex Dependency

Beacon depends entirely on Codex for data:

Required Codex Endpoints

1. /api/tickets/active

Returns categorized tickets in 4 sections.

Response:

{
  "section1": [...],  // Open tickets
  "section2": [...],  // Customer replied
  "section3": [...],  // Needs agent / overdue
  "section4": [...],  // Other active
  "last_sync_time": "2025-11-22T10:30:00Z"
}

Categorization Logic (in Codex): - Section 1: status == 'Open' AND no SLA issues - Section 2: Customer has replied, awaiting agent - Section 3: SLA critical/breached OR urgent priority OR overdue - Section 4: All other active tickets


2. /api/psa/agents

Returns list of agents for filtering.

Response:

[
  {
    "id": 123,  // Codex database ID
    "external_id": 19000234567,  // PSA agent ID
    "name": "John Doe",
    "email": "john@example.com",
    "active": true
  }
]

Usage: - Populates agent filter dropdown - Maps external_id to name for display - Only active agents shown


3. /api/psa/config

Returns PSA configuration including ticket URL template.

Response:

{
  "default_provider": "freshservice",
  "providers": {
    "freshservice": {
      "ticket_url_template": "https://msp.freshservice.com/helpdesk/tickets/{ticket_id}",
      "domain": "msp.freshservice.com",
      "api_key": "***"
    }
  }
}

Usage: - Constructs ticket links - Cached globally in Beacon - Falls back to no links if unavailable


Service Communication

All Codex calls use service-to-service authentication:

from app.service_client import call_service

# Automatically handles:
# - Token request from Core
# - Authorization header
# - Error handling
# - Timeouts

response = call_service('codex', '/api/tickets/active')
if response and response.status_code == 200:
    data = response.json()

Token Details: - Short-lived (5 minutes) - Type: service (not user) - Auto-renewed by call_service() - Cached to avoid excessive token requests


PSA Integration

Beacon never contacts PSA systems directly:

❌ Beacon → PSA (WRONG)
✅ Beacon → Codex → PSA (CORRECT)

Why? - Single point of API rate limiting (Codex) - Centralized sync logic - No duplicate API calls - Codex handles PSA auth - Simpler security model

Codex Sync Process:

# Manual sync
cd hivematrix-codex
source pyenv/bin/activate
python sync_psa.py --type tickets

# Automated sync (cron)
*/15 * * * * cd /path/to/hivematrix-codex && source pyenv/bin/activate && python sync_psa.py --type tickets


Configuration

Environment Variables

Beacon is configured via environment variables (loaded from .flaskenv).

⚠️ Important: .flaskenv is auto-generated by config_manager.py. Do not edit manually.

# Flask application settings
FLASK_APP=run.py
FLASK_ENV=production
SECRET_KEY=<generated-secret>
SERVICE_NAME=beacon

# Service URLs
CORE_SERVICE_URL=http://localhost:5000
CODEX_SERVICE_URL=http://localhost:5010

# Logging
LOG_LEVEL=INFO
ENABLE_JSON_LOGGING=true

View Configuration

Location: app/__init__.py

SUPPORTED_VIEWS = {
    "helpdesk": "Helpdesk",
    "professional-services": "Professional Services"
}

DEFAULT_VIEW_SLUG = "helpdesk"

Adding a New View:

  1. Add to SUPPORTED_VIEWS dict
  2. Update filter_tickets_by_view() function
  3. Define filtering logic (e.g., by group_id, tags, etc.)
  4. Add navigation tab in template
  5. Restart Beacon

Professional Services Setup

Configuration:

# In app/__init__.py
PROFESSIONAL_SERVICES_GROUP_ID = 19000234009

PSA-Specific Values:

PSA System How to Find Group ID
Freshservice Admin → Groups → Select group → URL shows ID
ConnectWise Board → Select board → ID in URL
Datto Autotask Queues → Queue ID

Updating for Your PSA:

  1. Find professional services group/board ID in your PSA
  2. Update PROFESSIONAL_SERVICES_GROUP_ID constant
  3. Restart Beacon
  4. Verify tickets categorize correctly

Multiple Groups: For multiple professional services groups, update filtering logic:

PROFESSIONAL_SERVICES_GROUP_IDS = [19000234009, 19000234010, 19000234011]

def filter_tickets_by_view(tickets, view_slug):
    if view_slug == 'professional-services':
        return [t for t in tickets if t.get('group_id') in PROFESSIONAL_SERVICES_GROUP_IDS]
    # ...

User Interface

Dashboard Layout

Header Section: - Service title: "Beacon - Ticket Dashboard" - View tabs: Helpdesk | Pro Services - Total active count with siren indicators - Last sync timestamp

Filter Section: - Agent dropdown filter

Content Sections: - Section 1 card (Open Tickets) - Section 2 card (Customer Replied) - Section 3 card (Needs Agent/Overdue) - Section 4 card (Other Active)

Each Card Contains: - Section title with count - Sortable table - Empty state message if no tickets


Ticket Sections

Section Layout:

<div class="card">
    <div class="card__header">
        <h2>Section Name (<span>Count</span>)</h2>
    </div>
    <div class="card__body">
        <table class="data-table">
            <thead>...</thead>
            <tbody>
                <!-- Tickets rendered here -->
            </tbody>
        </table>
        <p class="empty-state" style="display: none;">
            No tickets in this category.
        </p>
    </div>
</div>

Ticket Row Example:

<tr>
    <td><a href="https://psa.com/tickets/12345">#12345</a></td>
    <td>Password reset request</td>
    <td>John Doe</td>
    <td>Jane Smith</td>
    <td><span class="badge badge--medium">Medium</span></td>
    <td><span style="color: orange;">Due in 3h</span></td>
    <td>Nov 22, 09:15 AM</td>
    <td>Nov 22, 09:00 AM</td>
</tr>

Filtering

Agent Filter Workflow:

  1. User selects agent from dropdown
  2. JavaScript calls:
    window.location.href = `${currentView}?agent_id=${agentId}`;
    
  3. Page reloads with filtered data
  4. All 4 sections show only selected agent's tickets
  5. Filter persists across refreshes

"All Agents" Option: - Removes agent_id parameter - Shows all tickets - Default state

URL Examples:

/beacon/helpdesk                          # All agents
/beacon/helpdesk?agent_id=19000234567     # Specific agent


Column Sorting

Implementation:

document.querySelectorAll('.sortable-header').forEach(header => {
    header.addEventListener('click', function() {
        const sortKey = this.dataset.sortKey;
        const table = this.closest('table');
        const tbody = table.querySelector('tbody');
        const rows = Array.from(tbody.querySelectorAll('tr'));

        // Toggle sort direction
        const direction = this.dataset.sortDir === 'asc' ? 'desc' : 'asc';
        this.dataset.sortDir = direction;

        // Sort rows
        rows.sort((a, b) => {
            const aVal = a.querySelector(`[data-value-${sortKey}]`).dataset[`value${sortKey}`];
            const bVal = b.querySelector(`[data-value-${sortKey}]`).dataset[`value${sortKey}`];
            return direction === 'asc' ? aVal - bVal : bVal - aVal;
        });

        // Update table
        rows.forEach(row => tbody.appendChild(row));
    });
});

Sort Indicators: - Unsorted: No indicator - Ascending: ↑ - Descending: ↓


Development

Running Locally

Prerequisites: - Python 3.9+ - Codex service running (port 5010) - Core service running (port 5000)

Setup:

cd hivematrix-beacon

# Create virtual environment
python3 -m venv pyenv
source pyenv/bin/activate

# Install dependencies
pip install -r requirements.txt

# Configure environment
cd ../hivematrix-helm
python config_manager.py write-dotenv beacon
cd ../hivematrix-beacon

# Run Beacon
python run.py

Expected Output:

Loaded 8 services from services.json
Loaded 15 active agents from Codex
Starting Beacon - Ticket Dashboard
Supported views: {'helpdesk': 'Helpdesk', 'professional-services': 'Professional Services'}
 * Running on http://127.0.0.1:5001

Access Points: - Dashboard: http://localhost:5001/helpdesk - API: http://localhost:5001/api/tickets/helpdesk - Health: http://localhost:5001/health - Docs: http://localhost:5001/docs


File Structure

hivematrix-beacon/
├── app/
│   ├── __init__.py               # Main application & routes
│   ├── error_responses.py        # RFC 7807 error handlers
│   ├── rate_limit_key.py         # Per-user rate limiting
│   ├── service_client.py         # Service-to-service helper
│   ├── structured_logger.py      # JSON logging setup
│   ├── version.py                # Version info
│   ├── static/
│   │   └── js/
│   │       └── main.js           # Dashboard JavaScript
│   └── templates/
│       ├── layout.html           # Base template
│       └── index.html            # Dashboard template
├── run.py                        # Entry point
├── health_check.py               # Health check library
├── install.sh                    # Installation script
├── requirements.txt              # Python dependencies
├── .flaskenv                     # Auto-generated config
└── services.json                 # Symlink to helm

Adding Features

Add a New Ticket Section

1. Update Codex:

Modify Codex's /api/tickets/active to return new section:

# In Codex
return jsonify({
    'section1': [...],
    'section2': [...],
    'section3': [...],
    'section4': [...],
    'section5': [...],  # NEW SECTION
    'last_sync_time': last_sync_time
})

2. Update Beacon Route:

# In app/__init__.py
s1, s2, s3, s4, s5, last_sync_time = get_tickets_for_view(view_slug, agent_id)

return render_template(INDEX_TEMPLATE,
                       s1_items=s1,
                       s2_items=s2,
                       s3_items=s3,
                       s4_items=s4,
                       s5_items=s5,  # NEW
                       ...)

3. Update Template:

Add section card in templates/index.html:

<div class="card u-mb-3" id="s5-container">
    <div class="card__header">
        <h2>{{ section5_name }} (<span id="s5-item-count">{{ s5_items|length }}</span>)</h2>
    </div>
    <div class="card__body">
        <table class="data-table" id="s5-item-table">
            <!-- Table structure -->
        </table>
    </div>
</div>

4. Update JavaScript:

Add section to auto-refresh in static/js/main.js:

function updateDashboard(data) {
    updateSection('s1', data.s1_items);
    updateSection('s2', data.s2_items);
    updateSection('s3', data.s3_items);
    updateSection('s4', data.s4_items);
    updateSection('s5', data.s5_items);  // NEW
}

Add Custom Filtering

Example: Filter by Priority

1. Add Filter UI:

<select id="priority-filter">
    <option value="">All Priorities</option>
    <option value="1">Urgent</option>
    <option value="2">High</option>
    <option value="3">Medium</option>
    <option value="4">Low</option>
</select>

2. Add Filter Logic:

def filter_tickets_by_priority(tickets, priority):
    if not priority:
        return tickets
    return [t for t in tickets if t.get('priority') == int(priority)]

3. Update Route:

@app.route('/<view_slug>')
def dashboard_typed(view_slug):
    agent_id = request.args.get('agent_id', type=int)
    priority = request.args.get('priority', type=int)

    s1, s2, s3, s4, last_sync_time = get_tickets_for_view(view_slug, agent_id)

    if priority:
        s1 = filter_tickets_by_priority(s1, priority)
        s2 = filter_tickets_by_priority(s2, priority)
        s3 = filter_tickets_by_priority(s3, priority)
        s4 = filter_tickets_by_priority(s4, priority)

    return render_template(...)

Monitoring & Observability

Health Checks

Beacon provides comprehensive health monitoring.

Endpoint: GET /health

Components Checked: 1. Disk Space: Usage percentage, free space 2. Core Service: Availability and response time 3. Codex Service: Availability and response time

Example Response (Healthy):

{
  "service": "beacon",
  "status": "healthy",
  "timestamp": "2025-11-22T10:30:00.000Z",
  "checks": {
    "disk": {
      "status": "healthy",
      "usage_percent": 45.67,
      "free_gb": 123.45,
      "total_gb": 250.0
    },
    "dependencies": {
      "core": {
        "status": "healthy",
        "response_time_ms": 15
      },
      "codex": {
        "status": "healthy",
        "response_time_ms": 42
      }
    }
  }
}

Critical Dependencies: - Codex: If unhealthy, dashboard shows no tickets - Core: If unhealthy, authentication fails


Logging

Beacon implements structured JSON logging.

Log Format:

{
  "timestamp": "2025-11-22T10:30:00.123Z",
  "level": "INFO",
  "service": "beacon",
  "correlation_id": "a1b2c3d4-e5f6-7890",
  "message": "Loading dashboard for view: Helpdesk",
  "view_slug": "helpdesk",
  "agent_id": 19000234567,
  "ticket_count": 47
}

View Logs:

cd hivematrix-helm
source pyenv/bin/activate

# View Beacon logs
python logs_cli.py beacon --tail 50

# Filter by level
python logs_cli.py beacon --level ERROR --tail 100


Troubleshooting

No Tickets Displayed

Symptoms: - Dashboard loads but shows empty sections - "No tickets currently in this category" for all sections

Causes & Solutions:

1. Codex Not Running:

cd hivematrix-helm
python cli.py status codex

# If down, start it:
python cli.py start codex

2. Tickets Not Synced:

# Check last sync time in Codex
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:5010/api/tickets/active | jq '.last_sync_time'

# If null or old, sync manually:
cd hivematrix-codex
source pyenv/bin/activate
python sync_psa.py --type tickets

# Check sync logs:
cd ../hivematrix-helm
python logs_cli.py codex --tail 50 | grep sync

3. PSA Not Configured:

# Check PSA config exists
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:5010/api/psa/config

# If empty, configure PSA in Codex settings

4. View Filter Mismatch:

# Check professional services group ID
# If all tickets in wrong view, update PROFESSIONAL_SERVICES_GROUP_ID
grep PROFESSIONAL_SERVICES_GROUP_ID app/__init__.py


Agent Names Show as "Unassigned" or IDs

Symptoms: - Agent column shows IDs instead of names - All tickets show "Unassigned"

Causes & Solutions:

1. Agents Not Synced:

# Sync agents from PSA
cd hivematrix-codex
source pyenv/bin/activate
python sync_psa.py --type agents

# Verify agents loaded:
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:5010/api/psa/agents | jq

2. Agent Mapping Not Loaded:

# Check Beacon logs for agent loading
cd hivematrix-helm
python logs_cli.py beacon --tail 50 | grep agent

# Should see: "Loaded 15 active agents from Codex"

# If not, restart Beacon:
python cli.py restart beacon

3. Agent External ID Mismatch:

# Check ticket responder_id matches agent external_id
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:5010/api/tickets/active | jq '.section1[0] | {responder_id, external_id}'

# If mismatch, resync agents and tickets


Dashboard Not Auto-Refreshing

Symptoms: - Dashboard loads initially but doesn't update - "Last Sync" timestamp doesn't change - Total count stays static

Causes & Solutions:

1. JavaScript Errors:

# Check browser console (F12)
# Look for errors in main.js

# Common errors:
# - fetch() missing credentials: 'same-origin'
# - CORS errors
# - Parse errors (invalid JSON)

2. API Endpoint Failing:

# Test API endpoint directly
curl -H "Authorization: Bearer $TOKEN" \
  https://localhost/beacon/api/tickets/helpdesk

# Should return JSON, not HTML
# If HTML, check authentication

3. Auto-Refresh Disabled:

// Check in browser console:
console.log(window.AUTO_REFRESH_MS);

// Should be: 60000 (60 seconds)

// Manually trigger refresh:
fetch(`/api/tickets/${currentView}`, {credentials: 'same-origin'})
  .then(r => r.json())
  .then(data => console.log(data));


Symptoms: - Clicking ticket ID does nothing - Links go to wrong PSA - 404 errors on ticket links

Causes & Solutions:

1. PSA Config Missing:

# Check PSA config
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:5010/api/psa/config | jq

# Should have ticket_url_template
# If missing, configure PSA in Codex

2. Ticket Base URL Wrong:

# Check Beacon logs for PSA URL
cd hivematrix-helm
python logs_cli.py beacon | grep "PSA"

# Should see: "Loaded PSA config with base URL: https://..."

# If wrong, update in Codex PSA settings

3. External ID Mismatch:

# Ticket links use external_id, not database id
# Verify external_id exists in ticket data:
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:5010/api/tickets/active | jq '.section1[0].external_id'

# If null, resync tickets


High Ticket Count (Siren Activating)

Symptoms: - Total active count unusually high - Siren indicators pulsing - Overwhelming number of tickets

Investigation:

1. Check Section Distribution:

# View ticket counts by section
# Section 3 should be minimal (0-5)
# If Section 3 has many tickets, SLA issues exist

# Check in browser console:
console.log({
    section1: document.querySelectorAll('#s1-items-body tr').length,
    section2: document.querySelectorAll('#s2-items-body tr').length,
    section3: document.querySelectorAll('#s3-items-body tr').length,
    section4: document.querySelectorAll('#s4-items-body tr').length
});

2. Review Codex Categorization:

# Check if tickets are categorized correctly
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:5010/api/tickets/active | jq '{
    s1: (.section1 | length),
    s2: (.section2 | length),
    s3: (.section3 | length),
    s4: (.section4 | length)
  }'

3. Sync Issues:

# If duplicate tickets or old tickets showing:
# Force full resync
cd hivematrix-codex
source pyenv/bin/activate
python sync_psa.py --type tickets --full-sync


Performance Issues

Symptoms: - Dashboard slow to load - Browser freezing - High memory usage

Causes & Solutions:

1. Too Many Tickets:

# If total > 500, consider filtering

# Option A: Increase page load by lazy-loading sections
# Option B: Paginate results
# Option C: Filter by date (only show last 30 days)

# Check current count:
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:5010/api/tickets/active | jq '.section1 + .section2 + .section3 + .section4 | length'

2. Large Descriptions:

# Ticket descriptions can be very large HTML
# Consider truncating in Codex API response

# Check description sizes:
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:5010/api/tickets/active | \
  jq '.section1[0].description | length'

3. Auto-Refresh Too Frequent:

# Increase interval from 60s to 120s
# In app/__init__.py:
AUTO_REFRESH_INTERVAL_SECONDS = 120  # 2 minutes


See Also

Architecture & Design

Configuration & Setup

External Resources

Tools & Utilities

  • Service CLI: hivematrix-helm/cli.py start|stop|restart beacon
  • Log Viewer: hivematrix-helm/logs_cli.py beacon --tail 50
  • Codex Sync: hivematrix-codex/sync_psa.py - Sync PSA tickets
  • Config Manager: hivematrix-helm/config_manager.py sync-all

Last Updated: 2025-11-22 Version: 1.0 Maintained By: HiveMatrix Team