From 6c7f17088da592f43b4640c96782e3a0732ef410 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 19:13:50 +0000 Subject: [PATCH 1/2] chore(release): bump HyperDX app/package versions --- .changeset/alert-display-fields-core.md | 6 - ...lert-webhook-source-query-threshold-max.md | 19 --- .../alert-webhook-template-variables.md | 13 --- .changeset/angry-frogs-film.md | 5 - .changeset/bearer-prefixed-ingest-auth-api.md | 5 - .../bearer-prefixed-ingest-auth-collector.md | 5 - .../deterministic-metric-name-listing.md | 6 - .changeset/early-hotels-lay.md | 6 - .changeset/good-buttons-eat.md | 7 -- .changeset/gpu-metrics-infra-panel.md | 21 ---- .changeset/histogram-table-orderby.md | 7 -- .changeset/inline-alerts-external-api-mcp.md | 23 ---- .changeset/large-suits-smoke.md | 5 - .changeset/llm-observability-dashboard.md | 5 - .changeset/metric-name-select-not-found.md | 5 - .changeset/multiseries-metric-orderby.md | 7 -- .changeset/pattern-flyout-servicename.md | 5 - .../promql-label-autocomplete-duplicates.md | 5 - .changeset/promql-label-dashboard-filters.md | 7 -- .changeset/promql-label-filter-matchers.md | 7 -- .../promql-label-values-match-selectors.md | 5 - .changeset/promql-label-values-time-range.md | 6 - .changeset/promql-legend-template.md | 6 - .changeset/promql-proxy-preserve-host-path.md | 37 ------ .changeset/sharp-rules-rest.md | 5 - .changeset/show-deployed-version-sha.md | 5 - .changeset/static-list-dashboard-filters.md | 7 -- .changeset/swift-owls-spend.md | 20 ---- .changeset/webhook-form-template-variables.md | 11 -- .changeset/wicked-ads-admire.md | 5 - .env | 4 +- packages/api/CHANGELOG.md | 108 ++++++++++++++++++ packages/api/package.json | 4 +- packages/app/CHANGELOG.md | 88 ++++++++++++++ packages/app/package.json | 4 +- packages/cli/CHANGELOG.md | 21 ++++ packages/cli/package.json | 4 +- packages/common-utils/CHANGELOG.md | 14 +++ packages/common-utils/package.json | 2 +- packages/otel-collector/CHANGELOG.md | 6 + packages/otel-collector/package.json | 2 +- yarn.lock | 8 +- 42 files changed, 251 insertions(+), 290 deletions(-) delete mode 100644 .changeset/alert-display-fields-core.md delete mode 100644 .changeset/alert-webhook-source-query-threshold-max.md delete mode 100644 .changeset/alert-webhook-template-variables.md delete mode 100644 .changeset/angry-frogs-film.md delete mode 100644 .changeset/bearer-prefixed-ingest-auth-api.md delete mode 100644 .changeset/bearer-prefixed-ingest-auth-collector.md delete mode 100644 .changeset/deterministic-metric-name-listing.md delete mode 100644 .changeset/early-hotels-lay.md delete mode 100644 .changeset/good-buttons-eat.md delete mode 100644 .changeset/gpu-metrics-infra-panel.md delete mode 100644 .changeset/histogram-table-orderby.md delete mode 100644 .changeset/inline-alerts-external-api-mcp.md delete mode 100644 .changeset/large-suits-smoke.md delete mode 100644 .changeset/llm-observability-dashboard.md delete mode 100644 .changeset/metric-name-select-not-found.md delete mode 100644 .changeset/multiseries-metric-orderby.md delete mode 100644 .changeset/pattern-flyout-servicename.md delete mode 100644 .changeset/promql-label-autocomplete-duplicates.md delete mode 100644 .changeset/promql-label-dashboard-filters.md delete mode 100644 .changeset/promql-label-filter-matchers.md delete mode 100644 .changeset/promql-label-values-match-selectors.md delete mode 100644 .changeset/promql-label-values-time-range.md delete mode 100644 .changeset/promql-legend-template.md delete mode 100644 .changeset/promql-proxy-preserve-host-path.md delete mode 100644 .changeset/sharp-rules-rest.md delete mode 100644 .changeset/show-deployed-version-sha.md delete mode 100644 .changeset/static-list-dashboard-filters.md delete mode 100644 .changeset/swift-owls-spend.md delete mode 100644 .changeset/webhook-form-template-variables.md delete mode 100644 .changeset/wicked-ads-admire.md diff --git a/.changeset/alert-display-fields-core.md b/.changeset/alert-display-fields-core.md deleted file mode 100644 index f319f11cf0..0000000000 --- a/.changeset/alert-display-fields-core.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperdx/api': minor -'@hyperdx/common-utils': patch ---- - -feat: Alerts now persist their own `displayName` and `tags` diff --git a/.changeset/alert-webhook-source-query-threshold-max.md b/.changeset/alert-webhook-source-query-threshold-max.md deleted file mode 100644 index 16a8513095..0000000000 --- a/.changeset/alert-webhook-source-query-threshold-max.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@hyperdx/api': patch ---- - -Fix `{{sourceQuery}}` returning empty for inline-query and dashboard-tile -alerts. It read only the saved search's filter, so alerts backed by a chart -config — where the query lives on the alert or the tile — advertised a variable -that never rendered. It now resolves the query from whichever config backs the -alert: the builder `where` or the raw `sqlTemplate`. - -Add `{{thresholdMax}}`, the upper bound of a `between` / `outside` condition. -Receivers previously saw only the lower bound and could not reconstruct the -range that fired. It renders empty for every other comparator. - -Test Webhook now sends a sample value for every template variable. It carried -only the original seven, so a body using an enriched variable rendered it empty -— and because `threshold`, `thresholdMax` and `value` are emitted unquoted, a -body like `{"value": {{value}}}` was sent as `{"value": }` and rejected, -failing the test for a template that works on a real firing. diff --git a/.changeset/alert-webhook-template-variables.md b/.changeset/alert-webhook-template-variables.md deleted file mode 100644 index 241aa413c7..0000000000 --- a/.changeset/alert-webhook-template-variables.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@hyperdx/api': minor ---- - -Add enriched template variables to Generic and incident.io webhook bodies: -`{{alertId}}`, `{{status}}`, `{{alertType}}`, `{{comparator}}`, `{{threshold}}`, -`{{value}}`, `{{groupKey}}`, `{{sourceQuery}}`, `{{teamId}}`, `{{note}}`, and -ISO-8601 `{{startTimeISO}}` / `{{endTimeISO}}` alongside the existing Unix-ms -`{{startTime}}` / `{{endTime}}`. - -Receivers can now route, filter and dedupe on an alert's identity and condition -without parsing the rendered message body. Existing templates are unaffected — -every new variable is additive and renders empty when an alert doesn't carry it. diff --git a/.changeset/angry-frogs-film.md b/.changeset/angry-frogs-film.md deleted file mode 100644 index f6e228bc9a..0000000000 --- a/.changeset/angry-frogs-film.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@hyperdx/app": patch ---- - -chore: Add isSourceAllowed prop to SourceSelectControlledComponent diff --git a/.changeset/bearer-prefixed-ingest-auth-api.md b/.changeset/bearer-prefixed-ingest-auth-api.md deleted file mode 100644 index c692c3283c..0000000000 --- a/.changeset/bearer-prefixed-ingest-auth-api.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperdx/api': patch ---- - -Accept `Bearer `-prefixed Authorization header values on the OTel ingest endpoint in OpAMP-managed mode. The collector's bearer-token authenticator matches the full header value exactly and was configured with only the bare API key, so RFC 6750 clients that send `Authorization: Bearer ` were rejected. The generated collector config now also accepts `Bearer`, `bearer`, and `BEARER` prefixed forms of each ingestion API key. diff --git a/.changeset/bearer-prefixed-ingest-auth-collector.md b/.changeset/bearer-prefixed-ingest-auth-collector.md deleted file mode 100644 index 4ef7458a8b..0000000000 --- a/.changeset/bearer-prefixed-ingest-auth-collector.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperdx/otel-collector': patch ---- - -Accept `Bearer `-prefixed Authorization header values on the OTLP receiver in standalone mode (`OTLP_AUTH_TOKEN`). Previously only the bare-token form of the header was accepted, rejecting RFC 6750 clients that send `Authorization: Bearer `. The `Bearer`, `bearer`, and `BEARER` prefixed forms are now accepted alongside the bare token. diff --git a/.changeset/deterministic-metric-name-listing.md b/.changeset/deterministic-metric-name-listing.md deleted file mode 100644 index 1c1319da91..0000000000 --- a/.changeset/deterministic-metric-name-listing.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperdx/app': patch -'@hyperdx/common-utils': patch ---- - -fix: metric names in the chart editor are now listed deterministically instead of sampled. The dropdown discovered names with `groupUniqArray(3000)(MetricName)`, which keeps an arbitrary subset once a metrics table holds more than 3000 distinct names — the survivors follow hash order, not name order — so metrics that exist and are actively reporting could be unselectable, with no warning and no way to search for what had been dropped. Names are now fetched with an ordered, paginated query and matched server-side, ranked so an exact match is always on the first page, and the dropdown says when the list is incomplete. Also fixes the metric list ignoring the chart's selected time range, which pinned it to the last 24 hours. diff --git a/.changeset/early-hotels-lay.md b/.changeset/early-hotels-lay.md deleted file mode 100644 index fcb17d4330..0000000000 --- a/.changeset/early-hotels-lay.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@hyperdx/api": patch -"@hyperdx/app": patch ---- - -feat: Support autocomplete for PromQL label filters diff --git a/.changeset/good-buttons-eat.md b/.changeset/good-buttons-eat.md deleted file mode 100644 index a9c254865f..0000000000 --- a/.changeset/good-buttons-eat.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@hyperdx/api": patch -"@hyperdx/app": patch -"@hyperdx/common-utils": patch ---- - -feat: Support static filters in MCP diff --git a/.changeset/gpu-metrics-infra-panel.md b/.changeset/gpu-metrics-infra-panel.md deleted file mode 100644 index 5f9156f8f6..0000000000 --- a/.changeset/gpu-metrics-infra-panel.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@hyperdx/app': minor ---- - -Show GPU utilization and GPU memory utilization charts in the log/span side -panel Infrastructure section when `hw.gpu.*` metrics (OTel hardware semconv) -exist for the correlated host/node. Multiple GPUs on a host render as separate -series grouped by `hw.id`, and utilization is split per GPU engine by -`hw.gpu.task` (general/encoder/decoder) so a node saturated on video encode is -still visible; a missing task is reported as `general`. The section is fully -hidden when no GPU metrics are present and partially rendered when only one -metric is available. - -The Infrastructure tab now also treats a Kubernetes resource attribute that is -present but empty (for example `k8s.node.name: ""`) as absent. Such rows -previously surfaced an Infrastructure tab that could render nothing. - -Fix GPU chart availability leaking across rows: switching the side panel to a -row on a different host briefly rendered the previous host's set of GPU -charts, because the availability query keeps the prior result readable while -the new one runs. diff --git a/.changeset/histogram-table-orderby.md b/.changeset/histogram-table-orderby.md deleted file mode 100644 index d1a2c618ce..0000000000 --- a/.changeset/histogram-table-orderby.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperdx/common-utils': patch -'@hyperdx/app': patch -'@hyperdx/api': patch ---- - -Fixed single-series histogram charts failing with "Unknown expression or function identifier" when sorted by a group-by column or expression. The histogram translation packs group values into a single `group` Array, so the table default ORDER BY (the raw group-by text) referenced source columns that no longer exist in scope; matched sort items now address the packed array positionally. diff --git a/.changeset/inline-alerts-external-api-mcp.md b/.changeset/inline-alerts-external-api-mcp.md deleted file mode 100644 index 398b782c73..0000000000 --- a/.changeset/inline-alerts-external-api-mcp.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -'@hyperdx/api': minor ---- - -Support inline chart alerts (source `inline` + `chartConfig`) in the external -API v2 and the MCP `clickstack_save_alert` / `clickstack_get_alert` tools. -Inline alerts can now be created, updated, listed, and deleted through -`/api/v2/alerts` using the same tile-config dialect as v2 dashboards, with the -same validation rules as the internal API: display-type allowlist, metric -formula validation, the formula source-kind gate, raw SQL template validation, -and team-scoped source/connection ownership. Passing a `chartConfig` to a -`tile` or `saved_search` alert is now rejected instead of silently dropped, -and reading an inline alert whose config carries internal-only fields omits -`chartConfig` rather than returning a lossy approximation. - -Also fixes three pre-existing issues on the external v2 dashboards path: a -gauge tile saved through `clickstack_save_dashboard` with `isDelta: true` was -persisted as a non-delta (the flag was dropped converting MCP tiles to the -internal shape); a tile config carrying an unrecognized `configType` (e.g. -`promql`) was silently stored as a builder config and skipped the formula and -number-select rules, and is now rejected; and validation errors on alert -bodies no longer collapse to `Invalid input` — the schema reports the failing -branch's own message. diff --git a/.changeset/large-suits-smoke.md b/.changeset/large-suits-smoke.md deleted file mode 100644 index 182fde5e03..0000000000 --- a/.changeset/large-suits-smoke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@hyperdx/app": patch ---- - -Preserve conditional color rules for SQL and PromQl chart configs diff --git a/.changeset/llm-observability-dashboard.md b/.changeset/llm-observability-dashboard.md deleted file mode 100644 index 33276af585..0000000000 --- a/.changeset/llm-observability-dashboard.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperdx/app': minor ---- - -Add a read-time, schema-agnostic LLM observability dashboard at `/llm` (beta, linked from the dashboards list) — no ingestion changes required, and it works retroactively on already-ingested telemetry. Traces instrumented with the OTel GenAI semantic conventions, OpenLLMetry, OpenInference, or the Vercel AI SDK are interpreted at query time to chart traffic, token split (uncached/cached/cache-write/output/reasoning), estimated cost by model (bundled price catalog with cache-read discounts and cache-write premiums; an instrumentation-provided cost attribute always wins), latency/TTFT, tool analytics, per-session timelines with lazy-loaded conversation views, and side-by-side LLM span/log search. Aggregations elect an app's own cost-reporting spans as the authoritative per-call reporters so apps emitting several instrumentation dialects in parallel (e.g. opencode emitting OpenInference and Vercel AI spans for each call) are counted once — verified to match opencode's self-reported session cost exactly. diff --git a/.changeset/metric-name-select-not-found.md b/.changeset/metric-name-select-not-found.md deleted file mode 100644 index 0e8251095e..0000000000 --- a/.changeset/metric-name-select-not-found.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperdx/app': patch ---- - -Fix two problems with the chart editor's metric name picker. The truncation and load-failure notices now render below the input instead of above it, so they no longer push the field down out of alignment with the browse-metrics button beside it, and both were shortened to fit the tile editor's column without wrapping. A search that matches nothing now says so rather than silently hiding the dropdown, and offers the searched name as a selectable option — the catalog only covers the most recent three days of the chart's time range, so a metric that stopped reporting was previously impossible to chart by name. diff --git a/.changeset/multiseries-metric-orderby.md b/.changeset/multiseries-metric-orderby.md deleted file mode 100644 index c7149a953c..0000000000 --- a/.changeset/multiseries-metric-orderby.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperdx/common-utils': patch -'@hyperdx/app': patch -'@hyperdx/api': patch ---- - -Fixed multi-series metric charts failing with "Unknown expression or function identifier" when sorted by an expression group-by (e.g. `ResourceAttributes['service.name']`). Table tiles default their ORDER BY to the group-by text, so any multi-series metric table grouped by a resource/attribute-derived expression failed to render. Such sort expressions are now evaluated inside each per-series branch through internal companion columns instead of being re-evaluated in the composed outer query, where the source columns no longer exist. diff --git a/.changeset/pattern-flyout-servicename.md b/.changeset/pattern-flyout-servicename.md deleted file mode 100644 index e2a8a90b9b..0000000000 --- a/.changeset/pattern-flyout-servicename.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperdx/app': patch ---- - -fix: Reliably show service name and level in pattern sample drawer diff --git a/.changeset/promql-label-autocomplete-duplicates.md b/.changeset/promql-label-autocomplete-duplicates.md deleted file mode 100644 index 1665a492ef..0000000000 --- a/.changeset/promql-label-autocomplete-duplicates.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@hyperdx/app": patch ---- - -fix: De-dupe PromQL labels and values to prevent Mantine crash diff --git a/.changeset/promql-label-dashboard-filters.md b/.changeset/promql-label-dashboard-filters.md deleted file mode 100644 index 2eff9dce74..0000000000 --- a/.changeset/promql-label-dashboard-filters.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperdx/common-utils': patch -'@hyperdx/api': patch -'@hyperdx/app': patch ---- - -feat: Support dashboard filters based on Prometheus label values diff --git a/.changeset/promql-label-filter-matchers.md b/.changeset/promql-label-filter-matchers.md deleted file mode 100644 index ed9aadd2a9..0000000000 --- a/.changeset/promql-label-filter-matchers.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperdx/common-utils': patch -'@hyperdx/api': patch -'@hyperdx/app': patch ---- - -feat: Support series filter (matcher) in PromQL label dashboard filters diff --git a/.changeset/promql-label-values-match-selectors.md b/.changeset/promql-label-values-match-selectors.md deleted file mode 100644 index a38cb3351b..0000000000 --- a/.changeset/promql-label-values-match-selectors.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperdx/api': patch ---- - -feat: Evaluate Prometheus `match[]` series selectors on the labels and label values endpoints for ClickHouse TimeSeries connections diff --git a/.changeset/promql-label-values-time-range.md b/.changeset/promql-label-values-time-range.md deleted file mode 100644 index c03a945711..0000000000 --- a/.changeset/promql-label-values-time-range.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperdx/api': patch -'@hyperdx/app': patch ---- - -feat: Accept optional time bounds on Prometheus label values endpoint diff --git a/.changeset/promql-legend-template.md b/.changeset/promql-legend-template.md deleted file mode 100644 index b9d00d0d5c..0000000000 --- a/.changeset/promql-legend-template.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperdx/common-utils': patch -'@hyperdx/app': patch ---- - -feat: Support a custom template for PromQL series legends \ No newline at end of file diff --git a/.changeset/promql-proxy-preserve-host-path.md b/.changeset/promql-proxy-preserve-host-path.md deleted file mode 100644 index 1d549c25e2..0000000000 --- a/.changeset/promql-proxy-preserve-host-path.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -'@hyperdx/api': minor ---- - -fix: preserve a Connection host path prefix when proxying PromQL. -`proxyToPrometheus` joined absolute Prometheus paths (`/api/v1/query_range`, -`/api/v1/query`, `/api/v1/query_exemplars`, `/api/v1/label/.../values`) with -`new URL(path, host)`, which replaces the host pathname instead of appending to -it. VictoriaMetrics cluster `vmselect` URLs such as -`http://vmselect:8481/select/0/prometheus` were rewritten to -`/api/v1/query_range` and rejected. The join now keeps the existing pathname. - -This is a behavior change for Connections whose host already included a path -that was never meant as a Prometheus API prefix — for example -`http://prom:9090/graph` copied from the Prometheus UI. That previously happened -to work because the absolute API path replaced `/graph`; requests now go to -`/graph/api/v1/query_range` and will 404. Trim stray paths from existing -Connection hosts before upgrading. Root-mounted hosts (`http://prom:9090` or -`http://prom:9090/`) are unchanged. - -Query parameters on the Connection host are now only a fallback for a fixed set -of real Prometheus API params (`query`, `time`, `start`, `end`, `step`, -`match`/`match[]`, `limit`, `timeout`, `stats`): a request value for one of -these (including repeatable ones such as `match[]`) always wins and replaces a -same-named host value outright, rather than being dropped. Any other host query -key the request never mentions -- for example `?extra_label=namespace%3Dprod` -pinning a VictoriaMetrics tenant scope -- is left as-is and is never overridable -by the request, since a param name outside that fixed set is not forwarded at -all regardless of what the host carries. This also means a host copied with a -stray query string (not just a stray path) now forwards its non-Prometheus keys -upstream as a fallback on every request -- trim those too if they weren't -intended as Prometheus API params. - -This is also a behavior change for a direct API caller (e.g. curl or Terraform) -that previously relied on sending an arbitrary, non-Prometheus query param -through this endpoint: that param is now silently dropped rather than forwarded, -regardless of whether the Connection host carries anything under the same name. diff --git a/.changeset/sharp-rules-rest.md b/.changeset/sharp-rules-rest.md deleted file mode 100644 index 8bcfa90652..0000000000 --- a/.changeset/sharp-rules-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@hyperdx/app": patch ---- - -feat: Display static value filters diff --git a/.changeset/show-deployed-version-sha.md b/.changeset/show-deployed-version-sha.md deleted file mode 100644 index 913a0e0f33..0000000000 --- a/.changeset/show-deployed-version-sha.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperdx/app': patch ---- - -Add a `window.hdx` browser-console debug handle and a "Copy debug info" action in the Help menu, so you can confirm which build is deployed and grab the context worth attaching when filing an issue. `window.hdx.report()` (and the Help menu action) produces a pasteable summary: frontend version (from package.json), backend/API version (from `/api/health` — the two deploy separately), deployment mode, user/team ids, enabled env-configurable feature flags, current URL, screen/viewport/OS/browser info, and the RUM session id. The handle is installed once and reads its async fields (server version, identity, features, session id) live via getters. diff --git a/.changeset/static-list-dashboard-filters.md b/.changeset/static-list-dashboard-filters.md deleted file mode 100644 index 455b5383bb..0000000000 --- a/.changeset/static-list-dashboard-filters.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@hyperdx/common-utils': patch -'@hyperdx/api': patch -'@hyperdx/app': patch ---- - -feat: Add static filters to schemas and APIs \ No newline at end of file diff --git a/.changeset/swift-owls-spend.md b/.changeset/swift-owls-spend.md deleted file mode 100644 index 57d4d07f5a..0000000000 --- a/.changeset/swift-owls-spend.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -"@hyperdx/app": patch -"@hyperdx/cli": patch ---- - -fix(charts): show decimals on Y-axis ticks under 10 in magnitude - -The Y-axis of a time series chart (and the CLI's termchart equivalent) -always rounded tick labels to 0 decimal places, regardless of the chart's -Number Format settings. Charts whose values live under 1 (fractional -gauges, ratios, sub-1 rates) rendered every axis tick as `0` even though -the tooltip and legend showed the correct value. - -A tick under 10 in magnitude (as displayed - a percent tick's magnitude is -checked against its ×100 value, not its raw 0-1 ratio) now honors the -chart's configured decimals, capped at 2 to keep the label within the -axis's fixed width. A tick of 10 or more, and a tick of exactly 0, stay -integers exactly as before, whatever the chart's Number Format configures -- so ordinary counts and the byte/percent tiles in the bundled dashboard -templates are unaffected. diff --git a/.changeset/webhook-form-template-variables.md b/.changeset/webhook-form-template-variables.md deleted file mode 100644 index 9de3b10504..0000000000 --- a/.changeset/webhook-form-template-variables.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@hyperdx/app': patch ---- - -List every supported template variable in the webhook form, including the -enriched set added to Generic and incident.io bodies (`{{alertId}}`, -`{{status}}`, `{{alertType}}`, `{{comparator}}`, `{{threshold}}`, -`{{thresholdMax}}`, `{{value}}`, `{{groupKey}}`, `{{sourceQuery}}`, -`{{teamId}}`, `{{note}}` and ISO-8601 `{{startTimeISO}}` / `{{endTimeISO}}`). -Each variable now carries a one-line description, so a webhook body can be -written without leaving the form. diff --git a/.changeset/wicked-ads-admire.md b/.changeset/wicked-ads-admire.md deleted file mode 100644 index b51a78d76a..0000000000 --- a/.changeset/wicked-ads-admire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@hyperdx/app": patch ---- - -feat: Allow creation and editing of static list filters in the UI diff --git a/.env b/.env index b4e07529eb..d98b349968 100644 --- a/.env +++ b/.env @@ -8,8 +8,8 @@ NEXT_ALL_IN_ONE_IMAGE_NAME_DOCKERHUB=clickhouse/clickstack-all-in-one ALL_IN_ONE_IMAGE_NAME_DOCKERHUB=hyperdx/hyperdx-all-in-one NEXT_OTEL_COLLECTOR_IMAGE_NAME_DOCKERHUB=clickhouse/clickstack-otel-collector OTEL_COLLECTOR_IMAGE_NAME_DOCKERHUB=hyperdx/hyperdx-otel-collector -CODE_VERSION=2.37.0 -IMAGE_VERSION_SUB_TAG=.37.0 +CODE_VERSION=2.38.0 +IMAGE_VERSION_SUB_TAG=.38.0 IMAGE_VERSION=2 IMAGE_NIGHTLY_TAG=2-nightly IMAGE_LATEST_TAG=latest diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index 0eb03a961b..dbfad2091e 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -1,5 +1,113 @@ # @hyperdx/api +## 2.38.0 + +### Minor Changes + +- 74c28e7f: feat: Alerts now persist their own `displayName` and `tags` +- 9c4f94f2: Add enriched template variables to Generic and incident.io webhook bodies: + `{{alertId}}`, `{{status}}`, `{{alertType}}`, `{{comparator}}`, `{{threshold}}`, + `{{value}}`, `{{groupKey}}`, `{{sourceQuery}}`, `{{teamId}}`, `{{note}}`, and + ISO-8601 `{{startTimeISO}}` / `{{endTimeISO}}` alongside the existing Unix-ms + `{{startTime}}` / `{{endTime}}`. + + Receivers can now route, filter and dedupe on an alert's identity and condition + without parsing the rendered message body. Existing templates are unaffected — + every new variable is additive and renders empty when an alert doesn't carry it. + +- f0d1cef5: Support inline chart alerts (source `inline` + `chartConfig`) in the external + API v2 and the MCP `clickstack_save_alert` / `clickstack_get_alert` tools. + Inline alerts can now be created, updated, listed, and deleted through + `/api/v2/alerts` using the same tile-config dialect as v2 dashboards, with the + same validation rules as the internal API: display-type allowlist, metric + formula validation, the formula source-kind gate, raw SQL template validation, + and team-scoped source/connection ownership. Passing a `chartConfig` to a + `tile` or `saved_search` alert is now rejected instead of silently dropped, + and reading an inline alert whose config carries internal-only fields omits + `chartConfig` rather than returning a lossy approximation. + + Also fixes three pre-existing issues on the external v2 dashboards path: a + gauge tile saved through `clickstack_save_dashboard` with `isDelta: true` was + persisted as a non-delta (the flag was dropped converting MCP tiles to the + internal shape); a tile config carrying an unrecognized `configType` (e.g. + `promql`) was silently stored as a builder config and skipped the formula and + number-select rules, and is now rejected; and validation errors on alert + bodies no longer collapse to `Invalid input` — the schema reports the failing + branch's own message. + +- d9c5c455: fix: preserve a Connection host path prefix when proxying PromQL. + `proxyToPrometheus` joined absolute Prometheus paths (`/api/v1/query_range`, + `/api/v1/query`, `/api/v1/query_exemplars`, `/api/v1/label/.../values`) with + `new URL(path, host)`, which replaces the host pathname instead of appending to + it. VictoriaMetrics cluster `vmselect` URLs such as + `http://vmselect:8481/select/0/prometheus` were rewritten to + `/api/v1/query_range` and rejected. The join now keeps the existing pathname. + + This is a behavior change for Connections whose host already included a path + that was never meant as a Prometheus API prefix — for example + `http://prom:9090/graph` copied from the Prometheus UI. That previously happened + to work because the absolute API path replaced `/graph`; requests now go to + `/graph/api/v1/query_range` and will 404. Trim stray paths from existing + Connection hosts before upgrading. Root-mounted hosts (`http://prom:9090` or + `http://prom:9090/`) are unchanged. + + Query parameters on the Connection host are now only a fallback for a fixed set + of real Prometheus API params (`query`, `time`, `start`, `end`, `step`, + `match`/`match[]`, `limit`, `timeout`, `stats`): a request value for one of + these (including repeatable ones such as `match[]`) always wins and replaces a + same-named host value outright, rather than being dropped. Any other host query + key the request never mentions -- for example `?extra_label=namespace%3Dprod` + pinning a VictoriaMetrics tenant scope -- is left as-is and is never overridable + by the request, since a param name outside that fixed set is not forwarded at + all regardless of what the host carries. This also means a host copied with a + stray query string (not just a stray path) now forwards its non-Prometheus keys + upstream as a fallback on every request -- trim those too if they weren't + intended as Prometheus API params. + + This is also a behavior change for a direct API caller (e.g. curl or Terraform) + that previously relied on sending an arbitrary, non-Prometheus query param + through this endpoint: that param is now silently dropped rather than forwarded, + regardless of whether the Connection host carries anything under the same name. + +### Patch Changes + +- 25a3b015: Fix `{{sourceQuery}}` returning empty for inline-query and dashboard-tile + alerts. It read only the saved search's filter, so alerts backed by a chart + config — where the query lives on the alert or the tile — advertised a variable + that never rendered. It now resolves the query from whichever config backs the + alert: the builder `where` or the raw `sqlTemplate`. + + Add `{{thresholdMax}}`, the upper bound of a `between` / `outside` condition. + Receivers previously saw only the lower bound and could not reconstruct the + range that fired. It renders empty for every other comparator. + + Test Webhook now sends a sample value for every template variable. It carried + only the original seven, so a body using an enriched variable rendered it empty + — and because `threshold`, `thresholdMax` and `value` are emitted unquoted, a + body like `{"value": {{value}}}` was sent as `{"value": }` and rejected, + failing the test for a template that works on a real firing. + +- 808b3453: Accept `Bearer `-prefixed Authorization header values on the OTel ingest endpoint in OpAMP-managed mode. The collector's bearer-token authenticator matches the full header value exactly and was configured with only the bare API key, so RFC 6750 clients that send `Authorization: Bearer ` were rejected. The generated collector config now also accepts `Bearer`, `bearer`, and `BEARER` prefixed forms of each ingestion API key. +- bf4443df: feat: Support autocomplete for PromQL label filters +- 55db91fa: feat: Support static filters in MCP +- 89a897ec: Fixed single-series histogram charts failing with "Unknown expression or function identifier" when sorted by a group-by column or expression. The histogram translation packs group values into a single `group` Array, so the table default ORDER BY (the raw group-by text) referenced source columns that no longer exist in scope; matched sort items now address the packed array positionally. +- f1062a7b: Fixed multi-series metric charts failing with "Unknown expression or function identifier" when sorted by an expression group-by (e.g. `ResourceAttributes['service.name']`). Table tiles default their ORDER BY to the group-by text, so any multi-series metric table grouped by a resource/attribute-derived expression failed to render. Such sort expressions are now evaluated inside each per-series branch through internal companion columns instead of being re-evaluated in the composed outer query, where the source columns no longer exist. +- 4184a898: feat: Support dashboard filters based on Prometheus label values +- 27360036: feat: Support series filter (matcher) in PromQL label dashboard filters +- 7ed8dc8c: feat: Evaluate Prometheus `match[]` series selectors on the labels and label values endpoints for ClickHouse TimeSeries connections +- bcf0257c: feat: Accept optional time bounds on Prometheus label values endpoint +- cff6388c: feat: Add static filters to schemas and APIs +- Updated dependencies [74c28e7f] +- Updated dependencies [b917308d] +- Updated dependencies [55db91fa] +- Updated dependencies [89a897ec] +- Updated dependencies [f1062a7b] +- Updated dependencies [4184a898] +- Updated dependencies [27360036] +- Updated dependencies [c7965927] +- Updated dependencies [cff6388c] + - @hyperdx/common-utils@0.28.1 + ## 2.37.0 ### Minor Changes diff --git a/packages/api/package.json b/packages/api/package.json index df39b905ee..29bbc4f608 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@hyperdx/api", - "version": "2.37.0", + "version": "2.38.0", "license": "MIT", "private": true, "engines": { @@ -21,7 +21,7 @@ "@braintree/sanitize-url": "^7.1.1", "@clickhouse/client-common": "1.23.0-head.fae5998.1", "@esm2cjs/p-queue": "^7.3.0", - "@hyperdx/common-utils": "^0.28.0", + "@hyperdx/common-utils": "^0.28.1", "@hyperdx/node-opentelemetry": "^0.9.0", "@hyperdx/passport-local-mongoose": "^9.0.1", "@modelcontextprotocol/sdk": "^1.27.1", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 3fe83c9ed7..19853f8613 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,93 @@ # @hyperdx/app +## 2.38.0 + +### Minor Changes + +- 503aac82: Show GPU utilization and GPU memory utilization charts in the log/span side + panel Infrastructure section when `hw.gpu.*` metrics (OTel hardware semconv) + exist for the correlated host/node. Multiple GPUs on a host render as separate + series grouped by `hw.id`, and utilization is split per GPU engine by + `hw.gpu.task` (general/encoder/decoder) so a node saturated on video encode is + still visible; a missing task is reported as `general`. The section is fully + hidden when no GPU metrics are present and partially rendered when only one + metric is available. + + The Infrastructure tab now also treats a Kubernetes resource attribute that is + present but empty (for example `k8s.node.name: ""`) as absent. Such rows + previously surfaced an Infrastructure tab that could render nothing. + + Fix GPU chart availability leaking across rows: switching the side panel to a + row on a different host briefly rendered the previous host's set of GPU + charts, because the availability query keeps the prior result readable while + the new one runs. + +- 38e99a37: Add a read-time, schema-agnostic LLM observability dashboard at `/llm` (beta, linked from the dashboards list) — no ingestion changes required, and it works retroactively on already-ingested telemetry. Traces instrumented with the OTel GenAI semantic conventions, OpenLLMetry, OpenInference, or the Vercel AI SDK are interpreted at query time to chart traffic, token split (uncached/cached/cache-write/output/reasoning), estimated cost by model (bundled price catalog with cache-read discounts and cache-write premiums; an instrumentation-provided cost attribute always wins), latency/TTFT, tool analytics, per-session timelines with lazy-loaded conversation views, and side-by-side LLM span/log search. Aggregations elect an app's own cost-reporting spans as the authoritative per-call reporters so apps emitting several instrumentation dialects in parallel (e.g. opencode emitting OpenInference and Vercel AI spans for each call) are counted once — verified to match opencode's self-reported session cost exactly. + +### Patch Changes + +- 3f7934a5: chore: Add isSourceAllowed prop to SourceSelectControlledComponent +- b917308d: fix: metric names in the chart editor are now listed deterministically instead of sampled. The dropdown discovered names with `groupUniqArray(3000)(MetricName)`, which keeps an arbitrary subset once a metrics table holds more than 3000 distinct names — the survivors follow hash order, not name order — so metrics that exist and are actively reporting could be unselectable, with no warning and no way to search for what had been dropped. Names are now fetched with an ordered, paginated query and matched server-side, ranked so an exact match is always on the first page, and the dropdown says when the list is incomplete. Also fixes the metric list ignoring the chart's selected time range, which pinned it to the last 24 hours. +- bf4443df: feat: Support autocomplete for PromQL label filters +- 55db91fa: feat: Support static filters in MCP +- 89a897ec: Fixed single-series histogram charts failing with "Unknown expression or function identifier" when sorted by a group-by column or expression. The histogram translation packs group values into a single `group` Array, so the table default ORDER BY (the raw group-by text) referenced source columns that no longer exist in scope; matched sort items now address the packed array positionally. +- fbb1e20f: Preserve conditional color rules for SQL and PromQl chart configs +- 020e85f3: Fix two problems with the chart editor's metric name picker. The truncation and load-failure notices now render below the input instead of above it, so they no longer push the field down out of alignment with the browse-metrics button beside it, and both were shortened to fit the tile editor's column without wrapping. A search that matches nothing now says so rather than silently hiding the dropdown, and offers the searched name as a selectable option — the catalog only covers the most recent three days of the chart's time range, so a metric that stopped reporting was previously impossible to chart by name. +- f1062a7b: Fixed multi-series metric charts failing with "Unknown expression or function identifier" when sorted by an expression group-by (e.g. `ResourceAttributes['service.name']`). Table tiles default their ORDER BY to the group-by text, so any multi-series metric table grouped by a resource/attribute-derived expression failed to render. Such sort expressions are now evaluated inside each per-series branch through internal companion columns instead of being re-evaluated in the composed outer query, where the source columns no longer exist. +- cdcb023e: fix: Reliably show service name and level in pattern sample drawer +- 0ebb689a: fix: De-dupe PromQL labels and values to prevent Mantine crash +- 4184a898: feat: Support dashboard filters based on Prometheus label values +- 27360036: feat: Support series filter (matcher) in PromQL label dashboard filters +- bcf0257c: feat: Accept optional time bounds on Prometheus label values endpoint +- c7965927: feat: Support a custom template for PromQL series legends +- 83c1b57f: feat: Display static value filters +- 66f6cf0b: Add a `window.hdx` browser-console debug handle and a "Copy debug info" action in the Help menu, so you can confirm which build is deployed and grab the context worth attaching when filing an issue. `window.hdx.report()` (and the Help menu action) produces a pasteable summary: frontend version (from package.json), backend/API version (from `/api/health` — the two deploy separately), deployment mode, user/team ids, enabled env-configurable feature flags, current URL, screen/viewport/OS/browser info, and the RUM session id. The handle is installed once and reads its async fields (server version, identity, features, session id) live via getters. +- cff6388c: feat: Add static filters to schemas and APIs +- 53336f78: fix(charts): show decimals on Y-axis ticks under 10 in magnitude + + The Y-axis of a time series chart (and the CLI's termchart equivalent) + always rounded tick labels to 0 decimal places, regardless of the chart's + Number Format settings. Charts whose values live under 1 (fractional + gauges, ratios, sub-1 rates) rendered every axis tick as `0` even though + the tooltip and legend showed the correct value. + + A tick under 10 in magnitude (as displayed - a percent tick's magnitude is + checked against its ×100 value, not its raw 0-1 ratio) now honors the + chart's configured decimals, capped at 2 to keep the label within the + axis's fixed width. A tick of 10 or more, and a tick of exactly 0, stay + integers exactly as before, whatever the chart's Number Format configures + + - so ordinary counts and the byte/percent tiles in the bundled dashboard + templates are unaffected. + +- 25a3b015: List every supported template variable in the webhook form, including the + enriched set added to Generic and incident.io bodies (`{{alertId}}`, + `{{status}}`, `{{alertType}}`, `{{comparator}}`, `{{threshold}}`, + `{{thresholdMax}}`, `{{value}}`, `{{groupKey}}`, `{{sourceQuery}}`, + `{{teamId}}`, `{{note}}` and ISO-8601 `{{startTimeISO}}` / `{{endTimeISO}}`). + Each variable now carries a one-line description, so a webhook body can be + written without leaving the form. +- 0a187457: feat: Allow creation and editing of static list filters in the UI +- Updated dependencies [74c28e7f] +- Updated dependencies [25a3b015] +- Updated dependencies [9c4f94f2] +- Updated dependencies [808b3453] +- Updated dependencies [b917308d] +- Updated dependencies [bf4443df] +- Updated dependencies [55db91fa] +- Updated dependencies [89a897ec] +- Updated dependencies [f0d1cef5] +- Updated dependencies [f1062a7b] +- Updated dependencies [4184a898] +- Updated dependencies [27360036] +- Updated dependencies [7ed8dc8c] +- Updated dependencies [bcf0257c] +- Updated dependencies [c7965927] +- Updated dependencies [d9c5c455] +- Updated dependencies [cff6388c] + - @hyperdx/api@2.38.0 + - @hyperdx/common-utils@0.28.1 + ## 2.37.0 ### Minor Changes diff --git a/packages/app/package.json b/packages/app/package.json index 8900ff4c55..00248d7cf3 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@hyperdx/app", - "version": "2.37.0", + "version": "2.38.0", "private": true, "license": "MIT", "engines": { @@ -38,7 +38,7 @@ "@hookform/resolvers": "^3.9.0", "@hyperdx/api": "workspace:*", "@hyperdx/browser": "^0.22.1", - "@hyperdx/common-utils": "^0.28.0", + "@hyperdx/common-utils": "^0.28.1", "@hyperdx/node-opentelemetry": "^0.9.0", "@mantine/core": "^9.0.0", "@mantine/dates": "^9.0.0", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index ea2c5a2d75..d0eacd515d 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,26 @@ # @hyperdx/cli +## 0.6.3 + +### Patch Changes + +- 53336f78: fix(charts): show decimals on Y-axis ticks under 10 in magnitude + + The Y-axis of a time series chart (and the CLI's termchart equivalent) + always rounded tick labels to 0 decimal places, regardless of the chart's + Number Format settings. Charts whose values live under 1 (fractional + gauges, ratios, sub-1 rates) rendered every axis tick as `0` even though + the tooltip and legend showed the correct value. + + A tick under 10 in magnitude (as displayed - a percent tick's magnitude is + checked against its ×100 value, not its raw 0-1 ratio) now honors the + chart's configured decimals, capped at 2 to keep the label within the + axis's fixed width. A tick of 10 or more, and a tick of exactly 0, stay + integers exactly as before, whatever the chart's Number Format configures + + - so ordinary counts and the byte/percent tiles in the bundled dashboard + templates are unaffected. + ## 0.6.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 68ca52c4f6..41d1706c02 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@hyperdx/cli", - "version": "0.6.2", + "version": "0.6.3", "license": "MIT", "type": "module", "repository": { @@ -41,7 +41,7 @@ }, "devDependencies": { "@clickhouse/client": "1.23.0-head.fae5998.1", - "@hyperdx/common-utils": "^0.28.0", + "@hyperdx/common-utils": "^0.28.1", "@jest/globals": "^30.2.0", "@types/crypto-js": "^4.2.2", "@types/jest": "^29.5.14", diff --git a/packages/common-utils/CHANGELOG.md b/packages/common-utils/CHANGELOG.md index 7e0d554294..3c516d8fab 100644 --- a/packages/common-utils/CHANGELOG.md +++ b/packages/common-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @hyperdx/common-utils +## 0.28.1 + +### Patch Changes + +- 74c28e7f: feat: Alerts now persist their own `displayName` and `tags` +- b917308d: fix: metric names in the chart editor are now listed deterministically instead of sampled. The dropdown discovered names with `groupUniqArray(3000)(MetricName)`, which keeps an arbitrary subset once a metrics table holds more than 3000 distinct names — the survivors follow hash order, not name order — so metrics that exist and are actively reporting could be unselectable, with no warning and no way to search for what had been dropped. Names are now fetched with an ordered, paginated query and matched server-side, ranked so an exact match is always on the first page, and the dropdown says when the list is incomplete. Also fixes the metric list ignoring the chart's selected time range, which pinned it to the last 24 hours. +- 55db91fa: feat: Support static filters in MCP +- 89a897ec: Fixed single-series histogram charts failing with "Unknown expression or function identifier" when sorted by a group-by column or expression. The histogram translation packs group values into a single `group` Array, so the table default ORDER BY (the raw group-by text) referenced source columns that no longer exist in scope; matched sort items now address the packed array positionally. +- f1062a7b: Fixed multi-series metric charts failing with "Unknown expression or function identifier" when sorted by an expression group-by (e.g. `ResourceAttributes['service.name']`). Table tiles default their ORDER BY to the group-by text, so any multi-series metric table grouped by a resource/attribute-derived expression failed to render. Such sort expressions are now evaluated inside each per-series branch through internal companion columns instead of being re-evaluated in the composed outer query, where the source columns no longer exist. +- 4184a898: feat: Support dashboard filters based on Prometheus label values +- 27360036: feat: Support series filter (matcher) in PromQL label dashboard filters +- c7965927: feat: Support a custom template for PromQL series legends +- cff6388c: feat: Add static filters to schemas and APIs + ## 0.28.0 ### Minor Changes diff --git a/packages/common-utils/package.json b/packages/common-utils/package.json index e3c8686ac1..86ee7fc6a6 100644 --- a/packages/common-utils/package.json +++ b/packages/common-utils/package.json @@ -1,7 +1,7 @@ { "name": "@hyperdx/common-utils", "description": "Common utilities for HyperDX application", - "version": "0.28.0", + "version": "0.28.1", "license": "MIT", "private": true, "files": [ diff --git a/packages/otel-collector/CHANGELOG.md b/packages/otel-collector/CHANGELOG.md index 3339aeeac2..cda065776c 100644 --- a/packages/otel-collector/CHANGELOG.md +++ b/packages/otel-collector/CHANGELOG.md @@ -1,5 +1,11 @@ # @hyperdx/otel-collector +## 2.38.0 + +### Patch Changes + +- 808b3453: Accept `Bearer `-prefixed Authorization header values on the OTLP receiver in standalone mode (`OTLP_AUTH_TOKEN`). Previously only the bare-token form of the header was accepted, rejecting RFC 6750 clients that send `Authorization: Bearer `. The `Bearer`, `bearer`, and `BEARER` prefixed forms are now accepted alongside the bare token. + ## 2.37.0 ## 2.36.0 diff --git a/packages/otel-collector/package.json b/packages/otel-collector/package.json index 51cbf10891..6b702248a4 100644 --- a/packages/otel-collector/package.json +++ b/packages/otel-collector/package.json @@ -1,7 +1,7 @@ { "name": "@hyperdx/otel-collector", "description": "HyperDX OpenTelemetry Collector configuration and Docker image", - "version": "2.37.0", + "version": "2.38.0", "license": "MIT", "private": true } diff --git a/yarn.lock b/yarn.lock index db1bc4224c..07a29e4c77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4616,7 +4616,7 @@ __metadata: "@braintree/sanitize-url": "npm:^7.1.1" "@clickhouse/client-common": "npm:1.23.0-head.fae5998.1" "@esm2cjs/p-queue": "npm:^7.3.0" - "@hyperdx/common-utils": "npm:^0.28.0" + "@hyperdx/common-utils": "npm:^0.28.1" "@hyperdx/node-opentelemetry": "npm:^0.9.0" "@hyperdx/passport-local-mongoose": "npm:^9.0.1" "@modelcontextprotocol/sdk": "npm:^1.27.1" @@ -4708,7 +4708,7 @@ __metadata: "@hookform/resolvers": "npm:^3.9.0" "@hyperdx/api": "workspace:*" "@hyperdx/browser": "npm:^0.22.1" - "@hyperdx/common-utils": "npm:^0.28.0" + "@hyperdx/common-utils": "npm:^0.28.1" "@hyperdx/node-opentelemetry": "npm:^0.9.0" "@mantine/core": "npm:^9.0.0" "@mantine/dates": "npm:^9.0.0" @@ -4835,7 +4835,7 @@ __metadata: resolution: "@hyperdx/cli@workspace:packages/cli" dependencies: "@clickhouse/client": "npm:1.23.0-head.fae5998.1" - "@hyperdx/common-utils": "npm:^0.28.0" + "@hyperdx/common-utils": "npm:^0.28.1" "@jest/globals": "npm:^30.2.0" "@types/crypto-js": "npm:^4.2.2" "@types/jest": "npm:^29.5.14" @@ -4862,7 +4862,7 @@ __metadata: languageName: unknown linkType: soft -"@hyperdx/common-utils@npm:^0.28.0, @hyperdx/common-utils@workspace:packages/common-utils": +"@hyperdx/common-utils@npm:^0.28.1, @hyperdx/common-utils@workspace:packages/common-utils": version: 0.0.0-use.local resolution: "@hyperdx/common-utils@workspace:packages/common-utils" dependencies: From 09929038c70cf474c72ca097d9076a54b89731ac Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 4 Sep 2026 19:16:33 +0000 Subject: [PATCH 2/2] chore(release): update root CHANGELOG.md --- CHANGELOG.md | 232 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1ff3a646e..e26ac94b3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,238 @@ PR — keep the `hyperdx-release-notes` comment marker intact when editing so yo edits survive regeneration. Per-package detail lives in each `packages/*/CHANGELOG.md`. +## v2.38.0 — 2026-09-04 + + + +**LLM observability dashboard (beta)** + +You can now see what your LLM calls cost, how many tokens they consume and how +long they take to respond, without changing a line of instrumentation: a new +beta dashboard at `/llm` reads the traces you have already ingested and +interprets them at query time. It understands the OTel GenAI semantic +conventions, OpenLLMetry, OpenInference and the Vercel AI SDK, and works +retroactively over telemetry collected long before this release. Sending +`Authorization: Bearer ` to the OTel ingest endpoint now works too — +previously the standard RFC 6750 form was turned away as unauthorised. The +chart editor's metric dropdown also stops quietly hiding metrics on large +metrics tables. If a Prometheus Connection's host carries a path or a query +string, read the breaking change below before you upgrade. + +### 💥 Breaking Changes + +- **PromQL proxying keeps a Connection host's path prefix**: an absolute + Prometheus API path was joined to the host in a way that replaced the host's + own path, so a VictoriaMetrics cluster `vmselect` URL such as + `http://vmselect:8481/select/0/prometheus` was rewritten to + `/api/v1/query_range` and rejected. The path is now kept and appended to. A + host that carries a path never meant as a Prometheus API prefix — for example + `http://prom:9090/graph` copied out of the Prometheus UI — used to work by + accident and will now 404, so trim stray paths from your Connection hosts + before upgrading; root-mounted hosts such as `http://prom:9090` are + unaffected. Query parameters on the host are now only a fallback for a fixed + set of real Prometheus API params (`query`, `time`, `start`, `end`, `step`, + `match`/`match[]`, `limit`, `timeout`, `stats`), where a request value always + wins outright; any other host key is left as-is, is never overridable by the + request, and a non-Prometheus param sent by a direct API caller such as curl + or Terraform is now dropped rather than forwarded. Trim stray query strings + too if they weren't intended as Prometheus API params (#3047, thanks + @milansanjeev!). + +### ✨ New Features + +- **GPU charts in the log and span side panel**: the Infrastructure section now + charts GPU utilisation and GPU memory utilisation whenever `hw.gpu.*` metrics + (the OTel hardware semantic conventions) exist for the correlated host or + node. Every GPU on a host is drawn as its own series, grouped by `hw.id`, and + utilisation is split per GPU engine by `hw.gpu.task` — general, encoder, + decoder — so a node saturated on video encode is still visible; a missing task + is reported as `general`. The section hides itself entirely when there are no + GPU metrics and renders what it has when only one of the two is available. + Switching the panel to a row on a different host no longer briefly shows the + previous host's GPU charts while the new ones load. The Infrastructure tab + also stops appearing for rows whose Kubernetes resource attribute is present + but empty, such as `k8s.node.name: ""`, which used to open a tab that could + render nothing (#2897, thanks @MikeShi42!). +- **Alert webhooks carry the alert's identity and condition**: Generic and + incident.io webhook bodies gain template variables describing the alert + itself — `{{alertId}}`, `{{status}}`, `{{alertType}}`, `{{comparator}}`, + `{{threshold}}`, `{{value}}`, `{{groupKey}}`, `{{sourceQuery}}`, `{{teamId}}` + and `{{note}}` — plus ISO-8601 `{{startTimeISO}}` and `{{endTimeISO}}` + alongside the existing Unix-ms `{{startTime}}` and `{{endTime}}`. Your + receiver can route, filter and dedupe on those fields instead of parsing the + rendered message body. Existing templates are unaffected: every new variable + is additive and renders empty when an alert doesn't carry it (#3057, thanks + @jordan-simonovski!). +- **Inline chart alerts through the external API and MCP**: the `inline` alert + source — an alert that carries its own chart config, with no saved search or + dashboard tile behind it — can now be created, updated, listed and deleted + through `/api/v2/alerts` and the MCP `clickstack_save_alert` / + `clickstack_get_alert` tools, using the same tile-config dialect as v2 + dashboards. The same validation the app applies holds here: the display-type + allowlist, metric formula validation, the formula source-kind gate, raw SQL + template validation, and team-scoped source and connection ownership. Passing + a `chartConfig` to a `tile` or `saved_search` alert is now rejected rather + than silently dropped, and reading an inline alert whose config carries + internal-only fields omits `chartConfig` instead of returning a lossy + approximation (#3043). +- **Alerts carry their own display name and tags**: an alert now persists a + `displayName` and `tags` of its own, so it can be named and labelled in its + own right rather than being identified only by the saved search, dashboard + tile or chart config it watches (#3063, thanks @pulpdrew!). +- **Filters can offer a static list of values**: a filter can now be given a + fixed set of values to choose from, instead of the values always being + discovered from your data. The static list is carried through the schemas and + APIs as well as the app, and the filter renders as a picker over those values, + so a filter defined this way survives a round trip through the API and is + chosen from rather than typed into. You can create and edit one from the + dashboard filter editor as well, rather than only through the API, and the MCP + server understands static filters too, so an agent reading or writing a + dashboard keeps them intact (#3017, #3020, #3022, #3060, thanks @pulpdrew!). +- **Dashboard filters built on Prometheus label values**: a dashboard filter can + now take its values from a Prometheus label, so a dashboard of PromQL charts + can be filtered by the labels its metrics actually carry. Such a filter also + accepts a series filter (matcher), so its values come only from the series the + matcher selects rather than every series that carries the label (#3053, #3080, + thanks @pulpdrew!). +- **"Copy debug info" in the Help menu, and a `window.hdx` console handle**: + when something looks wrong, you can now grab everything worth attaching to an + issue in one action — the frontend and backend versions (they deploy + separately, so they can differ), deployment mode, your user and team ids, the + env-configurable feature flags that are on, the current URL, screen, viewport, + OS and browser details, and the session id. The same summary is available from + the browser console as `window.hdx.report()` (#3056). +- **PromQL series legends can follow your own template**: a PromQL chart now + accepts a custom template for its series legends, so you can label each series + the way you want instead of taking the default rendering of its labels + (#3055, thanks @pulpdrew!). + +### 🧪 Experimental + +- **LLM observability dashboard, in beta**: a new dashboard at `/llm`, linked + from the dashboards list, charts LLM traffic, token split (uncached, cached, + cache-write, output and reasoning), estimated cost by model, latency and time + to first token, and tool usage — plus per-session timelines with conversation + views and side-by-side LLM span and log search. Costs come from a bundled + price catalogue that accounts for cache-read discounts and cache-write + premiums, and a cost attribute reported by your own instrumentation always + wins over the estimate. Where an app emits several instrumentation dialects + for the same call — opencode, for instance, emits both OpenInference and + Vercel AI spans — one is elected as the authoritative reporter so the call is + counted once. Being beta, the dashboard's charts and layout may still change; + no flag or ingestion change is needed to try it (#2990). + +### 🔧 Improvements + +- **The webhook form lists every template variable it supports**: the form now + shows the full set — including the enriched variables above and the new + `{{thresholdMax}}`, the upper bound of a `between` or `outside` condition, + which receivers needed to reconstruct the range that fired — each with a + one-line description, so a webhook body can be written without leaving the + form. `{{thresholdMax}}` renders empty for every other comparator (#3071). +- **A metric the catalogue has not listed can still be charted by name**: the + chart editor's metric picker now says when a search matches nothing, instead + of silently hiding the dropdown, and offers the name you typed as a selectable + option — the catalogue only covers the most recent three days of the chart's + time range, so a metric that had stopped reporting was previously impossible + to chart by name. The truncation and load-failure notices also moved below the + input and were shortened, so they no longer push the field out of alignment + with the browse-metrics button beside it or wrap in the tile editor's column + (#3054, thanks @teeohhem!). +- **PromQL label filters autocomplete as you write them**: the PromQL editor now + suggests label filters as you type, so building a query no longer means + recalling exactly how your metrics are labelled (#3072, thanks @pulpdrew!). +- **Prometheus label values can be scoped to a time range**: the Prometheus + label values endpoint now accepts optional time bounds, so a lookup can be + limited to the window you are querying rather than covering everything the + source has seen (#3039, thanks @pulpdrew!). +- **Label lookups honour `match[]` series selectors**: the Prometheus labels and + label values endpoints now evaluate `match[]` series selectors on ClickHouse + TimeSeries connections, so a lookup can be narrowed to the series a selector + picks out instead of returning everything the source carries (#3079, thanks + @pulpdrew!). + +### 🐛 Bug Fixes + +- **Ingest accepts both Authorization header formats**: the OTel ingest endpoint + in OpAMP-managed mode and the OTLP receiver in standalone mode + (`OTLP_AUTH_TOKEN`) now accept `Bearer`, `bearer` and `BEARER` prefixed tokens + as well as the bare token, so an SDK or client that follows RFC 6750 no longer + has its telemetry rejected. Existing bare-token senders are unaffected + (#3027). +- **Every metric name is selectable in the chart editor**: the metric dropdown + used to sample the names it offered, so once a metrics table held more than + 3000 distinct names, metrics that existed and were actively reporting could be + missing from the list with no warning and no way to search for them. Names are + now listed in order and matched as you type, an exact match always appears + first, and the dropdown tells you when the list is incomplete. The list also + respects the chart's selected time range instead of always looking at the last + 24 hours (#2747, thanks @teeohhem!). +- **Multi-series metric charts sorted by an expression group-by render again**: + a multi-series metric table grouped by an expression such as + `ResourceAttributes['service.name']` failed with "Unknown expression or + function identifier", because table tiles sort by their group-by text by + default and that expression could not be resolved once the series were + composed together. Sort expressions are now evaluated within each series, so + these tiles chart as expected (#3013). +- **Grouped single-series histogram charts sort without erroring**: the same + "Unknown expression or function identifier" failure hit a histogram chart + sorted by a group-by column or expression, because the histogram query packs + the group values into one array and the table's default sort still named the + original columns. Matching sort items now address the packed array by + position, so a grouped histogram table renders (#3045). +- **Y-axis tick labels keep their decimals on small values**: a time series + chart whose values live under 1 — fractional gauges, ratios, sub-1 rates — + labelled every axis tick `0`, even though the tooltip and legend showed the + right value. A tick under 10 in magnitude now honours the chart's Number + Format decimals, capped at two so the label still fits the axis, while ticks + of 10 or more and a tick of exactly 0 stay integers as they were — so ordinary + counts and the byte and percent tiles in the bundled dashboard templates look + the same as before. The CLI's terminal charts get the same fix (#3030, thanks + @arj22!). +- **Conditional colour rules stick on SQL and PromQL charts**: the conditional + colour rules you set on a chart configured with raw SQL or with PromQL are now + preserved in the chart's config instead of being dropped (#2940, thanks + @espenloov!). +- **Duplicate PromQL labels no longer crash the filter picker**: a source that + reported the same label name or label value twice took the PromQL label + filter's Mantine control down with it. Labels and values are now de-duplicated + before they reach the picker (#3083, thanks @pulpdrew!). +- **The pattern sample drawer shows service name and level reliably**: samples + opened from a log pattern now consistently show the service that emitted the + event and its severity level, instead of leaving those fields blank (#3062, + thanks @pulpdrew!). +- **`{{sourceQuery}}` renders for chart-backed alerts, and Test Webhook fills + every variable**: `{{sourceQuery}}` read only the saved search's filter, so an + alert backed by a chart config — where the query lives on the alert or the + tile — advertised a variable that never rendered; it now resolves the query + from whichever config backs the alert, the builder `where` or the raw + `sqlTemplate`. Test Webhook also sends a sample value for every variable + rather than only the original seven, so a body such as + `{"value": {{value}}}` is no longer sent as `{"value": }` and rejected, + failing the test for a template that works on a real firing (#3071). +- **Dashboards saved through MCP keep their tile settings**: three long-standing + problems on the external v2 dashboards path are fixed. A gauge tile saved + through `clickstack_save_dashboard` with `isDelta: true` was persisted as a + non-delta, because the flag was dropped converting MCP tiles to the internal + shape; a tile config carrying an unrecognised `configType`, such as `promql`, + was silently stored as a builder config and skipped the formula and + number-select rules, and is now rejected outright; and validation errors on + alert bodies no longer collapse to `Invalid input`, reporting the failing + branch's own message instead (#3043). + + + +### 📦 Package changelogs + +- `@hyperdx/api` 2.37.0 → 2.38.0 — [changelog](https://github.com/hyperdxio/hyperdx/blob/main/packages/api/CHANGELOG.md#2380) +- `@hyperdx/app` 2.37.0 → 2.38.0 — [changelog](https://github.com/hyperdxio/hyperdx/blob/main/packages/app/CHANGELOG.md#2380) +- `@hyperdx/cli` 0.6.2 → 0.6.3 — [changelog](https://github.com/hyperdxio/hyperdx/blob/main/packages/cli/CHANGELOG.md#063) +- `@hyperdx/common-utils` 0.28.0 → 0.28.1 — [changelog](https://github.com/hyperdxio/hyperdx/blob/main/packages/common-utils/CHANGELOG.md#0281) +- `@hyperdx/otel-collector` 2.37.0 → 2.38.0 — [changelog](https://github.com/hyperdxio/hyperdx/blob/main/packages/otel-collector/CHANGELOG.md#2380) + + + ## v2.37.0 — 2026-08-28