SOLR Dashboard Management - Technical Implementation
Overview
The SOLR Dashboard Management system provides comprehensive monitoring and management capabilities for Apache SOLR search infrastructure in OpenRegister. It offers real-time statistics, health monitoring, and administrative operations through a unified web interface.
Architecture Components
Frontend Implementation
SolrDashboard.vue Component
Location: src/views/settings/SolrDashboard.vue
The main dashboard component providing comprehensive SOLR monitoring and management interface.
Key Features:
- Real-time statistics display with auto-refresh (30s intervals)
- Interactive management controls (warmup, commit, optimize, clear)
- Responsive design with Nextcloud UI components
- Error handling with graceful fallbacks
Component Structure:
<template>
<!-- Overview Cards -->
<div class="solr-overview-cards">
<!-- Connection, Documents, Index Size, Performance -->
</div>
<!-- Core Information -->
<div class="solr-cores-grid">
<!-- Active core details, tenant info -->
</div>
<!-- Performance Metrics -->
<div class="performance-grid">
<!-- Search/Index operations, error rates -->
</div>
<!-- Health & Resources -->
<div class="health-grid">
<!-- System status, memory/disk usage -->
</div>
<!-- Operations Management -->
<div class="operations-grid">
<!-- Recent activity, queue status, commit settings -->
</div>
</template>
Data Structure:
data() {
return {
solrStats: {
overview: {
available: false,
connection_status: 'unknown',
response_time_ms: 0,
total_documents: 0,
index_size: '0 B',
last_commit: null,
},
cores: {
active_core: 'unknown',
core_status: 'inactive',
tenant_id: 'unknown',
endpoint_url: 'N/A',
},
performance: {
total_searches: 0,
total_indexes: 0,
total_deletes: 0,
avg_search_time_ms: 0,
avg_index_time_ms: 0,
operations_per_sec: 0,
error_rate: 0,
},
health: {
status: 'unknown',
uptime: 'N/A',
memory_usage: { used: 'N/A', max: 'N/A', percentage: 0 },
disk_usage: { used: 'N/A', available: 'N/A', percentage: 0 },
warnings: [],
last_optimization: null,
},
operations: {
recent_activity: [],
queue_status: { pending_operations: 0, processing: false },
commit_frequency: { auto_commit: false, commit_within: 0 },
optimization_needed: false,
}
}
}
}
Backend Implementation
API Endpoints
Dashboard Statistics Endpoint
/**
* GET /api/solr/dashboard/stats
*
* Returns comprehensive SOLR dashboard statistics including:
* - Connection status and performance
* - Core information and configuration
* - Performance metrics and error rates
* - Health indicators and resource usage
* - Recent operations and queue status
*/
public function getSolrDashboardStats(): JSONResponse
Management Operations Endpoint
/**
* POST /api/solr/manage/{operation}
*
* Performs SOLR management operations:
* - commit: Force index commit
* - optimize: Index optimization
* - clear: Clear entire index
* - warmup: Index warmup operations
*/
public function manageSolr(string $operation): JSONResponse
Connection Testing Endpoint
/**
* GET /api/solr/test
*
* Tests SOLR connectivity and returns detailed status
*/
public function testSolrConnection(): JSONResponse
Service Layer Architecture
SolrService Enhancements
New Methods Added:
/**
* Get comprehensive dashboard statistics
*
* @return array Complete dashboard metrics
*/
public function getDashboardStats(): array
{
return [
'overview' => $this->getOverviewStats(),
'cores' => $this->getCoreInformation(),
'performance' => $this->getPerformanceMetrics(),
'health' => $this->getHealthIndicators(),
'operations' => $this->getOperationsStatus(),
'generated_at' => date('c'),
];
}
/**
* Get document count from SOLR core
*/
public function getDocumentCount(): int
/**
* Get approximate index size
*/
public function getIndexSize(): string
/**
* Warm up SOLR index with sample operations
*/
public function warmupIndex(): array
/**
* Calculate operations per second
*/
private function calculateOperationsPerSecond(): float
/**
* Calculate error rate percentage
*/
private function calculateErrorRate(): float
/**
* Get overall health status
*/
private function getHealthStatus(): string
Statistics Collection:
The service collects comprehensive metrics through various methods:
Data Flow Architecture
Statistics Collection Flow
Management Operation Flow
Performance Optimizations
Lazy Loading Implementation
/**
* SolrService implements lazy initialization to prevent
* performance bottlenecks during application startup
*/
class SolrService
{
private bool $clientInitialized = false;
private function ensureClientInitialized(): void
{
if (!$this->clientInitialized) {
$this->initializeClient();
$this->clientInitialized = true;
}
}
public function getDashboardStats(): array
{
$this->ensureClientInitialized();
// ... statistics collection
}
}
Parallel Statistics Collection
/**
* Dashboard statistics are collected in parallel
* to minimize response times
*/
public function getDashboardStats(): array
{
$this->ensureClientInitialized();
// Collect base statistics
$baseStats = $this->getStats();
$connection = $this->testConnection();
// Parallel collection of different metric types
return [
'overview' => $this->buildOverviewStats($baseStats, $connection),
'cores' => $this->buildCoreStats($connection),
'performance' => $this->buildPerformanceStats($baseStats),
'health' => $this->buildHealthStats($baseStats, $connection),
'operations' => $this->buildOperationsStats($baseStats),
'generated_at' => date('c'),
];
}
Frontend Optimization Strategies
Auto-Refresh Management
// Intelligent refresh scheduling
mounted() {
this.loadSolrStats()
this.refreshInterval = setInterval(() => {
// Only refresh when not performing operations
if (!this.loading && !this.operating && !this.warmingUp) {
this.loadSolrStats()
}
}, 30000)
},
beforeDestroy() {
if (this.refreshInterval) {
clearInterval(this.refreshInterval)
}
}
Error Handling with Graceful Fallbacks
async loadSolrStats() {
this.loadingStats = true
try {
const response = await fetch('/index.php/apps/openregister/api/solr/dashboard/stats')
const data = await response.json()
if (data.error) {
console.error('Failed to load SOLR stats:', data.error)
// Dashboard shows unavailable state
return
}
this.solrStats = { ...this.solrStats, ...data }
} catch (error) {
console.error('Failed to load SOLR stats:', error)
// Graceful degradation to offline state
} finally {
this.loadingStats = false
}
}
Error Handling & Resilience
Service Layer Error Handling
/**
* Comprehensive error handling with graceful degradation
*/
public function getSolrDashboardStats(): array
{
try {
$objectCacheService = $this->container->get(ObjectCacheService::class);
return $objectCacheService->getSolrDashboardStats();
} catch (\Exception $e) {
// Return safe default structure when SOLR unavailable
return [
'overview' => [
'available' => false,
'connection_status' => 'unavailable',
// ... safe defaults
],
// ... complete fallback structure
'error' => $e->getMessage()
];
}
}
Frontend Error States
<!-- Loading State -->
<div v-if="loadingStats" class="loading-container">
<NcLoadingIcon :size="64" />
<p>Loading SOLR statistics...</p>
</div>
<!-- Error State -->
<div v-else-if="solrStats.error" class="error-container">
<div class="error-message">
<h3>SOLR Unavailable</h3>
<p>{{ solrStats.error }}</p>
<NcButton @click="loadSolrStats">Retry</NcButton>
</div>
</div>
<!-- Normal State -->
<div v-else class="solr-content">
<!-- Dashboard content -->
</div>
Security Considerations
API Endpoint Protection
/**
* All dashboard endpoints require admin privileges
*
* @NoAdminRequired - NOT used for management operations
* @NoCSRFRequired - Used for read-only operations only
*/
class SettingsController extends Controller
{
public function getSolrDashboardStats(): JSONResponse
{
// Admin-only access enforced by Nextcloud
}
public function manageSolr(string $operation): JSONResponse
{
// Restricted operations with validation
if (!in_array($operation, ['commit', 'optimize', 'clear', 'warmup'])) {
return new JSONResponse(['error' => 'Invalid operation'], 400);
}
}
}
Tenant Isolation
/**
* All SOLR operations are tenant-aware
*/
class SolrService
{
private function buildQueryString(array $searchParams): string
{
// Always enforce tenant isolation
$tenantFilter = sprintf('tenant_id:%s', $this->escapeSolrValue($this->tenantId));
// Combine with user query
return sprintf('(%s) AND %s', $userQuery, $tenantFilter);
}
}
Testing Strategy
Unit Testing
/**
* Test dashboard statistics collection
*/
class SolrDashboardTest extends TestCase
{
public function testGetDashboardStatsWithAvailableSolr()
{
$solrService = $this->createMock(SolrService::class);
$solrService->method('getDashboardStats')->willReturn([
'overview' => ['available' => true],
// ... complete test data
]);
$result = $this->settingsService->getSolrDashboardStats();
$this->assertTrue($result['overview']['available']);
}
public function testGetDashboardStatsWithUnavailableSolr()
{
$solrService = $this->createMock(SolrService::class);
$solrService->method('getDashboardStats')->willThrowException(
new \RuntimeException('SOLR unavailable')
);
$result = $this->settingsService->getSolrDashboardStats();
$this->assertFalse($result['overview']['available']);
$this->assertArrayHasKey('error', $result);
}
}
Integration Testing
#!/bin/bash
# Test SOLR dashboard endpoints
echo "Testing SOLR Dashboard Integration..."
# Test dashboard stats endpoint
echo "1. Testing dashboard statistics..."
docker exec -u 33 master-nextcloud-1 curl -s -u 'admin:admin' \
-H 'Content-Type: application/json' \
'http://localhost/index.php/apps/openregister/api/solr/dashboard/stats' | jq .overview.available
# Test connection testing endpoint
echo "2. Testing connection test..."
docker exec -u 33 master-nextcloud-1 curl -s -u 'admin:admin' \
'http://localhost/index.php/apps/openregister/api/solr/test' | jq .connection.success
# Test management operations
echo "3. Testing warmup operation..."
docker exec -u 33 master-nextcloud-1 curl -s -u 'admin:admin' \
-X POST -H 'Content-Type: application/json' \
'http://localhost/index.php/apps/openregister/api/solr/manage/warmup' | jq .success
echo "SOLR Dashboard Integration Tests Complete!"
Frontend Testing
/**
* Vue component testing with Vue Test Utils
*/
import { mount } from '@vue/test-utils'
import SolrDashboard from '@/views/settings/SolrDashboard.vue'
describe('SolrDashboard.vue', () => {
test('displays loading state initially', () => {
const wrapper = mount(SolrDashboard)
expect(wrapper.find('.loading-container').exists()).toBe(true)
})
test('displays dashboard when data loaded', async () => {
const wrapper = mount(SolrDashboard)
// Mock API response
wrapper.vm.solrStats = mockSolrStats
wrapper.vm.loadingStats = false
await wrapper.vm.$nextTick()
expect(wrapper.find('.solr-content').exists()).toBe(true)
})
test('handles management operations', async () => {
const wrapper = mount(SolrDashboard)
// Mock successful warmup
wrapper.vm.warmupIndex = jest.fn().mockResolvedValue()
await wrapper.find('.warmup-button').trigger('click')
expect(wrapper.vm.warmupIndex).toHaveBeenCalled()
})
})
Deployment & Configuration
Environment Requirements
# docker-compose.yml additions
services:
solr:
image: solr:9-slim
container_name: openregister-solr
restart: always
ports:
- "8983:8983"
volumes:
- solr:/var/solr
environment:
- SOLR_HEAP=512m
- SOLR_LOG_LEVEL=WARN
healthcheck:
test: ['CMD-SHELL', 'curl -f http://localhost:8983/solr/openregister/admin/ping || exit 1']
interval: 30s
timeout: 10s
retries: 3
Configuration Settings
/**
* Default SOLR dashboard configuration
*/
private function getDefaultSolrSettings(): array
{
return [
'enabled' => false, // Disabled by default for safety
'host' => 'solr',
'port' => 8983,
'scheme' => 'http',
'path' => '/solr',
'core' => 'openregister',
'timeout' => 30,
'autoCommit' => true,
'commitWithin' => 1000,
'enableLogging' => false,
'dashboard_refresh_interval' => 30,
];
}
Monitoring Setup
#!/bin/bash
# SOLR Dashboard monitoring script
# Check dashboard health
check_dashboard_health() {
local response=$(docker exec -u 33 master-nextcloud-1 curl -s -u 'admin:admin' \
'http://localhost/index.php/apps/openregister/api/solr/dashboard/stats' | jq -r '.overview.connection_status')
if [ "$response" != "healthy" ]; then
echo "ALERT: SOLR Dashboard reports unhealthy status: $response"
# Send alert notification
else
echo "OK: SOLR Dashboard healthy"
fi
}
# Monitor performance metrics
check_performance() {
local error_rate=$(docker exec -u 33 master-nextcloud-1 curl -s -u 'admin:admin' \
'http://localhost/index.php/apps/openregister/api/solr/dashboard/stats' | jq -r '.performance.error_rate')
if (( $(echo "$error_rate > 5.0" | bc -l) )); then
echo "ALERT: High SOLR error rate: $error_rate%"
fi
}
# Run monitoring checks
check_dashboard_health
check_performance
Best Practices & Recommendations
Development Guidelines
- Component Structure: Keep dashboard components modular and focused
- Error Handling: Always provide graceful fallbacks for SOLR unavailability
- Performance: Use lazy loading and parallel operations where possible
- Security: Ensure all management operations require proper authentication
- Testing: Comprehensive unit and integration testing for all operations
Production Deployment
- Monitoring: Set up alerting for SOLR availability and performance
- Resource Management: Monitor memory and disk usage trends
- Security: Restrict dashboard access to authorized administrators only
- Backup: Regular backup of SOLR cores and configuration
- Scaling: Monitor query performance and optimize as needed
Maintenance Tasks
# Weekly maintenance script
#!/bin/bash
# Check SOLR optimization status
optimization_needed=$(docker exec -u 33 master-nextcloud-1 curl -s -u 'admin:admin' \
'http://localhost/index.php/apps/openregister/api/solr/dashboard/stats' | \
jq -r '.operations.optimization_needed')
if [ "$optimization_needed" = "true" ]; then
echo "Running SOLR optimization..."
docker exec -u 33 master-nextcloud-1 curl -s -u 'admin:admin' \
-X POST 'http://localhost/index.php/apps/openregister/api/solr/manage/optimize'
fi
# Generate weekly performance report
echo "Generating SOLR performance report..."
docker exec -u 33 master-nextcloud-1 curl -s -u 'admin:admin' \
'http://localhost/index.php/apps/openregister/api/solr/dashboard/stats' | \
jq '.performance' > "solr_performance_$(date +%Y%m%d).json"
The SOLR Dashboard Management system provides a robust, scalable solution for monitoring and managing SOLR search infrastructure with enterprise-grade features and comprehensive error handling.