Skip to content

feat: add observability commands to query logs, traces, aggregations, and keys - #986

Open
Vadman97 wants to merge 2 commits into
mainfrom
termag-vkorolik/cmvu4ki0a19zwf7cqgofnefiq
Open

Vadman97 wants to merge 2 commits into
mainfrom
termag-vkorolik/cmvu4ki0a19zwf7cqgofnefiq

Conversation

@Vadman97

@Vadman97 Vadman97 commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Demo: the transcript against a mock server is at team-o11y:artifacts/ix1-ldcli/demo-transcript.txt, and the help output is at team-o11y:artifacts/ix1-ldcli/help-output.txt.

This PR adds the hand-written command group ldcli observability, with the alias o11y. Before this change, ldcli had no observability commands. An agent had to find a private GraphQL endpoint, an auth header, and a numeric project ID. That took about 2 minutes in an alert investigation.

The group has these commands:

  • logs search prints one compact line for each log: timestamp, level, service, and message. --attributes error.message,code.function adds selected attributes. --json gives the full records.
  • traces search prints timestamp, duration, service, span name, status, and trace ID. --sort-column duration finds the slowest spans.
  • aggregate takes --product-type, --query, --function, --column, --group-by, --group-limit, and --bucket-count. If the API sampled the data, the output shows SAMPLED: sample factor N, and the JSON output has "sampled": true.
  • keys lists the keys of a product type. With --key, it lists the values of one key.

All commands take --project <key>, --start and --end (15m, 7d, 2w, or ISO 8601), and --query. They use the configured access token.

The public REST API has only usage endpoints for observability (/api/v2/usage/observability/*). These commands therefore use the observability GraphQL API, which is the API that the hosted LaunchDarkly MCP server uses (launchdarkly/mcp internal/ldapi/observability.go). The commands send the same headers (Gonfalon-Authorization and x-project-id) and the same GraphQL operations. The project ID is the LaunchDarkly project _id. The command gets it from GET /api/v2/projects/{key}. The CLI derives the API URL from --base-uri (https://pri.observability.<host>), as symbols upload does. --observability-url overrides it.

Other ldcli commands print JSON when stdout is not a terminal. These commands print compact text in that case, because 5 full log records can be 100 KB. JSON is printed only if you set --json, --output json, LD_OUTPUT, or output in the configuration file.

To test the change, I ran these commands. They all passed:

go build ./...
go test ./...
golangci-lint run ./...   # v2.9.0, 0 issues

The new tests use an httptest server as the observability API and the resources mock client for the project lookup. I also ran the binary against a mock server that returns response shapes copied from catamorphic, through the hosted MCP. I did not run the CLI against a real instance, because the box has no ldcli access token.

These are open questions for the reviewer:

  • The GraphQL API is not documented as a public API. If the backend changes an operation, the commands and the hosted MCP server break together.
  • Somebody must run one command against catamorphic or production with a real access token (api-...). The hosted MCP sends this header form, but I could not test it here.
  • --deployment-environment filters on the environment attribute that the SDK reports, for example Production. That value is not a LaunchDarkly environment key, so the flag does not use --environment.

🤖 Generated with Claude Code


Opened by termag ask for vkorolik: an agent run on ix1-ldcli-10292237/ldcli, thread cmvu4ki0a19zwf7cqgofnefiq.

The run worked in its own clone of the committed code. termag checked its commits before pushing (descends from the base, no protected paths, authored by the asker, no secret-shaped strings); review the change as you would any other before marking it ready.

Follow-ups on the thread push here: termag ask ix1-ldcli-10292237/ldcli --thread cmvu4ki0a19zwf7cqgofnefiq "…".

Opened from termag


Note

Overview
Adds a new ldcli observability command group (alias o11y) so users can query LaunchDarkly observability from the CLI using the project key and access token, without supplying a separate observability project ID.

Search: logs search and traces search call the observability GraphQL API and print compact one-line text by default (including when stdout is not a TTY); --json / --output json returns full records. Shared flags cover time range, query, limit, optional --deployment-environment, and extra attributes; traces support --sort-column.

Analytics helpers: aggregate runs bucketed counts/metrics (with sampling warnings and optional totals), and keys lists attribute keys or values for a --product-type.

Infrastructure: A new internal/observability HTTP client posts GraphQL with Gonfalon-Authorization and x-project-id, derives the API host from --base-uri (overridable via --observability-url), and resolves project keys via GET /api/v2/projects/{key}. The root command registers the group, documents it in the README/help template, and includes broad httptest coverage.

Reviewed by Cursor Bugbot for commit 6123c67. Bugbot is set up for automated code reviews on this repo. Configure here.

… and keys

Add the hand-written "ldcli observability" command group (alias "o11y"):
"logs search", "traces search", "aggregate", and "keys". An agent can now
query observability data with the access token that ldcli already uses.

The commands take the LaunchDarkly project key. They get the project _id
from the REST API and send it to the observability GraphQL API, the same
API and operations that the hosted LaunchDarkly MCP server uses. The CLI
derives the API URL from --base-uri, and --observability-url overrides it.

The default output is compact text, also when stdout is not a terminal,
because full log records are large. Use --json for full records.
"aggregate" shows the sample factor when the API sampled the data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Generated-by: termag
@Vadman97

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread cmd/observability/aggregate.go
Comment thread cmd/observability/search.go
@Vadman97
Vadman97 marked this pull request as ready for review October 29, 2026 23:50
@Vadman97
Vadman97 requested a review from a team as a code owner October 29, 2026 23:50
@Vadman97
Vadman97 requested review from tiffanylphan and removed request for a team October 29, 2026 23:50
…keys

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Generated-by: termag
@Vadman97

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 6123c67. Configure here.

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.

1 participant