RSS Git Download  Clone
Raw Blame History 4kB 103 lines
export default async (options) => {
    const {socket} = options

    try {
        const redis = socket.p3xrs.ioredis

        const [infoRaw, slowlog] = await Promise.all([
            redis.info(),
            redis.slowlog('GET', 10),
        ])

        // Parse INFO into sections
        const info = {}
        let currentSection = ''
        for (const line of infoRaw.split('\n')) {
            const trimmed = line.trim()
            if (!trimmed || trimmed.startsWith('#')) {
                if (trimmed.startsWith('# ')) {
                    currentSection = trimmed.slice(2).toLowerCase()
                    info[currentSection] = {}
                }
                continue
            }
            const colonIdx = trimmed.indexOf(':')
            if (colonIdx > 0) {
                const key = trimmed.slice(0, colonIdx)
                const value = trimmed.slice(colonIdx + 1)
                if (currentSection) {
                    info[currentSection][key] = value
                }
            }
        }

        // Extract key metrics
        const memory = info.memory || {}
        const stats = info.stats || {}
        const clients = info.clients || {}
        const server = info.server || {}
        const keyspace = info.keyspace || {}

        // Parse keyspace hit/miss
        const hits = parseInt(stats.keyspace_hits) || 0
        const misses = parseInt(stats.keyspace_misses) || 0
        const hitRate = hits + misses > 0 ? ((hits / (hits + misses)) * 100).toFixed(1) : '0.0'

        const data = {
            timestamp: Date.now(),
            server: {
                version: server.redis_version,
                uptime: parseInt(server.uptime_in_seconds) || 0,
                mode: server.redis_mode || 'standalone',
            },
            memory: {
                used: parseInt(memory.used_memory) || 0,
                usedHuman: memory.used_memory_human || '0B',
                rss: parseInt(memory.used_memory_rss) || 0,
                rssHuman: memory.used_memory_rss_human || '0B',
                peak: parseInt(memory.used_memory_peak) || 0,
                peakHuman: memory.used_memory_peak_human || '0B',
                fragRatio: parseFloat(memory.mem_fragmentation_ratio) || 0,
            },
            stats: {
                opsPerSec: parseInt(stats.instantaneous_ops_per_sec) || 0,
                totalCommands: parseInt(stats.total_commands_processed) || 0,
                hits,
                misses,
                hitRate: parseFloat(hitRate),
                inputKbps: parseFloat(stats.instantaneous_input_kbps) || 0,
                outputKbps: parseFloat(stats.instantaneous_output_kbps) || 0,
                totalNetInput: parseInt(stats.total_net_input_bytes) || 0,
                totalNetOutput: parseInt(stats.total_net_output_bytes) || 0,
                expiredKeys: parseInt(stats.expired_keys) || 0,
                evictedKeys: parseInt(stats.evicted_keys) || 0,
            },
            clients: {
                connected: parseInt(clients.connected_clients) || 0,
                blocked: parseInt(clients.blocked_clients) || 0,
                maxInput: parseInt(clients.client_recent_max_input_buffer) || 0,
                maxOutput: parseInt(clients.client_recent_max_output_buffer) || 0,
            },
            keyspace,
            slowlog: slowlog.map(entry => ({
                id: entry[0],
                timestamp: entry[1],
                duration: entry[2],
                command: Array.isArray(entry[3]) ? entry[3].join(' ') : String(entry[3]),
            })),
        }

        socket.emit(options.responseEvent, {
            status: 'ok',
            data,
        })

    } catch (e) {
        console.error(e)
        socket.emit(options.responseEvent, {
            status: 'error',
            error: e.message,
        })
    }
}