Cookbook

Session Analytics

Real-time session metrics, advanced filtering, security insights, and performance analytics powered by SessionAnalytics and SessionQueryBuilder.

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: JWT, API Key, OAuth, SAML authentication analytics
  • 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:

  1. SessionAnalytics: Comprehensive analytics engine with caching and reporting
  2. SessionQueryBuilder: Advanced filtering and query capabilities
  3. SessionCacheManager: Session data management with analytics integration

SessionAnalytics Core Features

Basic Usage

use Glueful\Auth\SessionAnalytics;

// Get analytics instance
$analytics = new SessionAnalytics();

// 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
]);

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 = new SessionCacheManager($cache);

// 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 = new SessionCacheManager($cache);

// 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',
    'last_activity_older_than' => 3600
]);

// Bulk session updates
$updatedCount = $sessionManager->updateSessionsWhere(
    ['provider' => 'oauth'], 
    ['security_level' => 'high']
);

// Provider migration
$migratedCount = $sessionManager->migrateSessions('jwt', 'oauth');

// Transaction-based bulk operations
$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 = new SessionAnalytics();

// 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,
        'saml' => 22
    ],
    'cache_hit_ratio' => 0.95
]
*/

Real-time Dashboard Integration

// Dashboard endpoint implementation
function getDashboardMetrics() {
    $analytics = new SessionAnalytics();
    
    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 = new SessionAnalytics();

// 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 analysis
$customAnalysis = $analytics->getSessionAnalytics([
    'time_range' => [
        'from' => strtotime('2024-01-01'),
        'to' => strtotime('2024-01-31')
    ]
]);

Security Analytics

Comprehensive security monitoring and anomaly detection:

$analytics = new SessionAnalytics();

// 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',
    'concurrent_limit_exceeded' => true
]);

Performance Monitoring

Detailed performance analytics and optimization insights:

$analytics = new SessionAnalytics();

// 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() {
    $analytics = new SessionAnalytics();
    $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).
  • 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.
  • Duration buckets
    • Fixed buckets used for duration analysis: 0‑5min, 5‑15min, 15‑60min, 1‑6hrs, 6hrs+.
  • Session cache keys
    • Session data stored under session:<id>; provider indexes under provider:<name>.

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(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 processLargeDataset(): array
    {
        $sessionManager = app($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)
        ];
    }
}