Session Analytics
This comprehensive guide covers Glueful's sophisticated session analytics system, which provides real-time monitoring, comprehensive reporting, security analysis, and performance insights for session management across multiple authentication providers.
Overview
Glueful's Session Analytics system provides enterprise-grade monitoring and analysis capabilities for session management. The system tracks usage patterns, security metrics, performance indicators, and user behavior across multiple authentication providers.
Key Features
- Real-time Session Metrics: Live monitoring with 1-minute cache optimization
- Advanced Query Builder: SQL-like interface for complex session filtering
- Security Event Tracking: Geographic anomaly detection and suspicious activity monitoring
- Performance Analytics: Session duration analysis, concurrent session monitoring, and cache optimization
- Multi-Provider Support: Analytics across authentication providers (JWT, API key, OAuth, and any custom provider)
- Geographic Distribution: IP-based location tracking and device analytics
- Historical Trend Analysis: Configurable time-range analysis with trend reporting
- User Activity Patterns: Hourly/weekly distribution and engagement analysis
Architecture
The session analytics system consists of three main components:
- SessionAnalytics: Comprehensive analytics engine with caching and reporting
- SessionQueryBuilder: Advanced filtering and query capabilities
- SessionCacheManager: Session data management with analytics integration
SessionAnalytics Core Features
Basic Usage
use Glueful\Auth\SessionAnalytics;
// Resolve from the container (it is autowired with the cache store and SessionCacheManager)
$analytics = app($context, SessionAnalytics::class);
// Get comprehensive session analytics
$report = $analytics->getSessionAnalytics();
// Apply filters for specific analysis
$filteredReport = $analytics->getSessionAnalytics([
'provider' => 'jwt',
'min_activity' => 300 // Active in last 5 minutes
]);
$context is the ApplicationContext (in a controller, $this->context). getSessionAnalytics() supports two filters, provider and min_activity; for anything richer use findSessionsWithCriteria() or the SessionQueryBuilder below. SessionAnalytics and SessionCacheManager are container services, so resolve them rather than constructing them by hand.
Comprehensive Analytics Report
The getSessionAnalytics() method returns a comprehensive report including:
[
'timestamp' => 1640995200,
'total_sessions' => 1247,
'active_sessions' => 892, // Active in last 5 minutes
'idle_sessions' => 234, // 5 minutes to 1 hour
'expired_sessions' => 121, // Over 1 hour idle
'by_provider' => [
'jwt' => [
'count' => 850,
'active' => 620,
'idle' => 180,
'avg_duration' => 3600.5,
'total_duration' => 3060425
],
'apikey' => [
'count' => 287,
'active' => 200,
'idle' => 87,
'avg_duration' => 7200.3,
'total_duration' => 2066486
]
],
'by_user_role' => [
'admin' => [
'session_count' => 45,
'unique_user_count' => 12,
'avg_activity' => 1200.5
],
'user' => [
'session_count' => 1180,
'unique_user_count' => 890,
'avg_activity' => 890.2
]
],
'by_time_range' => [
'last_5_minutes' => [
'new_sessions' => 23,
'active_sessions' => 892,
'unique_user_count' => 654
],
'last_15_minutes' => [
'new_sessions' => 67,
'active_sessions' => 945,
'unique_user_count' => 723
]
],
'geographic_distribution' => [
'countries' => [
'United States' => 567,
'Canada' => 234,
'United Kingdom' => 189
],
'cities' => [
'United States/New York' => 234,
'Canada/Toronto' => 123,
'United Kingdom/London' => 189
],
'ip_ranges' => [
'192.168.x.x' => 45,
'10.0.x.x' => 23
]
],
'device_types' => [
'devices' => [
'desktop' => 823,
'mobile' => 345,
'tablet' => 79
],
'browsers' => [
'chrome' => 567,
'firefox' => 234,
'safari' => 189
],
'platforms' => [
'windows' => 456,
'macos' => 234,
'linux' => 123
]
],
'security_events' => [
'failed_logins' => ['count' => 12, 'unique_ips' => 8],
'suspicious_locations' => ['count' => 3, 'locations' => []],
'concurrent_sessions_violations' => ['count' => 5, 'users' => []],
'session_hijacking_attempts' => ['count' => 0, 'patterns' => []],
'unusual_activity_patterns' => ['count' => 2, 'patterns' => []]
],
'performance_metrics' => [
'avg_session_duration' => 2834.5,
'peak_concurrent_sessions' => 1456,
'session_creation_rate' => 12.5,
'cache_hit_ratio' => 0.95,
'avg_requests_per_session' => 23.4,
'memory_usage_mb' => 45.2
],
'user_activity' => [
'most_active_users' => [
'user-123' => [
'session_count' => 8,
'total_duration' => 28800,
'last_seen' => 1640995180,
'first_seen' => 1640908800
]
],
'hourly_distribution' => [0, 5, 12, 23, 45, 67, 89, 234, ...], // 24 hours
'weekly_distribution' => [234, 567, 445, 678, 789, 456, 234], // 7 days
'total_unique_users' => 892
],
'session_duration' => [
'avg_duration' => 2834.5,
'median_duration' => 1800.0,
'min_duration' => 30,
'max_duration' => 28800,
'duration_buckets' => [
'0-5min' => 234,
'5-15min' => 345,
'15-60min' => 456,
'1-6hrs' => 189,
'6hrs+' => 23
]
],
'concurrent_sessions' => [
'users_with_multiple_sessions' => 45,
'max_sessions_per_user' => 5,
'avg_sessions_per_user' => 1.4,
'concurrency_distribution' => [
1 => 847, // 847 users with 1 session
2 => 34, // 34 users with 2 sessions
3 => 8, // 8 users with 3 sessions
4 => 2, // 2 users with 4 sessions
5 => 1 // 1 user with 5 sessions
]
],
'analysis_duration_ms' => 234.5
]
SessionQueryBuilder Advanced Filtering
The SessionQueryBuilder provides SQL-like filtering capabilities for complex session analysis:
Basic Filtering
use Glueful\Auth\SessionCacheManager;
$sessionManager = app($context, SessionCacheManager::class);
// Create query builder
$query = $sessionManager->sessionQuery();
// Filter by provider
$jwtSessions = $query->whereProvider('jwt')->get();
// Filter by multiple providers
$apiSessions = $query->whereProviderIn(['apikey', 'oauth'])->get();
// Filter by user role
$adminSessions = $query->whereUserRole('admin')->get();
// Filter by user permission
$moderatorSessions = $query->whereUserHasPermission('moderate_content')->get();
Time-based Filtering
// Sessions active in last 5 minutes
$recentSessions = $query->whereLastActivityWithin(300)->get();
// Sessions idle for more than 1 hour
$idleSessions = $query->whereLastActivityOlderThan(3600)->get();
// Sessions created in date range
$rangeSessions = $query->whereCreatedBetween(
strtotime('2024-01-01'),
strtotime('2024-01-31')
)->get();
Advanced Filtering
// Geographic filtering
$localSessions = $query->whereIpAddressLike('192.168.*')->get();
// Device filtering
$mobileSessions = $query->whereUserAgentLike('Mobile')->get();
// Role-based filtering
$privilegedSessions = $query->whereUserHasAnyRole(['admin', 'moderator'])->get();
// Note: Role filters expect session roles to be objects with a `name` field.
// If your roles are stored as plain strings, normalize when storing sessions
// (e.g., ['roles' => [['name' => 'admin']]]).
// Custom filtering with callbacks
$complexSessions = $query->where(function($session) {
return ($session['request_count'] ?? 0) > 50 &&
isset($session['user']['permissions']['manage_users']);
})->get();
Query Building and Optimization
// Complex query with sorting and pagination
$sessions = $query
->whereProvider('jwt')
->whereLastActivityWithin(3600)
->whereUserHasAnyRole(['admin', 'user'])
->orderBy('last_activity', 'desc')
->paginate(1, 50) // Page 1, 50 per page
->get();
// Count matching sessions
$count = $query->whereProvider('jwt')->count();
// Get first matching session
$session = $query->whereUser('user-uuid-123')->first();
// Check if sessions exist
$hasActiveSessions = $query->whereLastActivityWithin(300)->exists();
// Debug query (SQL-like representation)
$sqlRepresentation = $query->toSql();
// Output: "SELECT * FROM sessions WHERE provider = jwt AND last_activity >= 1640991600 ORDER BY last_activity DESC LIMIT 50"
Nested Conditions
// Complex OR conditions
$complexQuery = $query
->whereProvider('jwt')
->orWhere(function($subQuery) {
$subQuery->whereProvider('apikey')
->whereUserRole('admin');
})
->get();
// Nested AND conditions
$nestedQuery = $query
->whereSessions(function($subQuery) {
$subQuery->whereLastActivityWithin(300)
->whereUserHasPermission('admin_access');
})
->get();
SessionCacheManager Integration
SessionCacheManager provides session data management with built-in analytics integration:
Session Lifecycle Analytics
use Glueful\Auth\SessionCacheManager;
$sessionManager = app($context, SessionCacheManager::class);
// Store session with provider tracking
$success = $sessionManager->storeSession(
$userData,
$token,
'jwt', // Provider for analytics tracking
3600 // Custom TTL
);
// Provider-based session retrieval
$jwtSessions = $sessionManager->getSessionsByProvider('jwt');
$apiKeySessions = $sessionManager->getSessionsByProvider('apikey');
// User session analytics
$userSessions = $sessionManager->getUserSessions($userUuid);
$sessionCount = $sessionManager->getUserSessionCount($userUuid);
// Bulk operations with analytics
$terminatedCount = $sessionManager->terminateAllUserSessions($userUuid);
Advanced Session Operations
// Bulk session invalidation with criteria
$invalidatedCount = $sessionManager->invalidateSessionsWhere([
'provider' => 'jwt',
'idle_time' => '>3600' // idle for more than an hour
]);
// Bulk session updates
$updatedCount = $sessionManager->updateSessionsWhere(
['provider' => 'oauth'],
['security_level' => 'high']
);
// Provider migration
$migratedCount = $sessionManager->migrateSessions('jwt', 'oauth');
// Transaction-based bulk operations (transaction() has already called begin())
$transaction = $sessionManager->transaction();
try {
$sessionIds = $transaction->createSessions($bulkSessionData);
$transaction->commit();
} catch (Exception $e) {
$transaction->rollback();
throw $e;
}
Real-time Metrics
Real-time metrics provide immediate insights with 1-minute caching for optimal performance:
$analytics = app($context, \Glueful\Auth\SessionAnalytics::class);
// Get real-time metrics (cached for 1 minute)
$realTimeMetrics = $analytics->getRealTimeMetrics();
/*
[
'timestamp' => 1640995200,
'total_active' => 892,
'sessions_last_minute' => 12,
'sessions_last_hour' => 167,
'unique_users' => 654,
'avg_session_age' => 2834.5,
'peak_concurrent' => 1456,
'providers' => [
'jwt' => 620,
'apikey' => 200,
'oauth' => 50,
],
'cache_hit_ratio' => 0.95
]
*/
Real-time Dashboard Integration
use Glueful\Bootstrap\ApplicationContext;
// Dashboard endpoint implementation
function getDashboardMetrics(ApplicationContext $context): array {
$analytics = app($context, \Glueful\Auth\SessionAnalytics::class);
return [
'real_time' => $analytics->getRealTimeMetrics(),
'hourly_trend' => $analytics->getSessionTrends(6, 30), // Last 6 hours, 30-min intervals
'security_alerts' => $analytics->getSecurityEvents(1), // Last hour
];
}
Historical Analysis
Comprehensive historical trend analysis with configurable time ranges:
$analytics = app($context, \Glueful\Auth\SessionAnalytics::class);
// Get session trends
$trends = $analytics->getSessionTrends(
24, // Last 24 hours
60 // 60-minute intervals
);
/*
[
[
'timestamp' => 1640908800,
'active_sessions' => 567,
'new_sessions' => 23,
'terminated_sessions' => 12
],
[
'timestamp' => 1640912400,
'active_sessions' => 623,
'new_sessions' => 45,
'terminated_sessions' => 8
]
// ... more data points
]
*/
// Weekly trends
$weeklyTrends = $analytics->getSessionTrends(
168, // 7 days * 24 hours
360 // 6-hour intervals
);
// Custom time range: getSessionAnalytics() only understands the `provider` and
// `min_activity` filters, so select a date range with findSessionsWithCriteria()
$januarySessions = $analytics->findSessionsWithCriteria([
'time_range' => [
'from' => strtotime('2024-01-01'),
'to' => strtotime('2024-01-31')
]
]);
Security Analytics
Comprehensive security monitoring and anomaly detection:
$analytics = app($context, \Glueful\Auth\SessionAnalytics::class);
// Get security events for last 24 hours
$securityEvents = $analytics->getSecurityEvents(24);
/*
[
'failed_logins' => [
'count' => 45,
'unique_ips' => 23
],
'suspicious_locations' => [
'count' => 8,
'locations' => [
['country' => 'Unknown', 'ip' => '192.168.1.100', 'attempts' => 3],
['country' => 'Russia', 'ip' => '203.45.67.89', 'attempts' => 5]
]
],
'concurrent_sessions_violations' => [
'count' => 12,
'users' => ['user-uuid-1', 'user-uuid-2']
],
'session_hijacking_attempts' => [
'count' => 2,
'patterns' => [
'ip_change_pattern',
'user_agent_mismatch'
]
],
'unusual_activity_patterns' => [
'count' => 5,
'patterns' => [
'rapid_location_change',
'excessive_api_calls',
'off_hours_activity'
]
]
]
*/
Complex Security Filtering
// Find suspicious sessions
$suspiciousSessions = $analytics->findSessionsWithCriteria([
'ip_range' => [
'start' => '192.168.1.1',
'end' => '192.168.1.255'
],
'user_agent_pattern' => 'bot',
'time_range' => [
'from' => strtotime('-2 hours'),
'to' => time()
],
'activity_threshold' => [
'min_requests' => 100
],
'geographic_constraint' => [
'allowed_countries' => ['US', 'CA', 'GB']
]
]);
// Security audit for specific users
$userSecurityProfile = $analytics->findSessionsWithCriteria([
'permission_combinations' => ['admin_access', 'user_management'],
'security_level' => 'high'
]);
Performance Monitoring
Detailed performance analytics and optimization insights:
$analytics = app($context, \Glueful\Auth\SessionAnalytics::class);
// Get performance metrics from comprehensive analytics
$fullAnalytics = $analytics->getSessionAnalytics();
$performanceMetrics = $fullAnalytics['performance_metrics'];
/*
[
'avg_session_duration' => 2834.5, // Average session length in seconds
'peak_concurrent_sessions' => 1456, // Highest concurrent session count
'session_creation_rate' => 12.5, // Sessions created per minute
'cache_hit_ratio' => 0.95, // Cache efficiency (95%)
'avg_requests_per_session' => 23.4, // Request activity per session
'memory_usage_mb' => 45.2 // Current memory usage
]
*/
// Session duration analysis
$durationAnalysis = $fullAnalytics['session_duration'];
/*
[
'avg_duration' => 2834.5,
'median_duration' => 1800.0,
'min_duration' => 30,
'max_duration' => 28800,
'duration_buckets' => [
'0-5min' => 234, // Short sessions
'5-15min' => 345, // Quick interactions
'15-60min' => 456, // Normal sessions
'1-6hrs' => 189, // Long sessions
'6hrs+' => 23 // Extended sessions
]
]
*/
Performance Optimization Insights
// Identify performance bottlenecks
function analyzePerformanceBottlenecks(ApplicationContext $context): array {
$analytics = app($context, \Glueful\Auth\SessionAnalytics::class);
$metrics = $analytics->getSessionAnalytics();
$insights = [];
// Cache efficiency analysis
if ($metrics['performance_metrics']['cache_hit_ratio'] < 0.85) {
$insights[] = 'Cache hit ratio is low. Consider increasing cache TTL or optimizing cache keys.';
}
// Session duration analysis
$longSessions = $metrics['session_duration']['duration_buckets']['6hrs+'];
if ($longSessions > 50) {
$insights[] = "High number of extended sessions ({$longSessions}). Check for session timeout configuration.";
}
// Concurrent session analysis
$avgConcurrent = $metrics['concurrent_sessions']['avg_sessions_per_user'];
if ($avgConcurrent > 2.0) {
$insights[] = "High average concurrent sessions per user ({$avgConcurrent}). Consider implementing session limits.";
}
return $insights;
}
Configuration
Current Configuration Points
- Session TTL
- Default TTL comes from
config($context, 'session.access_token_lifetime'). - Per‑provider TTL from
config($context, 'security.authentication_providers.*.session_ttl')(e.g., JWT/API key/OAuth).
- Default TTL comes from
- Analytics cache
- Analytics cache prefix is fixed to
session_analytics:. - Full analytics are cached for 1 hour; real‑time metrics are computed on demand in current implementation.
- Analytics cache prefix is fixed to
- Duration buckets
- Fixed buckets used for duration analysis:
0‑5min,5‑15min,15‑60min,1‑6hrs,6hrs+.
- Fixed buckets used for duration analysis:
- Session cache keys
- Session data stored under
session:<id>; provider indexes underprovider:<name>.
- Session data stored under
Note: Environment variables like SESSION_ANALYTICS_* and a config/session_analytics.php file are not used in the current implementation.
Production Optimization
High-Volume Environments
// Optimized analytics for high-volume production
function getOptimizedAnalytics(ApplicationContext $context, array $filters = []): array
{
// Use DI cache store for caching
$cache = app($context, 'cache.store');
$analytics = app($context, Glueful\Auth\SessionAnalytics::class);
$cacheKey = 'analytics:optimized:' . md5(json_encode($filters));
if ($cached = $cache->get($cacheKey)) {
return $cached;
}
// In very large datasets, consider sampling via SessionQueryBuilder
$result = $analytics->getSessionAnalytics($filters);
$cache->set($cacheKey, $result, 300); // cache 5 minutes
return $result;
}
Memory Optimization
// Memory-efficient session processing
class MemoryOptimizedAnalytics
{
public function __construct(private ApplicationContext $context) {}
public function processLargeDataset(): array
{
$sessionManager = app($this->context, Glueful\Auth\SessionCacheManager::class);
$query = $sessionManager->sessionQuery()->whereProvider('jwt');
$page = 1;
$perPage = 1000;
$results = [];
do {
$pageResults = $query->paginate($page, $perPage)->get();
if ($pageResults === []) {
break;
}
// Process page
$results[] = count($pageResults);
$page++;
gc_collect_cycles();
} while (count($pageResults) === $perPage);
return [
'pages_processed' => $page - 1,
'sessions_processed' => array_sum($results)
];
}
}
Related Pages
- Authentication: how sessions are created and refreshed
- Browser Sessions: cookie-based sessions for browser clients
- API Keys: key-authenticated requests, which carry their own scopes
- Caching: the cache store that backs the session cache