Skip to content

feat: add analytics subcommand#784

Open
inickt wants to merge 1 commit intolivekit:mainfrom
inickt:analytics
Open

feat: add analytics subcommand#784
inickt wants to merge 1 commit intolivekit:mainfrom
inickt:analytics

Conversation

@inickt
Copy link
Contributor

@inickt inickt commented Mar 9, 2026

Adds a new lk analytics command group to query LiveKit Cloud Analytics sessions.

  • Added lk analytics list and lk analytics get SESSION_ID.
  • Implemented table output plus --json / -j output for both commands.
  • Added list query flags: --limit, --page, --start, --end with validation.
  • Uses selected CLI project credentials (--project / default project) and requires stored project_id (no --project-id override).
  • Added plan/authorization-aware error handling for Analytics API responses (including Scale-plan guidance).
  • Added --curl support for analytics REST requests (prints equivalent curl command).
  • Wired command into root CLI registration.
  • Added focused unit tests for command tree, date validation, error mapping, and helper formatting.
  • Verified with go test ./cmd/lk.

Mostly generated with Codex with manual code review.

Biggest thing I assumed was this is tightly coupled to LiveKit Cloud. Does this endpoint work for self hosted instances? I think the way this is built works for custom server URLs, but maybe some of the messages need to be tweaked

❯ go run ./cmd/lk analytics
NAME:
   lk analytics - List and inspect LiveKit Cloud analytics sessions

USAGE:
   lk analytics [command [command options]]

COMMANDS:
   list  List analytics sessions
   get   Get analytics session details by session ID

OPTIONS:
   --help, -h  show help
❯ go run ./cmd/lk analytics list --help
NAME:
   lk analytics list - List analytics sessions

USAGE:
   lk analytics list [options]

OPTIONS:
   --json, -j          Output as JSON (default: false)
   --limit int         Maximum number of sessions to return (default: 0)
   --page int          Page number (starts at 0) (default: 0)
   --start YYYY-MM-DD  Start date in YYYY-MM-DD format
   --end YYYY-MM-DD    End date in YYYY-MM-DD format
   --help, -h          show help

GLOBAL OPTIONS:
   --url URL              URL to LiveKit instance (default: "http://localhost:7880") [$LIVEKIT_URL]
   --api-key KEY          Your KEY [$LIVEKIT_API_KEY]
   --api-secret SECRET    Your SECRET [$LIVEKIT_API_SECRET]
   --dev                  Use developer credentials for local LiveKit server (default: false)
   --project NAME         NAME of a configured project
   --subdomain SUBDOMAIN  SUBDOMAIN of a configured project
   --config TOML          Config TOML to use in the working directory (default: "livekit.toml")
   --curl                 Print curl commands for API actions (default: false)
   --verbose              (default: false)
   --yes, -y              Assume yes for confirmations; fail or use default for other prompts (use in CI/non-interactive) (default: false)
❯ go run ./cmd/lk analytics get --help
NAME:
   lk analytics get - Get analytics session details by session ID

USAGE:
   lk analytics get [options] SESSION_ID

OPTIONS:
   --json, -j  Output as JSON (default: false)
   --help, -h  show help

GLOBAL OPTIONS:
   --url URL              URL to LiveKit instance (default: "http://localhost:7880") [$LIVEKIT_URL]
   --api-key KEY          Your KEY [$LIVEKIT_API_KEY]
   --api-secret SECRET    Your SECRET [$LIVEKIT_API_SECRET]
   --dev                  Use developer credentials for local LiveKit server (default: false)
   --project NAME         NAME of a configured project
   --subdomain SUBDOMAIN  SUBDOMAIN of a configured project
   --config TOML          Config TOML to use in the working directory (default: "livekit.toml")
   --curl                 Print curl commands for API actions (default: false)
   --verbose              (default: false)
   --yes, -y              Assume yes for confirmations; fail or use default for other prompts (use in CI/non-interactive) (default: false)
