Commit Graph
3049 Commits
Author SHA1 Message Date
Sai Nikhil d0fca58714 fix: should restrict patterns count api on logs page (#13515)
should restrict the patterns count call on logs page , search or
visualize mode ent #2292
2026-07-29 06:05:00 +00:00
ktx-akshay 8ef7988e5d fix: extended retention date picker rendering blank for streams with unlimited retention (#13510) 2026-07-29 05:33:56 +00:00
Loakesh Indiran cc155fca6c fix(synthetics): report a folder that still holds checks, and lift run-detail contrast (#13524)
Two unrelated synthetics fixes, both small.

## 1. Deleting a folder that still contains checks

Deleting a synthetics folder with checks in it showed the user a raw
database error:

```
DbError# SeaORMError# Execution Error: error returned from database:
(code: 787) FOREIGN KEY constraint failed
```

Alerts handles the same situation properly — *"Folder contains alerts,
please move/delete alerts from folder"*.

### Cause

The guard already existed. `FolderError::DeleteWithSynthetics` is
defined, and `folder_error_response` already maps it to *"Folder
contains synthetics, please move/delete synthetics from folder"*. It
simply never fired, because the two sides of the comparison are
different identifiers:

```
folders:     id = 3H8CpCLKyBqPokByb5pKetSlgnw   folder_id = 7487841328038936576   name = test
synthetics:  folder_id = 3H8CpCLKyBqPokByb5pKetSlgnw     <- stores folders.id
```

The delete endpoint receives the user-facing `folders.folder_id`
(`7487841328038936576`), but `ListSyntheticsParams.folder_id` filters
`synthetics.folder_id`, which holds the folder's **primary key**. The
count returned 0 for every folder, the guard passed, and the database
rejected the delete on the foreign key.

Dashboards, alerts and reports were unaffected: their list queries reach
the folder through a join and filter on `folders.folder_id`, so they
compare like with like.

### Fix

Translate the id with the existing `folders::get_pk_by_name` before
counting. A folder that doesn't exist falls through to the `exists`
check below, which already reports `NotFound`.

## 2. Run-detail contrast

Every field label in the protocol run detail — Status, Response time,
Error, Location, Runtime, Probe ID, Trigger, plus the not-evaluated
assertion rows — used `text-text-muted`. In light mode that token
resolves to `grey-300`, and its own definition documents it as
*"disabled, placeholder, de-emphasized"*. These are captions, not
disabled controls, so they now use `text-text-secondary` (`grey-500`).

## Testing

- `cargo check -p db --features enterprise` — clean.
- `cargo test -p db --features enterprise folders` — 14 pass.
- `ProtocolRunSummary.spec.ts` — 22 pass.

The id mismatch was confirmed against a live local SQLite metadata DB
(the row values quoted above are real), and the failing delete
reproduced exactly the 500 in the screenshot.

Not covered by an automated test: `delete_folder` has no DB-backed test
harness today, and the existing tests in that module only assert on
error-variant construction. Worth adding one if this area gets touched
again.
2026-07-28 23:40:09 +00:00
IluckySiandHengfei Yang c278682cca feat(web): add categraf option in custom metric ingestion (#13466)
This PR adds categraf as a explicit custom metric ingestion.

The configuration as follows:

> [[writers]]
> url = "http://localhost:5080/api/default/prometheus/api/v1/write"
> basic_auth_user = "root@example.com"
> basic_auth_pass = "o2oi_dMJ0RsB50MzVt2CVPCripths0WaGE832"

<img width="3064" height="1162" alt="image"
src="https://github.com/user-attachments/assets/189c3c96-441c-4476-8c31-943acaa788b0"
/>
<img width="3840" height="1862" alt="image"
src="https://github.com/user-attachments/assets/0408704b-b1d1-4546-8d8b-86dd5895d8bc"
/>

Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
2026-07-28 12:29:01 +00:00
ktx-vaidehi c9fc8d3b55 fix: dashboard builder redesign (#13419) 2026-07-28 10:59:27 +00:00
Abhay Padamani 5a0b10e7af fix: _timestamp alias migration (#13489)
## How `rewriteQueryTimestampAlias` works

Example query:

```sql
SELECT a AS _timestamp FROM t GROUP BY _timestamp
```

### Step 1 — walk the string, one token at a time
Move left to right, grouping characters into tokens (words, quotes,
punctuation). Keep a tiny bit of state: **"which clause am I in"** and
**"did I just see AS"**.

### Step 2 — update state on keywords, decide on `_timestamp`

| Token | State update | If it's `_timestamp`, decision |
|---|---|---|
| `SELECT` | clause = SELECT | — |
| `a` | — | — |
| `AS` | expectAlias = true | — |
| `_timestamp` (chars **12–21**) | — | in SELECT + just saw AS → **alias
definition** → record an edit |
| `FROM` | clause = FROM | — |
| `t` | — | — |
| `GROUP` | clause = GROUP | — |
| `BY` | (stay in GROUP) | — |
| `_timestamp` (chars **39–48**) | — | in GROUP + we saw an alias →
**reference** → record an edit |

### Step 3 — the edits we recorded (just notes, nothing changed yet)

```
edit 1: replace chars 12–22 with "ts"
edit 2: replace chars 39–49 with "ts"
```

That's it — the scan's only job is to find the **character positions**
of alias `_timestamp`s. It figures out positions itself (by tracking
clause state), instead of asking a parser for them.

### Step 4 — rebuild by copying the original + splicing

```
out  = sql.slice(0, 12)   → "SELECT a AS "
     + "ts"
     + sql.slice(22, 39)  → " FROM t GROUP BY "
     + "ts"
     + sql.slice(49)      → ""
```

Result: `SELECT a AS ts FROM t GROUP BY ts`

### Why this guarantees "only the alias changed"
Everything in the output comes from `sql.slice(...)` — literal copies of
the original — **except** the spliced `"ts"`. There's no re-generation
step (no parse/stringify), so nothing else *can* change.
2026-07-28 10:48:19 +00:00
7d212f4621 feat: workflows incident connection (#13472)
This connects incidents to workflows, so any lifecycle event of incident
will trigger workflow.

design at:
https://github.com/openobserve/designs/blob/main/infrastructure/workflows/design.md

---------

Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com>
Co-authored-by: Yashodhan Joshi <yjdoc2@gmail.com>
Co-authored-by: sai nikhil kethe <nikhil@openobserve.ai>
Co-authored-by: Shrinath Rao <shnath@openobserve.ai>
2026-07-28 10:04:35 +00:00
Bhargav e9596a10a3 feat: Mobile rum sdk v2 (#13503)
Design at: design/mobile-rum-sdk-evaluation/design-docs

Backend changes exist to make the OpenObserve RUM intake accept the
mobile SDK wire format alongside the existing browser format.

src/api/src/handler/http/request/rum/ingest.rs

200 → 202 Accepted on /rum, /logs, /replay | ---> OpenObserve-family
SDKs (which the mobile forks derive from) treat any non-202 as an
unexpected error and drop the batch.

#[serde(default)] on Event ---> Mobile replay omits creation_reason /
index_in_view that the browser format sends.

Multi-segment replay handling ---> Browser sends 1 segment + 1 event
object; mobile sends N segment parts + one event JSON array. Handler now
collects all segments, parses event as array-or-object, pairs them,
emits NDJSON → one _sessionreplay row per segment.

MAX_SEGMENTS=200, 16 MB decompressed cap via .take() --->
Decompression-bomb guard, newly needed now that N segments are accepted.
2026-07-28 07:58:21 +00:00
udevandsai nikhil kethe 24938430db fix(evals): ensure o2_ingest_ts in defined schema (#13506)
commit-id:e9e87fba

---
**Stack**:
- #13506 ⬅
- #13491
- #13481
- #13453
- #13428
---
⚠️ *Part of a stack created by [spr](https://github.com/ejoffe/spr). Do
not merge manually using the UI - doing so may have unexpected results.*

---------

Co-authored-by: sai nikhil kethe <nikhil@openobserve.ai>
2026-07-28 07:56:32 +00:00
Loakesh Indiran 967433fe9e fix(synthetics): stop the HTTP check card vanishing on non-GET methods (#13505)
## Problem

On a new HTTP / API check, picking **POST** (or any method other than
GET/HEAD) makes the entire **HTTP Request** card disappear — method,
timeout, follow-redirects, headers, assertions, all of it. The console
shows only:

```
SyntaxError: 2
    at ... nextToken ... parse ...
```

## Cause

The request-body field is the only thing that renders for non-GET/HEAD
methods, and its placeholder message was the literal text `{"key":
"value"}`:

```json
"bodyPlaceholder": "{\"key\": \"value\"}",
```

To vue-i18n `{...}` is an interpolation slot, so its parser hits `"`
where an identifier must be:

```
SyntaxError: Invalid token in placeholder: '"key":'
```

Messages compile lazily (`__INTLIFY_JIT_COMPILATION__: true` in
`vite.config.ts`), so nothing happens until the message is first
rendered. The throw then lands inside render and tears down the whole
`CheckHttpConfig` subtree — which is why the card vanishes, and why it
only vanishes for the methods that show a body.

## Fix

Escape the braces as `{'{'}` / `{'}'}`. Rendered output is
byte-identical — verified through `createI18n().t()`:

```
raw     -> "{\"key\": \"value\"}"   (logs a compilation error, throws under the app's config)
escaped -> "{\"key\": \"value\"}"   (compiles clean)
```

Applied across all 15 locale files, since the crash is
locale-independent.

Two other **en-US** messages carried the same latent crash and are
escaped the same way:
- `pipeline.streamSelectionNameInvalid` — a raw `@`, parsed as
linked-message syntax
- `aiToolset.genericDataPlaceholder` — `{}`, an empty placeholder

## Guard

New `enUsMessages.spec.ts` compiles every en-US message the way vue-i18n
does (`baseCompile` with a rethrowing `onError` — the default collects
errors and returns a best-effort AST, hiding exactly this). The next
such message fails CI instead of silently deleting a form section.

The other locales still have ~250 broken messages, overwhelmingly
placeholder *names* that were translated (`{方向}`, `{秒}`). Those break
interpolation semantics as well as compilation and need per-locale
review — out of scope here, so the guard is en-US only for now.

## Testing

**Before the fix**, driven in a real browser against a local build:

```
card on load: 1 | aria-expanded: true | options: 7
select POST -> card still there: 0 | HTTP Request heading: 0
[console] SyntaxError: 2
```

**After the fix**, every method exercised through the real select:

| method | selected | card | body field | assertions | new console
errors |
|---|---|---|---|---|---|
| POST | POST | 1 | 1 | 1 | 0 |
| PUT | PUT | 1 | 1 | 1 | 0 |
| DELETE | DELETE | 1 | 1 | 1 | 0 |
| PATCH | PATCH | 1 | 1 | 1 | 0 |
| HEAD | HEAD | 1 | 0 | 1 | 0 |
| OPTIONS | OPTIONS | 1 | 1 | 1 | 0 |
| GET | GET | 1 | 0 | 1 | 0 |

Body field visibility is correct in every case (hidden for GET/HEAD
only), zero console errors throughout.

**Full round-trip**, also in the browser — creating a non-GET check was
impossible before this fix:

- Create with POST + body `{"ping": "pong"}` → `POST
/api/default/synthetics` → **200**, redirect to the list, 0 console
errors. Wire payload carries `"method":"POST"` and the body verbatim.
- Reopen for edit → card present, method `POST`, body field populated
with `{"ping": "pong"}`, 0 console errors.

**Unit tests:** 598 passed, 0 failed across `locales`,
`components/synthetics`, `views/synthetics`, `utils/synthetics`,
`composables/synthetics`, including the new `enUsMessages.spec.ts`.

One suite, `views/synthetics/MonitorResults.spec.ts`, fails to load with
`Cannot read properties of undefined (reading 'value')`. That is
pre-existing and unrelated — `useLocalTimezone` gets no localStorage
under Node 26's vitest environment, and it fails identically on a clean
tree.
2026-07-28 07:09:48 +00:00
ktx-akshay 3af2a67727 fix: independent scrolling for dimensions list and charts in Insights drawer (#13504)
## Summary

Fixes shared scrolling in the Insights drawer (Logs → Analyze) where the
Dimensions sidebar and the charts panel scrolled together as one unit.
With many dimensions (e.g. 40+ Kubernetes fields), users had to scroll
through the entire Dimensions list just to reach the charts below.

## Root cause

The dashboard content relied on `flex-1` / `min-h-0` to constrain its
height, but its parent container wasn't a flex container, so those
styles had no effect. The content simply grew to fit everything, and the
drawer's outer scrollbar ended up scrolling both panels together instead
of letting each one scroll independently.
2026-07-28 07:09:14 +00:00
Ashish Kolhe 60b1942bf2 fix: agent env version filters (#13488)
Makes **environment** and **version** first-class identity dimensions
for GenAI agents, and adds an A/B **version-compare** experience to LLM
Insights.

### What's in it
- **Schema / identity (OSS, ungated):** migration adds `env` +
`agent_version` to `gen_ai_agents`; entity/table ops and agent-mapping
config carry them through; env/version surfaced across all AI screens
via a shared Env→Agent→Version cascade.
- **Version compare (LLM Insights):** pick two versions of an agent,
align their windows (**Since each rollout** / **Same wall-clock** /
**Manual**), and read latency / cost / error-rate deltas with confidence
intervals plus a tri-state failure-class diff (introduced / fixed /
shared).
- **Handlers + service wiring:** `#[cfg(feature = "enterprise")]` call
sites for the compare/agent-signals endpoints (enterprise impl + OSS 403
stub); the sketch-merge compute lives in the companion enterprise PR.


~120 files; primarily `web/src` (AI Observability + traces) and
`src/infra`/`src/core`/`src/config` for the schema and thin service
layer.
2026-07-28 03:10:14 +00:00
Loakesh Indiran cca95a9ec6 fix(synthetics): stop reporting unevaluated HTTP assertions as passed (#13498)
## Problem

A failing HTTP check showed **Failed** at the top of the run detail and
**Assertions: Passed** below it — a green tick against `status_code eq
200` on a run that never got a status code.

The probe is right to omit `assertions_passed` when the request never
returned a response (connection refused, EOF, timeout): it returns
before evaluating anything, because there is nothing to assert against.
The view had two branches for three states:

```vue
:variant="run.assertionsPassed === false ? 'error' : 'success'"
```

`null` is not `false`, so "never ran" landed in the success branch.

| `assertions_passed` | means | UI showed |
|---|---|---|
| `true` | ran, all passed | Passed ✅ |
| `false` | ran, one failed | Failed ✅ |
| *absent* | never ran | Passed ❌ |

## Changes

1. **Three states, not two.** Absent renders as a neutral **Not
evaluated** badge with neutral rows and a line explaining why.

2. **Render the probe's per-assertion results** when the record carries
them (see synthetic-o2-agent#4), so a run with several failing
assertions shows each one with its own comparison string instead of a
single inferred red row. Records written before the probe echoed that
array keep the old inference path.

3. **Fix `response_time_ms` on the legacy path.** The probe's detail
leads with `response_time`, so `startsWith` never matched the configured
field name and a failing latency assertion left every row green. The two
renamed fields now go through a lookup map rather than one special case.

4. Reported rows are self-describing, so the assertions card no longer
depends on the check-config fetch succeeding (403 on community builds,
deleted check, …).

## Testing

`ProtocolRunSummary.spec.ts` — 7 new tests covering the not-evaluated
state, the still-passes case, the reported-array path, config-fetch
failure, the legacy single-failure record, and `response_time_ms`. Full
synthetics sweep: 499 passed, 0 failed.

Verified end to end against a local deployment with five checks covering
each case:

| Check | Assertions | Record | UI |
|---|---|---|---|
| AT-A | `status_code eq 200` | `assertions_passed: true` | Passed, row
green |
| AT-B | `status_code eq 999` | `false` + array | Failed, row red |
| AT-C | `status_code eq 999` + `body contains NOPE` | `false` + array
of 2 | Failed, **both** rows red |
| AT-D | `response_time_ms lt 1` | `false` + array | Failed, row red |
| AT-E | unreachable target | `assertions_passed` absent | **Not
evaluated** |

Before: AT-C showed one red row and one green, AT-D showed no red row,
AT-E showed Passed.
2026-07-28 01:21:39 +00:00
Loakesh Indiran ee3ce2296a feat(synthetics): pick net or browser agent in the private-agent setup drawer (#13496)
## What

The private-agent setup drawer composed a single install command, so the
only way to get a browser-capable private location was for the caller to
pin `agentType` — which the org-level **Private Locations** page never
does. A location that could run browser journeys was unreachable from
the page dedicated to private locations.

- **Agent-type tabs** (`Net` / `Browser`) drive `--type` on the composed
command. The caller's `agentType` is now the opening default rather than
a lock, so either kind can be installed into the same location from
anywhere the drawer opens.
- **Linux/Windows hidden under Browser** — `install.sh`'s linux path
downloads a Go release binary and Windows runs `install.ps1`; neither
can run Chromium. Switching to Browser from one of those tabs snaps the
platform back to Docker, so the command never composes an install that
cannot work.
- **Locations card empty state** — the check form now offers the "Set up
private agent" CTA when there are no locations at all, instead of a dead
"No locations available" box. That is exactly the state a fresh
self-hosted org starts in, and the one where the CTA matters most.
Applies to both the browser and HTTP/net check forms (shared
`CheckLocations.vue`).
- **`open` watcher gains `immediate`** — a drawer mounted already-open
never fired the transition and composed from defaults instead of its own
props.

## Also

`vite.config.ts`: the monaco plugin is gated behind `!isTesting`. Its
`rmdirSync(..., { recursive: true })` was removed in Node 26, which
stopped vitest from booting at all. Tests already swap in
`monacoEditorTestResolver`.

## Testing

- New `AgentSetupDrawer.spec.ts` — 7 tests covering the type tabs, the
`--type=browser` flag, and the platform fallback.
- `CheckLocations.spec.ts` — 2 tests for the empty + `allowPrivate`
path.
- Full synthetics sweep: 597 passed, 0 failed.

Verified end to end against a local deployment: net and browser agents
both registered into one `lcl-dev` private location, which then
advertises `BROWSER HTTP SSH TCP TLS`.
2026-07-28 01:19:05 +00:00
Harsh Mahajan b7ae83d2ad chore: UX revamp for Incidents RCA analysis (#13388) 2026-07-27 14:42:10 +00:00
Omkar Kesarkhane c047dfe4cf fix: updated browser check action buttons (#13482)
Editing a browser check offered Cancel / Continue / Update check on the
Journey step, where neither save-bearing label matched its behaviour:
Continue advanced to Configure without saving, and Update check saved
but deliberately stayed on the page. There was no obvious save-and-leave
action.

Edit mode now shows Cancel / Save & Continue / Save & Exit on the
Journey step, and the Configure step's primary button becomes Save &
Exit. Create mode is unchanged — a new check has no name, URL or
locations yet, so saving from the Journey step would always fail
validation.
2026-07-27 16:51:38 +05:30
Omkar Kesarkhane 237fbca3af fix: Synthetic check runs table sorting issue (#13477)
## What changed
This PR makes the Synthetics runs table sortable (with a default sort by
last-run, newest first) on all columns, using raw underlying values
(e.g. `durationMs`, `statusRank`, `locationName`) instead of the
formatted display strings the cells render. It also removes a
`tableFilterKey`-based force re-render hack and an inline error-badge
cell/`filterByError` helper that duplicated existing
`filterByErrorPattern` filtering. Separately, it fixes a loading-state
flash in `RunDetail.vue`/`ProtocolRunSummary.vue`: `MonitorResults.vue`
now passes a resolved `overrideMonitorType` down to `RunDetail`,
`RunDetail` seeds `monitorType` from that override in drawer mode to
skip a redundant fetch, and `loadRun()` now sets
`synthetics.loading.value = true` synchronously so the skeleton shows
instead of an empty/wrong-branch UI while monitor type resolves. A new
`ProtocolRunSummarySkeleton.vue` component replaces a generic
`OSkeleton` block to mirror the actual result-card layout. The runs
query limit in `useSyntheticResults.ts` was bumped from 500 to 1000, and
the runs page size default is kept at 10.

## Why
Reviewing `MonitorRuns.vue`'s pagination, default sort, and column
sorting surfaced that columns weren't sortable and had no default sort,
and that sorting on formatted values would produce incorrect ordering
(e.g. "900ms" sorting after "1.2s", or status ordering depending on
locale). Separately, the session's testing turned up a UI flash where
`RunDetail`/`ProtocolRunSummary` briefly rendered the wrong branch
(empty state or "browser" default) before `fetchCheck()`/monitor-type
resolution completed.
2026-07-27 16:04:39 +05:30
ktx-akshay 6a366c4d48 fix(dashboards): remove misleading "New dashboard" action and fix icon copy on empty Favorites state (#13454) 2026-07-27 08:40:33 +00:00
Omkar Kesarkhane 640e0647c6 fix: group Synthetics and RUM under an Experience menu (#13474)
Collapse the two top-level RUM and Synthetics rail items into a single
Experience group tile, mirroring how Data groups Streams/Pipelines and
Dashboards groups Reports. Driven entirely by a new NAV_GROUPS entry in
navGroups.ts; when Synthetics is disabled the group auto-collapses and
RUM falls back to a plain link.
2026-07-27 07:23:34 +00:00
ktx-vaidehi 3200c202c7 fix: emptystate animation migration (#13440) 2026-07-27 05:21:41 +00:00
udev 8ed0f95ea0 fix: resolve AI session schema and AnyValue handling (#13459)
## Summary

- remove legacy `tool_name` and `tool_args` references from the session
span SQL projection
- use the canonical `gen_ai_tool_name` field for session tool calls
- handle `gen_ai.input.messages` and `gen_ai.output.messages` as OTEL
`AnyValue` payloads in backend session summaries and frontend turn
rendering
- support structured values, JSON-encoded span values, plain strings,
scalar values, and unstructured object fallbacks without dropping
message content
- add regression coverage for the SQL schema and message normalization
paths

## Testing

- frontend unit tests: 145 passed
- backend session extraction tests: 10 passed
- frontend application type-check passed
- targeted ESLint passed
- Rust formatting and diff checks passed

## Reference

-
https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-events.md
2026-07-24 18:35:47 +00:00
Loakesh Indiran 3f49343426 feat(synthetics): private-agent token lifecycle, browser private agents & P0 lease fixes (#13432)
Synthetics work spanning private-agent tokens, browser private agents,
and job-lease correctness. (Enterprise backend:
openobserve/o2-enterprise#2260.)

## Private-agent probe tokens
- Named, org-level, rotatable `o2syn_` probe tokens — **create / list /
rotate / disable**. Rotate = create-new + keep-old for zero-downtime
overlap; disable = revoke. Fixes the gap where a private-agent token was
an unrevocable standing credential.
- IAM **Synthetics Tokens** page (create / rotate / disable) with an
**Agents** column — how many agents currently use each token, so a token
is only revoked once it's safe.
- `POST /synthetics/agent-tokens` to mint a named token; agent
`token_id` tracking; per-agent **Restart config** action.

## Browser checks on private locations
- Allow browser checks on private, **browser-capable** locations
(previously public/Lambda only).
- Agent-setup drawer emits `--type=browser` so the install command pulls
the browser probe image.

## Private locations as agent pools
- A private location is treated as a **pool of interchangeable agents**
— list shows live/total agent count + C/min (deliberate naming instead
of auto-generated `private-location-XXXX`).

## Lease correctness (P0)
- **Atomic job lease** — no duplicate runs when a location has multiple
agents (guarded `status = 0` claim + winner-scoped return).
- **Capability-filter the lease by agent type** — a net agent and a
browser agent can now share one pool; the net agent no longer wins (and
fails with `unsupported check type: browser`) a browser job.

## Scheduling & RBAC
- Expose `next_run_at` on DueMonitor for drift-free scheduling.
- CREATE-folder query is authoritative (RBAC); require PUT permission to
move checks between folders; pass the folder query param on per-check
API calls.
2026-07-24 17:39:35 +00:00
Omkar Kesarkhane 23675360fe fix: added beta badge to all synthetics page headers (#13456) 2026-07-24 17:17:52 +00:00
Abhay Padamani 49b7c3ce5a fix: metrics page improvements (#13452) 2026-07-24 15:21:57 +00:00
Bhargav 1d99426df9 fix: browser sdk package version upgraded to 0.4.1 (#13455) 2026-07-24 13:47:29 +00:00
Abhay Padamani f13e28a46e fix: dashboard and metrics page label overlap issues (#13450)
<img width="1172" height="482" alt="image"
src="https://github.com/user-attachments/assets/3a49a47a-15c8-4eda-8044-ecca31d6eaf7"
/>


<img width="721" height="128" alt="image"
src="https://github.com/user-attachments/assets/6cdf5b58-c71b-47a5-b92a-ae76f76867d7"
/>


<img width="167" height="225" alt="image"
src="https://github.com/user-attachments/assets/dd0fa886-0e22-45ca-89d0-a8254a67e70d"
/>

<img width="215" height="234" alt="image"
src="https://github.com/user-attachments/assets/19109ee0-0f02-47e3-b16f-e8c28b76bb8d"
/>


<img width="215" height="230" alt="image"
src="https://github.com/user-attachments/assets/ed1777b4-53be-4279-aab3-0ca1910b1050"
/>
2026-07-24 13:18:06 +00:00
Omkar KesarkhaneandClaude Opus 4.8 80592f9404 fix: fixed protocol check breakdown cards (#13443)
## What changed

- **MonitorRuns.vue**: Fixed protocol check breakdown cards showing
"Pass Rate by Device" instead of "Duration by Location (Avg)". Added
`OTooltip` with truncation and `cursor-help` on all breakdown card name
spans. Resolved private location labels in the timeline tooltip. Unified
duration formatting to 2 decimal places. Added back the device breakdown
card for browser checks. Fixed `locationDurationBreakdown` to resolve
location IDs to human-readable labels.
- **syntheticResultsSchema.ts**: Renamed device keys `laptop_large` →
`desktop` and `mobile_small` → `mobile` to match the incoming data
schema.

## Why

Protocol check monitors were showing an irrelevant "Pass Rate by Device"
card (device data doesn't exist for protocol checks) instead of the
correct "Duration by Location" card. Browser names and location names in
breakdown cards were untruncated, causing layout issues with long names.
Private location labels in the timeline tooltip displayed raw KSUIDs
instead of human-readable names. Duration values had inconsistent
decimal precision (some clipped, some raw).

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 10:18:44 +00:00
ktx-kirtan 17884df10f fix(ui): summary stat strips & Calm Signal polish (Alerts, Incidents, AI evals) (#13444)
Applies the **Calm Signal** colour language and summary stat strips
across the monitoring + AI-evaluation pages.

- Colourful summary stat strips (`OStatStrip`) with selectable filter
tiles + left row rails / exception washes on **Alerts, Incidents, Eval
Jobs, Scorers, Score Configs**.
- Tile tones match their `OTag` chip colours; critical-first (left)
ordering; re-click a tile to clear the filter.
- AI Observability: consistent section headers, detail drawer, and
per-session signals.
- Migrate `ScorerTypeDialog` to the standard `ODialog`; token-compliance
+ vertical separators on the eval form pages.
- Table perf: lazy tooltips, delegated row shortcuts, virtualization.
2026-07-24 09:13:08 +00:00
Abhay PadamaniandClaude Opus 4.8 5ec9b89ff8 build: FE code format check for improved maintainability (#13351)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 07:11:39 +00:00
Sai Nikhil a8b5f5767d fix: pipeline ui issues (#13438) 2026-07-24 06:33:56 +00:00
ktx-vaidehi d506a9884b fix: dashboard all folder search for favorites (#13437) 2026-07-24 06:05:44 +00:00
Bhargav 6ba66d7f08 fix(logs): full-width row borders, table-owned scroll, histogram top … (#13435)
The results table sized each virtual row to its own text (w-max), so row
bottom-borders stopped at the end of each line and the shared
histogram+table
scroll container gained a horizontal scroll that dragged the histogram
off,
leaving a blank strip.

- Size the table to its widest rendered row (measured, rAF-throttled) so
every
  row spans the full scrollable width and borders run edge to edge; the
  unwrapped source cell keeps its full text (no ellipsis) and scrolls.
- Pin the histogram and give the logs table its own scroll box (drop the
delegated scroll-el); both scrollbars now belong to the table, so
horizontal
  scroll can't move the chart. Patterns view keeps the combined scroll.
- Remove the window-derived width prop and the dead tableRowSize
measuring loop.
- Bump histogram grid.top 5 -> 8 so the top y-axis label isn't clipped.
2026-07-24 05:52:00 +00:00
Shrinath RaoandClaude Opus 4.8 c122fbf9dc fix(logs): stop lazy-editor's transient empty emission wiping restored share-link query (#13426)
## The bug
Opening a **shared link** to an SQL search intermittently lands on an
**empty query editor** ("SQL query is missing or invalid"). Recurring
Logs-Features alpha flake: `monaco-query-prefill` P0 / `shareLink` P1 →
*"query editor never contained SELECT."*

Follow-up to #13414 — that PR guarded a plausible path (the
`fullSQLMode` watcher's "switch ON"), but the trace after it deployed
showed the query **still** dropped. This finds and fixes the actual
cause.

## Root cause (trace-confirmed)
The Monaco query editor is **lazy-loaded**. After the short-URL restore
sets the SQL query, the editor fires its change callback with an empty
`""` **while it mounts — before the restored value is applied.**
`SearchBar.updateQueryValue()` treated that transient empty as a real
edit:

```js
searchObj.data.editorValue = value;   // "" overwrites the restored query
searchObj.data.query = value;
if (value.trim() === "" && searchObj.meta.sqlMode === true) {
  searchObj.meta.sqlMode = false;     // → SQL mode auto-detects OFF → editor cleared for good
}
```

Under load the editor's empty emission lands *after* the restore, so the
query is lost. The trace shows the URL ending `sql_mode=false` with the
`query` param gone — exactly this.

## The fix — state-based, not a timer
The editor emits `""` *because it isn't ready yet*. So we gate on
**readiness (state)**, not a wall-clock wait (a fixed delay would just
change the odds, like "make the env faster"):

- `restoreUrlQueryParams()` sets `meta.pendingUrlQueryRestore = true`
when it restores a non-empty query.
- `updateQueryValue()` **ignores an empty emission while that flag is
set**, and clears the flag the instant the real (non-empty) value lands
— so genuine user clears *after* load still work. This mirrors the
existing `loadingStream` guard already in that function.

Because it keys off state, the race can't beat it: no matter *when* the
empty emission arrives, it's ignored until the real value is in.

## Verification
- ✅ **New real unit test** on `restoreUrlQueryParams`
(`useLogs.spec.ts`, actual composable) — asserts the base64 query
decodes into state, SQL mode restores, and `pendingUrlQueryRestore` is
set. **7 passed.**
- ✅ The guard is deterministic by construction (reads the same shared
`searchObj.meta`).
- ⚠️ The load-race is only observable against a **deployed** frontend,
so the final "flake gone on alpha under load" confirmation is a re-run
once this is deployed to alpha. (I was wrong once here — so I'm being
explicit that this last step is pending, not assumed.)

## Note
#13414's guard is left in place — it's a valid defensive symmetry fix,
just not the operative cause. This PR is the operative fix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 04:26:46 +00:00
73452af92b chore: update translations from en-US.json (#13425)
Auto-generated translation updates from the English source file
(`web/src/locales/languages/en-US.json`).

🤖 Generated with automated translation workflow

Co-authored-by: github-merge-queue[bot] <118344674+github-merge-queue[bot]@users.noreply.github.com>
Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
2026-07-24 03:21:33 +00:00
dependabot[bot] 455b021106 chore(deps): bump qs, cypress and express in /web (#13433)
Bumps [qs](https://github.com/ljharb/qs) to 6.15.3 and updates ancestor
dependencies [qs](https://github.com/ljharb/qs),
[cypress](https://github.com/cypress-io/cypress) and
[express](https://github.com/expressjs/express). These dependencies need
to be updated together.

Updates `qs` from 6.14.2 to 6.15.3
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ljharb/qs/blob/main/CHANGELOG.md">qs's
changelog</a>.</em></p>
<blockquote>
<h2><strong>6.15.3</strong></h2>
<ul>
<li>[Fix] <code>parse</code>: enforce <code>throwOnLimitExceeded</code>
for cumulative array growth via
<code>combine</code>/<code>merge</code></li>
<li>[Fix] <code>utils</code>: respect encoding of surrogate pairs across
chunks (<a
href="https://redirect.github.com/ljharb/qs/issues/559">#559</a>)</li>
<li>[Robustness] <code>parse</code>: throw the <code>arrayLimit</code>
error before splitting oversized comma values</li>
<li>[Robustness] <code>utils.merge</code> / <code>utils.assign</code>:
avoid invoking <code>__proto__</code> setter when copying own
properties</li>
<li>[Robustness] <code>utils</code>: enforce <code>arrayLimit</code>
consistently across <code>merge</code>'s array paths</li>
<li>[Perf] <code>utils</code>: make <code>compact</code> O(n) via a
side-channel visited-set instead of <code>Array.indexOf</code></li>
<li>[Deps] update <code>side-channel</code></li>
<li>[Dev Deps] update <code>eslint</code>, <code>mock-property</code>,
<code>tape</code></li>
<li>[Tests] <code>parse</code>: characterize current lenient handling of
unbalanced bracket keys (<a
href="https://redirect.github.com/ljharb/qs/issues/558">#558</a>)</li>
</ul>
<h2><strong>6.15.2</strong></h2>
<ul>
<li>[Fix] <code>stringify</code>: skip null/undefined entries in
<code>arrayFormat: 'comma'</code> + <code>encodeValuesOnly</code>
instead of crashing in <code>encoder</code></li>
<li>[Fix] <code>stringify</code>: use configured <code>delimiter</code>
after <code>charsetSentinel</code> (<a
href="https://redirect.github.com/ljharb/qs/issues/555">#555</a>)</li>
<li>[Fix] <code>stringify</code>: apply <code>formatter</code> to
encoded key under <code>strictNullHandling</code> (<a
href="https://redirect.github.com/ljharb/qs/issues/554">#554</a>)</li>
<li>[Fix] <code>stringify</code>: skip null/undefined filter-array
entries instead of crashing in <code>encoder</code> (<a
href="https://redirect.github.com/ljharb/qs/issues/551">#551</a>)</li>
<li>[Fix] <code>parse</code>: handle nested bracket groups and add
regression tests (<a
href="https://redirect.github.com/ljharb/qs/issues/530">#530</a>)</li>
<li>[readme] fix grammar (<a
href="https://redirect.github.com/ljharb/qs/issues/550">#550</a>)</li>
<li>[Dev Deps] update <code>@ljharb/eslint-config</code></li>
<li>[Tests] add regression tests for keys containing percent-encoded
bracket text</li>
</ul>
<h2><strong>6.15.1</strong></h2>
<ul>
<li>[Fix] <code>parse</code>: <code>parameterLimit: Infinity</code> with
<code>throwOnLimitExceeded: true</code> silently drops all
parameters</li>
<li>[Deps] update <code>@ljharb/eslint-config</code></li>
<li>[Dev Deps] update <code>@ljharb/eslint-config</code>,
<code>iconv-lite</code></li>
<li>[Tests] increase coverage</li>
</ul>
<h2><strong>6.15.0</strong></h2>
<ul>
<li>[New] <code>parse</code>: add <code>strictMerge</code> option to
wrap object/primitive conflicts in an array (<a
href="https://redirect.github.com/ljharb/qs/issues/425">#425</a>, <a
href="https://redirect.github.com/ljharb/qs/issues/122">#122</a>)</li>
<li>[Fix] <code>duplicates</code> option should not apply to bracket
notation keys (<a
href="https://redirect.github.com/ljharb/qs/issues/514">#514</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ljharb/qs/commit/18d085e919dae70c8f1b200ab99323058edab2c2"><code>18d085e</code></a>
v6.15.3</li>
<li><a
href="https://github.com/ljharb/qs/commit/c38af42039d8cbf83f3e0d486c924eaa5a5d1712"><code>c38af42</code></a>
[Deps] update <code>side-channel</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/adce539489fcd34cc10830cf8c4a43e90b9300b0"><code>adce539</code></a>
[Dev Deps] update <code>eslint</code>, <code>mock-property</code>,
<code>tape</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/74a0f6a83af59245b4fa78785fbe709438580c97"><code>74a0f6a</code></a>
[Robustness] <code>utils</code>: enforce <code>arrayLimit</code>
consistently across <code>merge</code>'s arra...</li>
<li><a
href="https://github.com/ljharb/qs/commit/f4938f594a0a2773d3c99c0c6f5c96f30d909a2c"><code>f4938f5</code></a>
[Tests] <code>parse</code>: characterize current lenient handling of
unbalanced bracket ...</li>
<li><a
href="https://github.com/ljharb/qs/commit/5d5f723afe55a861c52cff6327f62269df35fdd1"><code>5d5f723</code></a>
[Perf] <code>utils</code>: make <code>compact</code> O(n) via a
side-channel visited-set instead of...</li>
<li><a
href="https://github.com/ljharb/qs/commit/52afe00abdb36416ee01c8d5243919b47a59af67"><code>52afe00</code></a>
[Robustness] <code>parse</code>: throw the <code>arrayLimit</code> error
before splitting oversized...</li>
<li><a
href="https://github.com/ljharb/qs/commit/963e538c740961a35ecaa0b38ee1f5c16697e208"><code>963e538</code></a>
[Fix] <code>parse</code>: enforce <code>throwOnLimitExceeded</code> for
cumulative array growth via...</li>
<li><a
href="https://github.com/ljharb/qs/commit/59da434d5de8c3d2564e4d75aeedde2e8af72369"><code>59da434</code></a>
[Fix] <code>utils</code>: respect encoding of surrogate pairs across
chunks</li>
<li><a
href="https://github.com/ljharb/qs/commit/9532969635a4bc96506370b28dd28dcab446e7ee"><code>9532969</code></a>
[Robustness] <code>utils.merge</code> / <code>utils.assign</code>: avoid
invoking <code>__proto__</code> sette...</li>
<li>Additional commits viewable in <a
href="https://github.com/ljharb/qs/compare/v6.14.2...v6.15.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `cypress` from 15.8.2 to 15.19.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cypress-io/cypress/releases">cypress's
releases</a>.</em></p>
<blockquote>
<h2>v15.19.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-19-0">https://docs.cypress.io/app/references/changelog#15-19-0</a></p>
<h2>v15.18.1</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-18-1">https://docs.cypress.io/app/references/changelog#15-18-1</a></p>
<h2>v15.18.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-18-0">https://docs.cypress.io/app/references/changelog#15-18-0</a></p>
<h2>v15.17.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-17-0">https://docs.cypress.io/app/references/changelog#15-17-0</a></p>
<h2>v15.16.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-16-0">https://docs.cypress.io/app/references/changelog#15-16-0</a></p>
<h2>v15.15.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-15-0">https://docs.cypress.io/app/references/changelog#15-15-0</a></p>
<h2>v15.14.2</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-14-2">https://docs.cypress.io/app/references/changelog#15-14-2</a></p>
<h2>v15.14.1</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-14-1">https://docs.cypress.io/app/references/changelog#15-14-1</a></p>
<h2>v15.14.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-14-0">https://docs.cypress.io/app/references/changelog#15-14-0</a></p>
<h2>v15.13.1</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-13-1">https://docs.cypress.io/app/references/changelog#15-13-1</a></p>
<h2>v15.13.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-13-0">https://docs.cypress.io/app/references/changelog#15-13-0</a></p>
<h2>v15.12.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-12-0">https://docs.cypress.io/app/references/changelog#15-12-0</a></p>
<h2>v15.11.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-11-0">https://docs.cypress.io/app/references/changelog#15-11-0</a></p>
<h2>v15.10.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-10-0">https://docs.cypress.io/app/references/changelog#15-10-0</a></p>
<h2>v15.9.0</h2>
<p>Changelog: <a
href="https://docs.cypress.io/app/references/changelog#15-9-0">https://docs.cypress.io/app/references/changelog#15-9-0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/cypress-io/cypress/commit/d19a47c2421485e2352b89e3167a0a3237c2d21c"><code>d19a47c</code></a>
test: migrate dev-server e2e specs to the reporter iframe (<a
href="https://redirect.github.com/cypress-io/cypress/issues/34301">#34301</a>)</li>
<li><a
href="https://github.com/cypress-io/cypress/commit/dd72f31efdf30291f0aa7387ad290afecbdbebde"><code>dd72f31</code></a>
chore: Update Chrome (stable) to 150.0.7871.128 (<a
href="https://redirect.github.com/cypress-io/cypress/issues/34293">#34293</a>)</li>
<li><a
href="https://github.com/cypress-io/cypress/commit/388f6e09f568571f11ee221c6a52254dec600752"><code>388f6e0</code></a>
chore: retrieve SSL.com CodeSignTool for Windows signing from github CDN
(<a
href="https://redirect.github.com/cypress-io/cypress/issues/34">#34</a>...</li>
<li><a
href="https://github.com/cypress-io/cypress/commit/3ff59601d1f07fffba90881b9514ed48d8f12e75"><code>3ff5960</code></a>
perf: render command log in an isolated iframe to prevent renderer crash
(<a
href="https://redirect.github.com/cypress-io/cypress/issues/34">#34</a>...</li>
<li><a
href="https://github.com/cypress-io/cypress/commit/37a899cab005044b6b98576de87de2b6c810e31f"><code>37a899c</code></a>
fix: allow chaining assertions after should('exist') on raw DOM elements
(<a
href="https://redirect.github.com/cypress-io/cypress/issues/34">#34</a>...</li>
<li><a
href="https://github.com/cypress-io/cypress/commit/bfe83a15d38a06b715b40cbb1b53b2443ff02f3a"><code>bfe83a1</code></a>
chore: clean up the server cookie automation converters and various
automatio...</li>
<li><a
href="https://github.com/cypress-io/cypress/commit/72cef528bff59f94843afcd4482ce1d5d260c302"><code>72cef52</code></a>
chore: Update Chrome (stable) to 150.0.7871.124 and Chrome (beta) to
151.0.79...</li>
<li><a
href="https://github.com/cypress-io/cypress/commit/6792160d0eda19fe04dd9c9a93da42c8fcf6af1e"><code>6792160</code></a>
chore: bump websocket-driver to 0.7.5 to resolve critical Snyk
vulnerability ...</li>
<li><a
href="https://github.com/cypress-io/cypress/commit/de06a0731b305b4bbd82d20cceb994fdc51e3acc"><code>de06a07</code></a>
test: fix cy-in-cy studio AI test to exercise authenticated flow (<a
href="https://redirect.github.com/cypress-io/cypress/issues/34278">#34278</a>)</li>
<li><a
href="https://github.com/cypress-io/cypress/commit/9e7e850e1693e1c2a4d2d66dbb92149eaef62244"><code>9e7e850</code></a>
feat: upgrade chai to 4.5.0 and expose new assertion aliases (<a
href="https://redirect.github.com/cypress-io/cypress/issues/34178">#34178</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/cypress-io/cypress/compare/v15.8.2...v15.19.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `express` from 4.22.1 to 4.22.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/expressjs/express/releases">express's
releases</a>.</em></p>
<blockquote>
<h2>v4.22.2</h2>
<h2>What's Changed</h2>
<ul>
<li>fix: restore &gt;20 array parsing for <code>req.query</code>
repeated keys (<a
href="https://github.com/expressjs/express/commit/8d09bfe6d88983da5c3e12cfdd54782c4dc675db"><code>8d09bfe6</code></a>)
<ul>
<li>This also unifies array-cap behavior across notations. Indexed
notation (<code>a[0]=...</code>) was historically capped at qs's default
<code>arrayLimit</code> of 20 even in older qs versions; after this
change it also allows up to 1000 items.</li>
</ul>
</li>
<li>deps: qs@~6.15.1</li>
<li>deps: body-parser@~1.20.5</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/suuuuuuminnnnnn"><code>@​suuuuuuminnnnnn</code></a>
made their first contribution in <a
href="https://redirect.github.com/expressjs/express/pull/7021">expressjs/express#7021</a></li>
<li><a href="https://github.com/SAY-5"><code>@​SAY-5</code></a> made
their first contribution in <a
href="https://redirect.github.com/expressjs/express/pull/7181">expressjs/express#7181</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/expressjs/express/compare/v4.22.1...v4.22.2">https://github.com/expressjs/express/compare/v4.22.1...v4.22.2</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/expressjs/express/blob/v4.22.2/History.md">express's
changelog</a>.</em></p>
<blockquote>
<h1>4.22.2 / 2026-05-011</h1>
<ul>
<li>fix: restore &gt;20 array parsing for <code>req.query</code>
repeated keys (<a
href="https://github.com/expressjs/express/commit/8d09bfe6d88983da5c3e12cfdd54782c4dc675db"><code>8d09bfe6</code></a>)
<ul>
<li>This also unifies array-cap behavior across notations. Indexed
notation (<code>a[0]=...</code>) was historically capped at qs's default
<code>arrayLimit</code> of 20 even in older qs versions; after this
change it also allows up to 1000 items.</li>
</ul>
</li>
<li>deps: qs@~6.15.1</li>
<li>deps: body-parser@~1.20.5</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/expressjs/express/commit/df0abc9333a3398b97b71f6ea7cd77d5ea3e9f97"><code>df0abc9</code></a>
4.22.2</li>
<li><a
href="https://github.com/expressjs/express/commit/836d36668ea750f78b4373b4de79bbd22634e6ec"><code>836d366</code></a>
<code>4.x</code> update qs to 6.15.1, body-parser 1.20.5 (<a
href="https://redirect.github.com/expressjs/express/issues/7224">#7224</a>)</li>
<li><a
href="https://github.com/expressjs/express/commit/8d09bfe6d88983da5c3e12cfdd54782c4dc675db"><code>8d09bfe</code></a>
fix: restore array parsing for req.query repeated keys (<a
href="https://redirect.github.com/expressjs/express/issues/7181">#7181</a>)</li>
<li><a
href="https://github.com/expressjs/express/commit/d39e8ad1778a0b8a606a5a7b17096d0cc5ec722d"><code>d39e8ad</code></a>
deps: body-parser@~1.20.4 (<a
href="https://redirect.github.com/expressjs/express/issues/7021">#7021</a>)</li>
<li><a
href="https://github.com/expressjs/express/commit/efe85d9fdc9e3a62f7a1121b4f5f484862298b48"><code>efe85d9</code></a>
deps: qs@^6.14.1 (<a
href="https://redirect.github.com/expressjs/express/issues/6972">#6972</a>)</li>
<li><a
href="https://github.com/expressjs/express/commit/f62378e1bc776259c0a471476c2dc043a02ac762"><code>f62378e</code></a>
📝 add note to history</li>
<li>See full diff in <a
href="https://github.com/expressjs/express/compare/v4.22.1...v4.22.2">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/openobserve/openobserve/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 03:15:11 +00:00
Omkar KesarkhaneandClaude Opus 4.8 4315dc3be9 fix: synthetic monitoring UI issues (#13427)
### Empty state for checks with no runs
- When `totalRuns === 0`, the entire MonitorRuns content area (tabs,
KPIs, charts, table) is replaced by a hero `OEmptyState`
- Distinguishes "never triggered" (shows "Trigger a run now" action)
from "no runs in this time window" (shows "Jump to latest data" action)
- Default time range is always "Last 15 minutes" — drops stale
query-param anchoring

### Consolidated check fetch
- Moved the check API call to `MonitorResults.fetchCheck()` on mount,
removing the duplicate `resolveMonitorType()` in `MonitorRuns`
- `isBrowser` is now a computed deriving from the `checkType` prop
- Removes `need-check-data` emit/watch pattern — parent always fetches
on mount

### Org routing fix
- `SyntheticMonitoring.vue` and `PrivateLocationDetail.vue` now carry
`org_identifier` when navigating to `synthetic-monitor-results`

### Location label fix
- `MonitorRuns.vue` and `RunDetail.vue` use `loc.label` instead of
`loc.name` (matches `SyntheticLocation` type)

## Changes
- `MonitorRuns.vue` — page-level empty state gate, `checkType` prop,
`isBrowser` computed, removed `resolveMonitorType()`/watch
- `MonitorResults.vue` — `fetchCheck()` on mount, `checkType` ref,
removed `need-check-data` listener
- `SyntheticMonitoring.vue` — carry `org_identifier` in `openDetail`
- `PrivateLocationDetail.vue` — carry `org_identifier` in `openMonitor`
- `RunDetail.vue` — `loc.name` → `loc.label`
- `MonitorResults.spec.ts` — updated props and mock descriptions

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 18:59:00 +00:00
Ashish Kolhe 45b30fa559 feat(traces): default trace detail view to Waterfall (#13424)
## What

On the traces detail page, make **Waterfall** the first tab and the
default landing view (previously Flame Graph).

## Why

Waterfall is the more universally useful default for inspecting a
trace's span timeline; users landing on Flame Graph first had an extra
click to get to it.

## Changes

- `TraceDetails.vue`: reorder `TRACE_TAB_DEFS` so `waterfall` leads
`flame-graph`, and set `DEFAULT_TRACE_TAB` to `"waterfall"`. The
fallback watcher and reorder/persistence logic reference these, so they
follow automatically.
- `TraceDetails.spec.ts`: updated tab-order / default / fallback /
reorder assertions for the new default order.

## Behavior note

Tab order and the active tab are persisted per-browser in `localStorage`
(`o2_trace_tab_order` / `o2_trace_active_tab`). Users who have already
opened a trace keep their saved preference — the new Waterfall default
applies to browsers with no stored preference.

## Testing

`TraceDetails.spec.ts` + `TraceDetails.missing-span-kind.spec.ts` — 199
passed / 3 skipped.
2026-07-23 16:45:10 +00:00
ktx-vaidehi bf39d9de84 fix: keyboard shortcuts for metrics (#13413) 2026-07-23 15:58:52 +00:00
ktx-vaidehiandClaude Opus 4.8 50d3fda602 fix: UI token change (#13315)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 15:58:24 +00:00
Omkar KesarkhaneandClaude Opus 4.8 eb5d86382d fix: display location label instead of id's in synthetic runs (#13415)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 15:37:25 +00:00
Loakesh Indiran 41420d11e7 fix(synthetics): RBAC — folder query param, move gate, create folder authority (#13399)
Three related synthetics RBAC fixes (frontend + backend handlers).
Read-path and write-path folder isolation, all mirroring how alerts
already works.

## Fixes

- **Per-check calls now send `?folder=`** — the UI wasn't passing the
check's folder on per-check API calls
(`get`/`run`/`enable`/`getRuns`/`getRun`/`presignArtifacts`/`artifactUrl`),
so folder-scoped RBAC couldn't resolve. Threaded `route.query.folder`
through the service + all call sites; also fixed `update()` which
computed the folder param but never appended it. Matches
`web/src/services/alerts.ts`.
- **Move requires PUT permission** — the `move_synthetics` handler did
no permission check and didn't even extract the user, so a
List+Delete-only role could move checks between folders. Now runs
`check_permissions(id, org, user, "synthetics", "PUT", …)` per check
before moving → 403 if any fails. Mirrors alerts' `move_to_folder`.
- **Create is folder query-authoritative** — the POST gate checks
`?folder=`, but the handler wrote to `body.folder_id`, so a crafted body
could create a check in a folder the user can't access. The `?folder=`
query is now authoritative (`body.folder_id` ignored for the
destination), exactly like regular alerts' `create_alert`
(`get_folder(query)`).

## Notes

- Backend fixes are OSS-only — `check_permissions` lives in
`openobserve-core`, so gating in the handlers is the correct place; no
enterprise change.
- The anomaly-detection alert create has the same body-vs-query gap as
the synthetics create fix — tracked separately in #13416 (fix later).
- Pairs with the o2-enterprise default-folder registration fix (#2247).
2026-07-23 15:13:08 +00:00
Shrinath RaoandClaude Opus 4.8 1daa36b0f8 fix(logs): preserve restored SQL query on shared-link open + align log-detail default-tab test (13368) (#13414)
> **This PR contains two independent logs changes:**
> **(A)** a product fix for the shared-link SQL-query restore race, and
> **(B)** the log-detail default-tab test alignment (original scope of
this PR).

---

# (A) fix(logs): preserve restored SQL query on shared-link open
(fullSQLMode watcher race)

## The bug
Opening a **shared link** to an SQL search **sometimes lands on an empty
query editor** ("SQL query is missing or invalid") instead of the shared
search. Intermittent, worse under load — it's the recurring
Logs-Features alpha flake (`monaco-query-prefill` P0 "query editor never
contained SELECT").

**Not the short-URL mechanism** — the short URL correctly carries
`sql_mode=true` + the base64 query. The loss happens in the browser
during restore.

## Root cause — a watcher race
`restoreUrlQueryParams()` raises `shouldIgnoreWatcher`, flips
`meta.sqlMode = true`, then writes the decoded query into the editor.
Flipping `sqlMode` fires the **`fullSQLMode`** watcher in `Index.vue`,
whose two branches were **asymmetric**:

- **switch OFF** branch → already checks `shouldIgnoreWatcher` ✅
- **switch ON** branch → **did not** ❌ — it called `setQuery()`,
rebuilding a *default* `SELECT … FROM stream` over the value the restore
was mid-writing.

Under load the watcher wins the race; the editor briefly empties, SQL
mode auto-detects back **off**, and the editor is cleared entirely.

## The fix
Make the "switch ON" branch honour `shouldIgnoreWatcher` too — symmetric
with "switch OFF". During any programmatic restore the watcher **stands
down** and the restored query is the last word. (`shouldIgnoreWatcher`
is raised only by programmatic-state paths whose purpose is to suppress
watcher side-effects, so honouring it here is consistent.)

## Verification (A)
- ✅ **New unit test**: with `shouldIgnoreWatcher` set, flipping
`sqlMode` ON does **not** call `setQuery`/`updateUrlQueryParams`, and
the restored `SELECT` query is preserved.
- ✅ Existing `fullSQLMode` watcher test still passes; full
`Index.spec.ts` green (**69 passed**).
- ✅ Reproduced the failure on **alpha under CI-load** beforehand
(share-link P0 flaky, "query editor never contained SELECT").
- ⚠️ The race is only observable against a **deployed** frontend (the
alpha e2e suite runs against alpha's frontend, not a local build), so
the final "flake gone on alpha under load" check requires this deployed
to alpha, then re-running the Logs-Features share-link tests.

Files: `web/src/plugins/logs/Index.vue`,
`web/src/plugins/logs/Index.spec.ts`.

---

# (B) test(logs): align log-detail default-tab test with Table default
(13368)

## What
Updates the log-detail sidebar default-tab regression test (originally
Bug #9724) to match the **intentionally shipped** behavior from [PR
#13368](https://github.com/openobserve/openobserve/pull/13368) — *"logs
sidebar table will be default view and draggable tabs"*.

## Why
#13368 changed the log-detail sidebar default from the **JSON** tab to
the **Table** tab (`SearchResult.vue` — `detailTableInitialTab.value =
"table"`). The Bug #9724 test still asserted JSON-as-default, so it
fails on `main`: the JSON tab's `data-state` stays `inactive` for the
full timeout across all retries, on both OSS and ENT Logs-Regression.
Not a flake and not a product bug — the test expectation was simply out
of date after a deliberate default-view change.

## Changes
- Rename test → **"Log detail sidebar opens with Table tab by default
(#13368)"**.
- Add `verifyTableTabSelectedByDefault()` page-object helper
(auto-retrying `toHaveAttribute('data-state','active')`); remove the
now-invalid `verifyJsonTabSelectedByDefault()`.
- Reorder switch steps: assert Table default (+ wrap toggle, which
renders only on the Table tab), switch to JSON and back to Table, reopen
and confirm Table default persists.

## Note on #13407
Supersedes the earlier heal
[#13407](https://github.com/openobserve/openobserve/pull/13407), which
misdiagnosed the failure as a `data-state` timing flake. A
locally-hosted stale pre-#13368 build had masked the change.

Files: `tests/ui-testing/pages/logsPages/logsPage.js`,
`tests/ui-testing/playwright-tests/RegressionSet/Logs/logs-regression.spec.js`.

```
npx playwright test playwright-tests/RegressionSet/Logs/logs-regression.spec.js \
  -g "Table tab by default" --project=chromium
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:35:24 +00:00
github-actions[bot]andgithub-merge-queue[bot] a02ab53005 chore: update translations from en-US.json (#13367)
Auto-generated translation updates from the English source file
(`web/src/locales/languages/en-US.json`).

🤖 Generated with automated translation workflow

Co-authored-by: github-merge-queue[bot] <118344674+github-merge-queue[bot]@users.noreply.github.com>
2026-07-23 12:09:34 +00:00
ktx-akshay fb6d93dcfe fix: dashboard-view back button redirects to Favorites instead of the Default folder (#13409) 2026-07-23 11:53:22 +00:00
Sai Nikhil 2cec0a0c94 fix: pipeline and workflows UI change (#13397) 2026-07-23 11:28:13 +00:00
ktx-vaidehiandClaude Opus 4.8 8886a03b99 feat(dashboards): redesign panel config sections (#13371)
- Collapse all config sections by default (was expanded)
- Add open-state accent to OCollapsible sidebar variant: left accent
bar, tinted header, and accent-colored icon/chevron when expanded
- Move sidebar chevron to the right of the label (rotates on open)
- Give every config section a leading icon via SECTION_ICONS
- Add theme-aware collapsible open-state tokens (light + dark)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 11:14:16 +00:00
Ashish Kolhe 57caf3894c fix(agent-graph): correct stream gating, independent selector, and agent→model/tool edge attribution (#13404)
Fixes the Agent Graph end-to-end — UI (openobserve/web) + service-graph
backend (openobserve/core). Root causes were found and validated against
live trace data.

---

## 1. UI: wrong graph until refresh + no independent graph-type selector

The Agent Graph page embeds Traces' `ServiceGraph`, which read its
viz/layout type from the shared `searchObj.meta` singleton and
auto-loads on mount.

- **Wrong graph on return (from Agent Behavior):** the effective stream
fell back to the literal `default` trace stream before `loadAgents()`
resolved, so ServiceGraph rendered that whole stream's service topology
instead of the agent graph. Fixed: no `default` fallback in agent mode;
render is gated behind `graphReady` (a resolved agent stream), with a
spinner / "no agents" empty state otherwise; stale agent/stream
selections reconciled on reload.
- **No graph-type selector / inherited the Traces tab's type:** added
`vizType`/`layoutType` prop overrides on `ServiceGraph` (computeds
prefer props, else the shared store — Traces behavior unchanged), and
gave the Agent Graph page its own Tree/Graph + layout selector with its
own state and `agentGraph_*` localStorage keys.
- **Stream picker** now lists only the distinct `source_stream`s of
discovered agents (not agentless streams), annotated with per-stream
agent counts, with an option tooltip and wider control.

New `AgentGraphPage.spec.ts` (5 tests): gating, empty state, viz/layout
independence, stream-picker scoping. `vue-tsc` app + vitest typecheck
clean.

## 2. Backend: agent→model/tool edges mis-attributed to the service

Model/tool spans (`chat`, `execute_tool`) don't carry
`gen_ai.agent.name` — it lives on an ancestor `invoke_agent` span
(confirmed as the norm across the OTel GenAI spec, Google ADK, OpenAI
Agents SDK, OpenInference, CrewAI, LangGraph). The edge builder climbs
≤4 parent hops to find it, else falls back to `service_name`. When an
intermediate span is missing (the spec permits omitting `invoke_agent`;
inconsistent sampling / async context loss produce orphan LLM spans),
the climb fails and the span mis-attributes to the service — a spurious
`service → model` / `service → tool` edge.

Fix: add a per-trace agent CTE (`MAX(gen_ai_agent_name) GROUP BY
trace_id`) as a fallback level in the COALESCE, between the ancestor
climb and the `service_name` fallback, for both edge queries. This
matches the industry-recommended fallback (group by trace when the chain
breaks).

### Validation (live introspect data, 2 streams, 7-day window)

| stream | before | after |
|---|---|---|
| `sre_agent_traces_production` | `service → model` (47+3 reqs) |
eliminated → o2_ai_agent (247) / sre_rca_agent (29) |
| `sre_agent_traces_production_us2` | `service → model` (20 reqs) |
eliminated → o2_ai_agent (279) |

- No cross-agent contamination in the multi-agent stream (traces are
single-agent). No tool-edge regression.
- Non-agent traces: CTE returns nothing → NULL join → falls to
`service_name` exactly as before (no behavior change).
- Perf: single-column `GROUP BY trace_id` aggregate, ~+25% wallclock on
the batch edge query; runs in the hourly job, not a hot path.

Unit tests cover the COALESCE position and CTE builder.

## Not included / follow-up
- **env/version in the agent dropdown** requires backend extractor + DB
migration + API changes. Tracked separately.

## Note
Full enterprise `cargo build` isn't runnable in the dev environment (the
`o2_enterprise` crate is a resolution stub); the SQL-builder logic is
verified via standalone rustc and the runtime behavior via the live
dry-run above. CI runs the real enterprise build.
2026-07-23 10:56:29 +00:00
Abhay Padamani a237306208 feat: copy paste support for date time picker (#13374)
Design At: ui/datetime-picker-copy-paste.md

<img width="399" height="561" alt="image"
src="https://github.com/user-attachments/assets/d4c11056-ffe2-451f-8d1b-ddbcf7c59336"
/>
2026-07-23 10:38:35 +00:00
Omkar KesarkhaneandClaude Opus 4.8 100a82ab00 fix: added warning start filter in synthetics (#13395)
## What changed

- **Warning status consistency**: The backend returns 4 run statuses
(`passed`, `warning`, `failed`, `error`) but the frontend only handled
`passed`/`failed` consistently. Across `MonitorRuns.vue`,
`SyntheticMonitoring.vue`, `syntheticResultsSchema.ts`, and
`useSyntheticResults.ts`, all 4 statuses are now properly mapped to
their own badge variants, filter options, KPI cards, timeline segments,
and breakdowns.
- **Cooldown period label**: Removed the `*` required indicator from the
cooldown period label in `CheckAlerts.vue` since the field is optional.

## Why

The TLS certificate-expiring-soon check returns `warning` status, which
appeared inconsistently: green "passed" in some views, red "failed" in
others, or entirely missing from filter dropdowns. The fixes ensure SREs
can distinguish "slightly flaky check" from "service is crashing" at a
glance.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 10:02:52 +00:00
Sai Nikhil e8dfffcb5e fix: scorer issues on ai eval (#13400) 2026-07-23 08:31:25 +00:00