Skip to content

Servify Statistical Metric Definitions (Metrics Glossary) ​

Last updated: 2026-03-31

This document defines the calculation conventions for all statistical metrics in the Dashboard and Analytics modules, ensuring frontend and backend share the same understanding.


1. Dashboard Core Metrics ​

Metric nameEnglish identifierCalculation conventionData source
Total customerstotal_customersCOUNT(*) FROM users WHERE role='customer', subject to tenant/workspace isolationusers table
Total agentstotal_agentsCOUNT(*) FROM agents, subject to tenant/workspace isolationagents table
Total ticketstotal_ticketsCOUNT(*) FROM ticketstickets table
Total sessionstotal_sessionsCOUNT(*) FROM sessionssessions table
Today's ticketstoday_ticketsCOUNT(*) FROM tickets WHERE created_at >= 今日0时tickets table
Today's sessionstoday_sessionsCOUNT(*) FROM sessions WHERE created_at >= 今日0时sessions table
Today's messagestoday_messagesCOUNT(*) FROM messages WHERE created_at >= 今日0时messages table
Open ticketsopen_ticketsCOUNT(*) FROM tickets WHERE status='open'tickets table
Assigned ticketsassigned_ticketsCOUNT(*) FROM tickets WHERE status='assigned'tickets table
Resolved ticketsresolved_ticketsCOUNT(*) FROM tickets WHERE status='resolved'tickets table
Closed ticketsclosed_ticketsCOUNT(*) FROM tickets WHERE status='closed'tickets table
Online agentsonline_agentsCOUNT(*) FROM agents WHERE status='online'agents table
Busy agentsbusy_agentsCOUNT(*) FROM agents WHERE status='busy'agents table
Active sessionsactive_sessionsCOUNT(*) FROM sessions WHERE status='active'sessions table
Average response timeavg_response_timeAVG(avg_response_time) FROM agents (seconds)agents table
Average resolution timeavg_resolution_timeAVG(EXTRACT(epoch FROM (resolved_at - created_at))) FROM tickets WHERE resolved_at IS NOT NULL (seconds)tickets table
Customer satisfactioncustomer_satisfactionCOALESCE(AVG(rating), 0) FROM customer_satisfactions (1–5 scale)customer_satisfactions table
AI usage (today)ai_usage_todaydaily_stats.ai_usage_count WHERE date=今日daily_stats table
Knowledge provider usage (today)knowledge_provider_usage_todaydaily_stats.we_knora_usage_count WHERE date=今日 (merged; no separate column)daily_stats table
WeKnora usage (today)weknora_usage_todaydaily_stats.we_knora_usage_count WHERE date=今日daily_stats table

2. Time-Range Statistics ​

Endpoint: GET /api/statistics/time-range?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD

The following metrics are aggregated daily:

Metric nameEnglish identifierCalculation convention
Ticket countticketsCOUNT(*) FROM tickets WHERE created_at >= ? AND created_at < next_day
Session countsessionsCOUNT(*) FROM sessions WHERE created_at >= ? AND created_at < next_day
Message countmessagesCOUNT(*) FROM messages WHERE created_at >= ? AND created_at < next_day
Resolved ticketsresolved_ticketsCOUNT(*) FROM tickets WHERE resolved_at >= ? AND resolved_at < next_day
Average response timeavg_response_timeAVG(avg_response_time) FROM agents (global average, not per day)
Customer satisfactioncustomer_satisfactionCOALESCE(AVG(rating), 0) FROM customer_satisfactions WHERE created_at >= ? AND created_at < next_day

Note: avg_response_time uses the global average (the agents table) in time-range statistics, because there is currently no per-message response time record.

3. Agent Performance Statistics ​

Endpoint: GET /api/statistics/agent-performance?start_date=...&end_date=...&limit=N

Metric nameEnglish identifierCalculation convention
Agent IDagent_idagents.user_id
Agent nameagent_nameusers.name
Departmentdepartmentagents.department
Total ticketstotal_ticketsCOUNT(tickets.id) WHERE tickets.agent_id = agents.user_id AND tickets.created_at 在范围内
Resolved ticketsresolved_ticketsCOUNT(CASE WHEN status IN ('resolved','closed'))
Average response timeavg_response_timeagents.avg_response_time (global value, seconds)
Average resolution timeavg_resolution_timeAVG(EXTRACT(epoch FROM (resolved_at - created_at))) WHERE resolved_at IS NOT NULL (seconds)
Ratingratingagents.rating

4. Category Statistics ​

Ticket category statistics ​

Endpoint: GET /api/statistics/ticket-category?start_date=...&end_date=...

Grouped by tickets.category with COUNT(*), sorted in descending order.

Ticket priority statistics ​

Endpoint: GET /api/statistics/ticket-priority?start_date=...&end_date=...

Grouped by tickets.priority with COUNT(*), sorted in descending order.

Customer source distribution ​

Endpoint: GET /api/statistics/customer-source

Grouped by customers.source with COUNT(*), sorted in descending order.

5. Daily Stats ​

Stored via the daily_stats table, updated on a schedule by a Worker or incremented in an event-driven fashion.

Note: the "increment events" below are IncrementKind constants (modules/analytics/application/types.go), all written through the single repository method IncrementDailyStat (dispatched to the corresponding column by Kind); they are not eight separate methods.

FieldDescriptionIncrement event
total_sessionsSessions that dayIncrementSessions
total_messagesMessages that dayIncrementMessages
total_ticketsTickets that dayIncrementTickets
resolved_ticketsTickets resolved that dayIncrementResolved
ai_usage_countAI usage countIncrementAIUsage
(no separate column)External knowledge provider usage count: there is no separate daily_stats column; IncrementKnowledgeProvider and IncrementWeKnora are merged into we_knora_usage_count; knowledge_provider_usage_count appears only in the AIMetrics response JSON (modules/ai/delivery/contract_types.go:39) and is not a field of this tableIncrementKnowledgeProvider
we_knora_usage_countWeKnora usage countIncrementWeKnora
sla_violationsSLA violation countIncrementSLA

6. Multi-Tenant Isolation Rules ​

All statistics queries are constrained by tenant_id and workspace_id:

  • Entity tables (tickets, sessions, messages, agents, customer_satisfactions): direct WHERE tenant_id = ? AND workspace_id = ?
  • User tables (users + customers): tenant information obtained by JOINing the customers table
  • Null values mean no restriction (the admin view)

7. Known Limitations ​

  1. Response time granularity: avg_response_time is currently stored in the agents table as a globally accumulated value and cannot be pinned to a specific time range
  2. Satisfaction rating: based on customer_satisfactions.rating (1–5 scale); returns 0 when there is no data
  3. Daily Stats updates: rely on the Worker or the event bus being triggered; not real-time exact