❯ go run ./cmd/lk analytics list --limit 10
Using project [production]
┌─────────────────┬──────────────┬──────────────────────┬──────────────────────┬──────────────┬────────┬──────────────┬───────────────┐
│ Session ID      │ Room         │ Created              │ Ended                │ Participants │ Active │ Bandwidth In │ Bandwidth Out │
├─────────────────┼──────────────┼──────────────────────┼──────────────────────┼──────────────┼────────┼──────────────┼───────────────┤
│ RM_************ │ ************ │ 2026-03-09T19:42:56Z │ -                    │ 2            │ 2      │ 6389         │ 1260393       │
│ RM_************ │ ************ │ 2026-03-09T19:42:33Z │ -                    │ 3            │ 3      │ 540199       │ 659804        │
│ RM_************ │ ************ │ 2026-03-09T19:42:23Z │ -                    │ 3            │ 3      │ 360856       │ 1793389       │
│ RM_************ │ ************ │ 2026-03-09T19:41:49Z │ -                    │ 3            │ 3      │ 965691       │ 1283796       │
│ RM_************ │ ************ │ 2026-03-09T19:41:42Z │ -                    │ 3            │ 3      │ 1316907      │ 1399754       │
│ RM_************ │ ************ │ 2026-03-09T19:40:50Z │ -                    │ 3            │ 3      │ 2457568      │ 3080111       │
│ RM_************ │ ************ │ 2026-03-09T19:40:34Z │ -                    │ 3            │ 3      │ 2159730      │ 2915837       │
│ RM_************ │ ************ │ 2026-03-09T19:39:50Z │ 2026-03-09T19:41:26Z │ 3            │ 0      │ 1924178      │ 2585488       │
│ RM_************ │ ************ │ 2026-03-09T19:38:57Z │ 2026-03-09T19:41:23Z │ 3            │ 0      │ 2727681      │ 3655848       │
│ RM_************ │ ************ │ 2026-03-09T19:38:22Z │ 2026-03-09T19:39:56Z │ 3            │ 0      │ 1926794      │ 2552719       │
└─────────────────┴──────────────┴──────────────────────┴──────────────────────┴──────────────┴────────┴──────────────┴───────────────┘
❯ go run ./cmd/lk analytics get RM_************ --project production
Using project [production]
┌─────────────────┬──────────────────────────────────────┬──────────────────────┬──────────────────────┬──────────────┬────────────────────┬───────────┐
│ Session ID      │ Room                                 │ Start                │ End                  │ Participants │ Connection Minutes │ Bandwidth │
├─────────────────┼──────────────────────────────────────┼──────────────────────┼──────────────────────┼──────────────┼────────────────────┼───────────┤
│ RM_************ │ ************************************ │ 2026-03-09T19:39:50Z │ 2026-03-09T19:41:26Z │ 3            │ 2                  │ 2585488   │
└─────────────────┴──────────────────────────────────────┴──────────────────────┴──────────────────────┴──────────────┴────────────────────┴───────────┘
┌───────────────────────┬────────────────────┬──────────────────────┬──────────────────────┬────────────┬────────────┬──────────────┐
│ Identity              │ Name               │ Joined               │ Left                 │ Region     │ Connection │ SDK          │
├───────────────────────┼────────────────────┼──────────────────────┼──────────────────────┼────────────┼────────────┼──────────────┤
│ sip_+***********      │ Phone +*********** │ 2026-03-09T19:39:50Z │ 2026-03-09T19:41:26Z │ US East 1  │ UDP        │ GO 2.11.3    │
│ agent-*************** │ -                  │ 2026-03-09T19:39:51Z │ 2026-03-09T19:41:26Z │ US Central │ UDP        │ PYTHON 1.1.2 │
│ EG_************       │ -                  │ 2026-03-09T19:39:53Z │ 2026-03-09T19:41:26Z │ US Central │ UDP        │ GO 2.13.3    │
└───────────────────────┴────────────────────┴──────────────────────┴──────────────────────┴────────────┴────────────┴──────────────┘

Comment on lines +364 to +384
func resolveAnalyticsProjectID() (string, error) {
if project != nil && project.ProjectId != "" {
return project.ProjectId, nil
}

if project == nil {
return "", fmt.Errorf("%s; %s", analyticsProjectIDRequirement, analyticsProjectSelectHint)
}

projectName := project.Name
if strings.TrimSpace(projectName) == "" {
projectName = "<selected>"
}

return "", fmt.Errorf(
"selected project [%s] is missing project_id; %s. %s",
projectName,
analyticsProjectIDRequirement,
analyticsProjectSelectHint,
)
}
Copy link
Member

@rektdeckard rektdeckard Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Urf, I would love a better solution than this...it basically mandates the user either remove and re-auth the legacy project, or go and edit ~/.livekit/cli-config.yaml to manually add it. We've only started storing the project ID in the last ~5 months.

Let me see if there's an easy way to maybe install a startup hook that will backfill old projects with their ID.

@rektdeckard
Copy link
Member

This looks great so far! I will take a closer look and play around with it this evening. To answer your question, no -- analytics service is not implemented in LiveKit OSS. But neither are the agent, number (Phone numbers), or cloud commands so no concern there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants