Beacon - Real-Time Ticket Dashboard¶
Port: 5001 Database: None (stateless, consumes Codex API) Repository: hivematrix-beacon Version: 1.0
Table of Contents¶
- Overview
- Architecture
- Design Philosophy
- Technology Stack
- Data Flow
- Features
- Dual Dashboard Views
- Ticket Categorization
- Visual Indicators
- Agent Filtering
- Auto-Refresh
- Sortable Tables
- API Reference
- Web Routes
- API Endpoints
- Public Endpoints
- Integration
- Codex Dependency
- Service Communication
- PSA Integration
- Configuration
- Environment Variables
- View Configuration
- Professional Services Setup
- User Interface
- Dashboard Layout
- Ticket Sections
- Filtering
- Column Sorting
- Development
- Running Locally
- File Structure
- Adding Features
- Monitoring & Observability
- Health Checks
- Logging
- Troubleshooting
- See Also
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?
- Single Source of Truth:
- Codex is the master data repository
- Beacon always shows current Codex data
-
No discrepancies between services
-
No Duplicate API Calls:
- Only Codex talks to PSA systems
- Respects API rate limits
-
Reduces PSA load
-
Consistent Data:
- All services see same ticket data
- Categorization logic centralized in Codex
-
Changes to sync logic don't affect Beacon
-
Simple Deployment:
- No database to manage
- Stateless = easy horizontal scaling
- 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:
Sirens pulse if count > 30Agent 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:
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:
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:
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:
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:
- Add to
SUPPORTED_VIEWSdict - Update
filter_tickets_by_view()function - Define filtering logic (e.g., by group_id, tags, etc.)
- Add navigation tab in template
- Restart Beacon
Professional Services Setup¶
Configuration:
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:
- Find professional services group/board ID in your PSA
- Update
PROFESSIONAL_SERVICES_GROUP_IDconstant - Restart Beacon
- 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:
- User selects agent from dropdown
- JavaScript calls:
- Page reloads with filtered data
- All 4 sections show only selected agent's tickets
- Filter persists across refreshes
"All Agents" Option:
- Removes agent_id parameter
- Shows all tickets
- Default state
URL Examples:
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:
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));
Ticket Links Not Working¶
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¶
Related Services¶
- Codex - Master Data - PSA ticket data source and sync
- Core - Authentication - JWT authentication and session management
- Nexus - Gateway - Frontend proxy and routing
- Helm - Orchestration - Service management and centralized logging
- All Services - Complete service inventory
Architecture & Design¶
- Authentication Flow
- Service-to-Service Communication
- Frontend Architecture
- Dashboard Design Patterns
Configuration & Setup¶
- Installation Guide - Complete installation walkthrough
- Configuration Guide - Environment variables and PSA setup
- Codex PSA Configuration - PSA provider 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