get_client_activity
Analyze client activity patterns in Valkey/Redis instances by retrieving time-bucketed connection counts, command distribution, and buffer usage data for performance monitoring and incident investigation.
Instructions
Get time-bucketed client activity from persisted snapshots. Shows connection counts, command distribution, and buffer usage over time. Use startTime/endTime to focus on a specific incident window.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| startTime | No | Start time (Unix timestamp ms) | |
| endTime | No | End time (Unix timestamp ms) | |
| bucketSizeMinutes | No | Bucket size in minutes (default 5) | |
| instanceId | No | Optional instance ID override |
Implementation Reference
- The core business logic that implements activity timeline aggregation by bucketing client snapshots.
async getActivityTimeline(params: ActivityTimelineParams, connectionId?: string): Promise<ActivityTimelineResponse> { const startTime = params.startTime || Date.now() - 60 * 60 * 1000; // 1 hour ago const endTime = params.endTime || Date.now(); const bucketSizeMinutes = params.bucketSizeMinutes || 5; const bucketSizeMs = bucketSizeMinutes * 60 * 1000; let snapshots: StoredClientSnapshot[]; try { snapshots = await this.storage.getClientSnapshots({ startTime, endTime, limit: MAX_SNAPSHOT_LIMIT, clientName: params.client, connectionId, }); } catch (error) { this.logger.error('Failed to fetch snapshots for activity timeline', error); throw new HttpException('Failed to fetch analytics data', HttpStatus.INTERNAL_SERVER_ERROR); } // Bucket the data const bucketMap = new Map<number, { clientNames: Set<string>; totalConnections: number; commandCounts: Map<string, number>; idleTimes: number[]; qbufValues: number[]; omemValues: number[]; }>(); for (const snapshot of snapshots) { const bucketTime = Math.floor(snapshot.capturedAt / bucketSizeMs) * bucketSizeMs; if (!bucketMap.has(bucketTime)) { bucketMap.set(bucketTime, { clientNames: new Set<string>(), totalConnections: 0, commandCounts: new Map<string, number>(), idleTimes: [], qbufValues: [], omemValues: [], }); } const bucket = bucketMap.get(bucketTime)!; - packages/mcp/src/index.ts:522-540 (registration)MCP tool registration and API proxy call for 'get_client_activity'.
server.tool( 'get_client_activity', 'Get time-bucketed client activity from persisted snapshots. Shows connection counts, command distribution, and buffer usage over time. Use startTime/endTime to focus on a specific incident window.', { startTime: z.number().optional().describe('Start time (Unix timestamp ms)'), endTime: z.number().optional().describe('End time (Unix timestamp ms)'), bucketSizeMinutes: z.number().optional().describe('Bucket size in minutes (default 5)'), instanceId: z.string().optional().describe('Optional instance ID override'), }, async ({ startTime, endTime, bucketSizeMinutes, instanceId }) => { const id = resolveInstanceId(instanceId); const qs = buildQuery({ startTime, endTime, bucketSizeMinutes }); const data = await apiFetch(`/mcp/instance/${id}/history/client-activity${qs}`); if (isLicenseError(data)) { return { content: [{ type: 'text' as const, text: licenseErrorResult(data) }] }; } return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }], }; - The API controller method that maps the 'get_client_activity' MCP request to the analysis service.
async getClientActivity( @Param('id', ValidateInstanceIdPipe) id: string, @Query('startTime') startTime?: string, @Query('endTime') endTime?: string, @Query('bucketSizeMinutes') bucketSizeMinutes?: string, ) { try { return await this.clientAnalyticsAnalysisService.getActivityTimeline( { startTime: safeParseInt(startTime), endTime: safeParseInt(endTime), bucketSizeMinutes: safeParseInt(bucketSizeMinutes), }, id,