mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 16:09:05 +00:00
6ca0eec1075053d4e97b35dfbf8ededcdcd1791a
3155
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f112ac01a5 |
fix: dashboard layout improvements (#13815)
<h2 style="unicode-bidi: plaintext; color: rgb(204, 204, 204);
font-family: -apple-system, "system-ui", "Segoe UI",
Roboto, sans-serif; font-style: normal; font-variant-ligatures: normal;
font-variant-caps: normal; letter-spacing: normal; orphans: 2;
text-align: start; text-indent: 0px; text-transform: none; widows: 2;
word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal;
background-color: rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color:
initial;">Dashboard layout & UX improvements</h2><p
style="white-space: pre-wrap; margin-top: 0.1em; margin-bottom: 0.2em;
unicode-bidi: plaintext; color: rgb(204, 204, 204); font-family:
-apple-system, "system-ui", "Segoe UI", Roboto,
sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures:
normal; font-variant-caps: normal; font-weight: 400; letter-spacing:
normal; orphans: 2; text-align: start; text-indent: 0px; text-transform:
none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;
background-color: rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color: initial;">Polish
pass on the dashboard experience: settings layout, drag/resize grid
feedback, empty states, and per-tab panel counts.</p><h3
style="unicode-bidi: plaintext; color: rgb(204, 204, 204); font-family:
-apple-system, "system-ui", "Segoe UI", Roboto,
sans-serif; font-style: normal; font-variant-ligatures: normal;
font-variant-caps: normal; letter-spacing: normal; orphans: 2;
text-align: start; text-indent: 0px; text-transform: none; widows: 2;
word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal;
background-color: rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color: initial;">✨
Highlights</h3><p style="white-space: pre-wrap; margin-top: 0.1em;
margin-bottom: 0.2em; unicode-bidi: plaintext; color: rgb(204, 204,
204); font-family: -apple-system, "system-ui", "Segoe
UI", Roboto, sans-serif; font-size: 13px; font-style: normal;
font-variant-ligatures: normal; font-variant-caps: normal; font-weight:
400; letter-spacing: normal; orphans: 2; text-align: start; text-indent:
0px; text-transform: none; widows: 2; word-spacing: 0px;
-webkit-text-stroke-width: 0px; background-color: rgb(24, 24, 24);
text-decoration-thickness: initial; text-decoration-style: initial;
text-decoration-color: initial;"><strong>Grid feedback while
dragging/resizing panels</strong> (<a
href="vscode-webview://0vkpvjgb486eanj04qjfqcnqmnatevjacbbbqdp3ecrs4efo5krm/web/src/views/Dashboards/RenderDashboardCharts.vue"
target="_blank" rel="noopener noreferrer" style="color: rgb(77, 170,
252); text-decoration: rgb(77, 170,
252);">RenderDashboardCharts.vue</a>)</p><ul
style="padding-inline-start: 2em; color: rgb(204, 204, 204);
font-family: -apple-system, "system-ui", "Segoe UI",
Roboto, sans-serif; font-size: 13px; font-style: normal;
font-variant-ligatures: normal; font-variant-caps: normal; font-weight:
400; letter-spacing: normal; orphans: 2; text-align: start; text-indent:
0px; text-transform: none; widows: 2; word-spacing: 0px;
-webkit-text-stroke-width: 0px; white-space: normal; background-color:
rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color: initial;"><li
style="unicode-bidi: plaintext;">Added a live alignment grid that
appears only during a drag or resize, drawn from GridStack's real cell
metrics (192 columns × row height).</li><li style="unicode-bidi:
plaintext;">The grid is<span> </span><strong>operation-aware</strong>:
lines snap to the top/left edges
while<span> </span><em>moving</em><span> </span>and the bottom/right
edges while<span> </span><em>resizing</em>, so the edge you're dragging
always lands on a line and every line is reachable (no skipped
positions).</li><li style="unicode-bidi: plaintext;">Panels are made
opaque during interaction (<code style="font-family: monospace; color:
rgb(208, 208, 208); background-color: rgb(60, 60, 60); padding: 2px 4px;
border-radius: 3px; word-break: break-word; font-size:
0.9em;">--color-surface-base</code>) so the grid only shows in the
gutters/empty cells, not through chart or table panels.</li></ul><p
style="white-space: pre-wrap; margin-top: 0.1em; margin-bottom: 0.2em;
unicode-bidi: plaintext; color: rgb(204, 204, 204); font-family:
-apple-system, "system-ui", "Segoe UI", Roboto,
sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures:
normal; font-variant-caps: normal; font-weight: 400; letter-spacing:
normal; orphans: 2; text-align: start; text-indent: 0px; text-transform:
none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;
background-color: rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color:
initial;"><strong>Empty states</strong> (<a
href="vscode-webview://0vkpvjgb486eanj04qjfqcnqmnatevjacbbbqdp3ecrs4efo5krm/web/src/lib/core/EmptyState/presets.ts"
target="_blank" rel="noopener noreferrer" style="color: rgb(77, 170,
252); text-decoration: rgb(77, 170, 252);">presets.ts</a>, <a
href="vscode-webview://0vkpvjgb486eanj04qjfqcnqmnatevjacbbbqdp3ecrs4efo5krm/web/src/components/dashboards/settings/VariableSettings.vue"
target="_blank" rel="noopener noreferrer" style="color: rgb(77, 170,
252); text-decoration: rgb(77, 170, 252);">VariableSettings.vue</a>, <a
href="vscode-webview://0vkpvjgb486eanj04qjfqcnqmnatevjacbbbqdp3ecrs4efo5krm/web/src/views/Dashboards/ScheduledDashboards.vue"
target="_blank" rel="noopener noreferrer" style="color: rgb(77, 170,
252); text-decoration: rgb(77, 170,
252);">ScheduledDashboards.vue</a>)</p><ul style="padding-inline-start:
2em; color: rgb(204, 204, 204); font-family: -apple-system,
"system-ui", "Segoe UI", Roboto, sans-serif;
font-size: 13px; font-style: normal; font-variant-ligatures: normal;
font-variant-caps: normal; font-weight: 400; letter-spacing: normal;
orphans: 2; text-align: start; text-indent: 0px; text-transform: none;
widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;
white-space: normal; background-color: rgb(24, 24, 24);
text-decoration-thickness: initial; text-decoration-style: initial;
text-decoration-color: initial;"><li style="unicode-bidi:
plaintext;">Replaced the generic<span> </span><code style="font-family:
monospace; color: rgb(208, 208, 208); background-color: rgb(60, 60, 60);
padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size:
0.9em;">NoData</code><span> </span>placeholder with<span> </span><code
style="font-family: monospace; color: rgb(208, 208, 208);
background-color: rgb(60, 60, 60); padding: 2px 4px; border-radius: 3px;
word-break: break-word; font-size:
0.9em;">OEmptyState</code><span> </span>for the Variables settings table
and the Scheduled Dashboards list.</li><li style="unicode-bidi:
plaintext;">Added a new<span> </span><code style="font-family:
monospace; color: rgb(208, 208, 208); background-color: rgb(60, 60, 60);
padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size:
0.9em;">no-variables</code><span> </span>preset (illustration + copy +
"Add variable" action); reused the existing<span> </span><code
style="font-family: monospace; color: rgb(208, 208, 208);
background-color: rgb(60, 60, 60); padding: 2px 4px; border-radius: 3px;
word-break: break-word; font-size:
0.9em;">no-reports</code><span> </span>preset for scheduled
dashboards.</li><li style="unicode-bidi: plaintext;">Fixed the Variables
table so a long
list<span> </span><strong>scrolls</strong><span> </span>instead of
clipping, and made the Scheduled Dashboards table fill the drawer height
so the empty state centers.</li></ul><p style="white-space: pre-wrap;
margin-top: 0.1em; margin-bottom: 0.2em; unicode-bidi: plaintext; color:
rgb(204, 204, 204); font-family: -apple-system, "system-ui",
"Segoe UI", Roboto, sans-serif; font-size: 13px; font-style:
normal; font-variant-ligatures: normal; font-variant-caps: normal;
font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start;
text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px;
-webkit-text-stroke-width: 0px; background-color: rgb(24, 24, 24);
text-decoration-thickness: initial; text-decoration-style: initial;
text-decoration-color: initial;"><strong>Dashboard settings
layout</strong> (<a
href="vscode-webview://0vkpvjgb486eanj04qjfqcnqmnatevjacbbbqdp3ecrs4efo5krm/web/src/components/dashboards/settings/GeneralSettings.vue"
target="_blank" rel="noopener noreferrer" style="color: rgb(77, 170,
252); text-decoration: rgb(77, 170,
252);">GeneralSettings.vue</a>)</p><ul style="padding-inline-start: 2em;
color: rgb(204, 204, 204); font-family: -apple-system,
"system-ui", "Segoe UI", Roboto, sans-serif;
font-size: 13px; font-style: normal; font-variant-ligatures: normal;
font-variant-caps: normal; font-weight: 400; letter-spacing: normal;
orphans: 2; text-align: start; text-indent: 0px; text-transform: none;
widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;
white-space: normal; background-color: rgb(24, 24, 24);
text-decoration-thickness: initial; text-decoration-style: initial;
text-decoration-color: initial;"><li style="unicode-bidi:
plaintext;">Reworked the General settings layout.</li></ul><p
style="white-space: pre-wrap; margin-top: 0.1em; margin-bottom: 0.2em;
unicode-bidi: plaintext; color: rgb(204, 204, 204); font-family:
-apple-system, "system-ui", "Segoe UI", Roboto,
sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures:
normal; font-variant-caps: normal; font-weight: 400; letter-spacing:
normal; orphans: 2; text-align: start; text-indent: 0px; text-transform:
none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;
background-color: rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color:
initial;"><strong>Tab panel-count badge</strong> (<a
href="vscode-webview://0vkpvjgb486eanj04qjfqcnqmnatevjacbbbqdp3ecrs4efo5krm/web/src/components/dashboards/tabs/TabList.vue"
target="_blank" rel="noopener noreferrer" style="color: rgb(77, 170,
252); text-decoration: rgb(77, 170, 252);">TabList.vue</a>)</p><ul
style="padding-inline-start: 2em; color: rgb(204, 204, 204);
font-family: -apple-system, "system-ui", "Segoe UI",
Roboto, sans-serif; font-size: 13px; font-style: normal;
font-variant-ligatures: normal; font-variant-caps: normal; font-weight:
400; letter-spacing: normal; orphans: 2; text-align: start; text-indent:
0px; text-transform: none; widows: 2; word-spacing: 0px;
-webkit-text-stroke-width: 0px; white-space: normal; background-color:
rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color: initial;"><li
style="unicode-bidi: plaintext;">Each dashboard tab now shows a badge
with its panel count (section headers excluded), so tab density is
visible without opening each tab.</li></ul><p style="white-space:
pre-wrap; margin-top: 0.1em; margin-bottom: 0.2em; unicode-bidi:
plaintext; color: rgb(204, 204, 204); font-family: -apple-system,
"system-ui", "Segoe UI", Roboto, sans-serif;
font-size: 13px; font-style: normal; font-variant-ligatures: normal;
font-variant-caps: normal; font-weight: 400; letter-spacing: normal;
orphans: 2; text-align: start; text-indent: 0px; text-transform: none;
widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;
background-color: rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color:
initial;"><strong>Variable dependency indicator</strong> (<a
href="vscode-webview://0vkpvjgb486eanj04qjfqcnqmnatevjacbbbqdp3ecrs4efo5krm/web/src/components/dashboards/settings/VariableSettings.vue"
target="_blank" rel="noopener noreferrer" style="color: rgb(77, 170,
252); text-decoration: rgb(77, 170,
252);">VariableSettings.vue</a>)</p><ul style="padding-inline-start:
2em; color: rgb(204, 204, 204); font-family: -apple-system,
"system-ui", "Segoe UI", Roboto, sans-serif;
font-size: 13px; font-style: normal; font-variant-ligatures: normal;
font-variant-caps: normal; font-weight: 400; letter-spacing: normal;
orphans: 2; text-align: start; text-indent: 0px; text-transform: none;
widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;
white-space: normal; background-color: rgb(24, 24, 24);
text-decoration-thickness: initial; text-decoration-style: initial;
text-decoration-color: initial;"><li style="unicode-bidi:
plaintext;">Variables that depend on others show a "Depends on: …" chip
(tree icon + count) in the settings table.</li></ul><p
style="white-space: pre-wrap; margin-top: 0.1em; margin-bottom: 0.2em;
unicode-bidi: plaintext; color: rgb(204, 204, 204); font-family:
-apple-system, "system-ui", "Segoe UI", Roboto,
sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures:
normal; font-variant-caps: normal; font-weight: 400; letter-spacing:
normal; orphans: 2; text-align: start; text-indent: 0px; text-transform:
none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;
background-color: rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color:
initial;"><strong>Panel header token</strong> (<a
href="vscode-webview://0vkpvjgb486eanj04qjfqcnqmnatevjacbbbqdp3ecrs4efo5krm/web/src/lib/styles/tokens/component.css"
target="_blank" rel="noopener noreferrer" style="color: rgb(77, 170,
252); text-decoration: rgb(77, 170, 252);">component.css</a>)</p><ul
style="padding-inline-start: 2em; color: rgb(204, 204, 204);
font-family: -apple-system, "system-ui", "Segoe UI",
Roboto, sans-serif; font-size: 13px; font-style: normal;
font-variant-ligatures: normal; font-variant-caps: normal; font-weight:
400; letter-spacing: normal; orphans: 2; text-align: start; text-indent:
0px; text-transform: none; widows: 2; word-spacing: 0px;
-webkit-text-stroke-width: 0px; white-space: normal; background-color:
rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color: initial;"><li
style="unicode-bidi: plaintext;">Lightened<span> </span><code
style="font-family: monospace; color: rgb(208, 208, 208);
background-color: rgb(60, 60, 60); padding: 2px 4px; border-radius: 3px;
word-break: break-word; font-size:
0.9em;">--color-panel-bar-bg</code><span> </span>(grey-200 → grey-100)
for a softer chart-header band; the grey-300 divider still carries the
header/body edge.</li></ul><h3 style="unicode-bidi: plaintext; color:
rgb(204, 204, 204); font-family: -apple-system, "system-ui",
"Segoe UI", Roboto, sans-serif; font-style: normal;
font-variant-ligatures: normal; font-variant-caps: normal;
letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px;
text-transform: none; widows: 2; word-spacing: 0px;
-webkit-text-stroke-width: 0px; white-space: normal; background-color:
rgb(24, 24, 24); text-decoration-thickness: initial;
text-decoration-style: initial; text-decoration-color: initial;">
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
||
|
|
d770d0245a |
fix: preserve online evaluation provider API keys (#13739)
## Summary - preserve the stored provider API key when an edit submits a blank value - replace the stored key when a nonblank value is supplied - show the create-time required marker only for providers that require authentication - retain keyless creation for self-hosted providers ## Testing - ProviderFormPage Vitest suite passed: 8 tests - Targeted ESLint passed - cargo fmt check passed - git diff check passed - Focused Rust test compilation is blocked by unrelated existing alert-state model errors Related to #13655. Companion enterprise PR: https://github.com/openobserve/o2-enterprise/pull/2390 |
||
|
|
b9e11bb885 |
fix(web): classify unquoted LIKE patterns wherever the parser stops (#13818)
`x LIKE E00%` parses as the identifier `E00` followed by the modulo operator, so the PEG parser fails on a later token and the existing `found === "%"` check never fires — the error fell through to the allow-list suppression and the editor showed no diagnostic at all. Only patterns whose first character terminates the identifier (`LIKE BIN-%`) were caught. Add hasUnquotedLikePattern(), which inspects the LIKE/ILIKE/RLIKE operand nearest the error position and reports badLikePattern when it is a bare wildcard token. It runs immediately before the suppression return, so it can only reclassify errors that were previously dropped; quoted patterns, parenthesised expressions and function calls never match. Detection on the unquote_like_pattern mutation set goes 6/13 -> 13/13, so raise that threshold from 0.5 to 0.9. The old 0.5 sat exactly on the sample boundary, which is why adding one query to the shared query-agent corpus in #13808 turned the suite red. Also stop the per-mutation tests from regenerating the whole mutation pool (~1,000 queries x 16 mutations, each re-parsed) on every case: memoize generateBrokenQueries() and give the heavy tests an explicit 30s timeout. Spec runtime drops from ~112s to ~48s and the 5s-default timeouts go away. |
||
|
|
ddb67f3efb |
fix(synthetics): record from a specific step, and stop silently downgrading recorded actions (#13799)
Supersedes #13777, which carried the record-from-step commits alone. Closing that in favour of this, because the two changes land in the same three files (`types/synthetics.ts`, `useSyntheticsRecorder.ts`, `JourneySteps.vue`) and reviewing them apart means resolving the same conflict twice. ## Problem **A recorded hover was stored as a click.** Playwright 1.56 added `hover` to the recorder's action model, reachable from its "Choose action" picker. The extension's action mapper seeds every step with `action: 'click'` as a placeholder for its switch to overwrite, and returned that placeholder from `default:` — so any action name the switch did not know became a click the author never performed. On the usual hover target — a nav trigger, a dropdown opener — clicking it can navigate or submit. The run still reports green. There are three separate guards meant to stop exactly this, and none of them fired, because the relabel happens upstream of all of them: | Guard | Why it missed | |---|---| | `UNSUPPORTED_REPLAY_ACTIONS` (extension) | step already said `click` | | `RETIRED_ACTIONS` → `isStorableAction` | step already said `click` | | `V2_STEP_ACTIONS` (Rust validation) | `click` is valid | The same picker offers **Right click** and **Double click** as explicit choices. Both were flattened too: `click_count` was dropped by the mapper and never existed downstream, and the probe's executor called `locator.click({ timeout })` while reading neither `button` nor `click_count`. A deliberately recorded right click replayed as a left click; a double click as a single one. **Recording could only start from scratch.** Fixing step 12 of a 15-step journey meant re-recording all 15. ## Change **Record from a specific step.** Each step gets a record action that replays the prefix before it, then flips the recorder into insert mode at that point. A restore that cannot reach the requested step reports where it stopped (`prefixFailed`) rather than silently recording from the wrong place. **Every action Playwright can record is now stored and replayed as itself.** - `hover` is a first-class v2 action — mapped, stored, validated, and executed by `Locator.hover` in the probe and `Frame.hover` in the extension player. - `button` and `click_count` travel to storage, so right click and double click replay as recorded. - An action name the mapper does not know now **throws** instead of returning the `click` placeholder. This is the part that is not hover-specific: upstream added one action in nine minors and will add more, and the next one must be a deliberate decision rather than a silent downgrade. **The extension handshake reports capabilities, not just presence.** `getStatus` now returns `extVersion` and a `capabilities` array; O2 gates affordances on `hasCapability()` with a defined pre-handshake fallback, and warns when the installed build is older than the minimum. Previously the protocol carried no version at all — Chrome updates the extension independently of when O2 deploys, so the two could disagree about the wire with no way to say so. **Two dead message declarations, opposite problems.** `setSources` no longer exists in playwright-core (sources arrive alongside the actions), so its declared variant could never fire — while its `generatedCode` field is exactly what an eject-to-code feature would reach for. Deleted. `elementPicked` is the reverse: it fires on every "Pick locator" and every click in inspecting mode, and was being discarded, which made inspect mode a dead end. Now kept. ### Compatibility `button` and `click_count` are optional with defined absent-behaviour — absent means a single left click. Every journey stored today stays valid, means the same thing, and serialises byte-identically. **No schema version bump and no migration.** A test pins that rather than leaving it as an intention. `hover` is a new vocabulary entry with no default, so the probe must be able to execute one before O2 is allowed to store one — the probe change ships first. ## Implementation | File | | |---|---| | `src/config/src/meta/synthetics.rs` | `hover` joins `V2_STEP_ACTIONS`/`V2_ELEMENT_ACTIONS`; `button` and `click_count` added to `BrowserStepV2` with validation (`left\|middle\|right`, `1..=3`) | | `web/src/types/synthetics.ts` | `button`/`clickCount` on both step types; `extVersion` + `capabilities` on `RecorderStatus`; `setSources` variant deleted and `elementPicked` typed; `prefixFailed` and insert-mode fields on `recordingStarted` | | `web/src/utils/synthetics/mapRecordedStep.ts` | promotes `button`/`clickCount` from the wire, like every other stored field | | `web/src/utils/synthetics/buildV2Steps.ts` | `hover` in `ACTION_TO_V2`; crosses camelCase → snake_case for the two click fields | | `web/src/constants/synthetics.ts` | `hover` out of `RETIRED_ACTIONS`; `MIN_EXTENSION_VERSION` | | `web/src/composables/useSyntheticsRecorder.ts` | `startRecordingFrom`, `hasCapability`, `pickedSelector`, `extensionOutdated` | | `web/src/components/synthetics/journey/{BrowserJourney,JourneySteps}.vue` | per-step record action and its wiring | `click_count` is capped at 3: the recorder only ever emits 1 or 2, and an unbounded count is a way to hold a page's event loop open. The two click fields cross from camelCase to snake_case in `buildV2Step` and nowhere else — reading `step.wire` directly inside it would have worked and invented a second path into storage. ### Depends on a recorder extension build `hover`, the click fields and the capability handshake all need the matching extension build. O2 degrades honestly without it: `hasCapability()` falls back to the pre-handshake set, and an older build raises the outdated-extension warning instead of failing on a message shape it does not recognise. ## Tests - **Rust** — hover accepted as an element action; `button`/`click_count` validated at both bounds; a step carrying neither still validates (the compatibility guarantee). Two existing tests encoded "hover is rejected" and now say the opposite. 101 pass. - **Probe** — hover hovers rather than clicks; a right click sends the recorded button; a double click sends two clicks; a journey stored before these fields replays unchanged. The action union is asserted against the Rust vocabulary, so the next divergence fails a test instead of reaching an executor with no case for it. Also pinned: a selector carrying a frame hop resolves into the iframe, which had no coverage anywhere. - **Web** — 1213 across 60 files. Nine existing tests encoded "hover is retired" across constants, `buildV2Steps`, `buildPayload` and the save-gate schema; each now states the opposite deliberately. - **Extension** — the unmapped-action throw, hover round-tripping both directions, and a double click surviving the round trip as two clicks. `vue-tsc`, `cargo clippy -D warnings`, and `prettier --check` are clean. The last commit is formatting only: the three record-from-step files arrived failing `format:check`, which is a gate of its own and would not have been caught by lint. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
192f11f7ea |
fix(i18n): correct mistranslations in zh-CN locale (#13835)
## Summary
Fixes machine-translation errors in the Simplified Chinese locale
(`web/src/locales/languages/zh-CN.json`), found by sweeping the file
against the English source. Three batches of the same class of error:
### Nonsense translations (wrong sense of the English word)
| Before | After | English source |
|---|---|---|
| 痕迹 / 踪迹 (physical traces) | 追踪 | Traces (nav, tabs, buttons — 8 keys)
|
| 朗姆酒 (the liquor) | RUM | RUM |
| 漂亮 / 崩溃了 (beautiful / crashed) | 格式化 / 折叠 | Pretty / Collapsed view
toggle |
| 汽车 (a car) | 自动 | Auto (layout mode) |
| 转 / 转弯 (road turns) | 回合 | Turn / Turns (conversation) |
| {n} 个电话 (phone calls) | {n} 次调用 | {n} calls (tool calls) |
| oTel 收藏家/代理人 (art collector) | OTel Collector / 代理 | OTel Collector /
Agent |
| 空缺评测任务 (job vacancy) | 打开评估任务 | Open Eval Jobs |
| 简历 (a CV) | 恢复 | Resume (pause/resume) |
| 出口 (trade export, ×3) | 导出 | Export |
| 逃脱了 (ran away) | 已转义 | Escaped (string escaping) |
| 测试赛 (sports match) | 测试匹配 | Test Match |
| 比分 (sports score) | 分数 | scores (eval scores) |
| 好吧 ("well, fine") | 正常 | Ok (status) |
| 领域 (domain/field) | 区域 | Region (bucket region) |
| 全球 (worldwide, ×4) | 全局 | Global (scope) |
| 商店 (a shop) | 存储 | Store (key store) |
| 尺寸 (physical size, ×5) | 维度 | Dimensions (metrics) |
| 用法 / 使用密钥 (how-to / secret key) | 用量 / 用量键 | Usage / Usage key |
| 滤镜 (photo filters) | 筛选条件 | Filters |
| 网络缓存影响 (network) | 缓存净影响 | Net Cache Impact |
| 申请并搜索 (apply for) | 应用并搜索 | Apply & Search |
| 压缩后的尺寸 | 压缩后大小 | Compressed Size |
| 等得紧,我们正在搜寻你的踪迹。 | 正在加载追踪... | Loading Traces... |
### Terminology unification
- **GenAI agents → 智能体** (agent graph, agent behavior, agent mapping,
sessions — ~40 strings). Infrastructure agents (host collectors,
synthetics runners) keep the conventional 代理.
- **Eval jobs → 评估任务** (was a mix of 评估作业 / 评测任务 / 作业). Batch jobs
elsewhere (backfill, search jobs) keep 作业.
- **Enrichment table → 富化表** (was a mix of 充实表 / 丰富表 / 扩充表).
- **Cipher Key → 加密密钥** (was mixed with 密码密钥); **Actions → 操作** (was 行动
in 4 places); **Running Queries → 运行中的查询**; synthetics **journey → 流程**
(was 旅程); assistant 助理 → 助手.
- `shortcuts.actions.tracesSearch` resynced with current English source
("Run query" → 运行查询).
### Cosmetic
- Shortcuts cheatsheet: corrupted ⌘ symbol (rendered as ▼) restored;
ungrammatical strings fixed (按?任何地方 → 在任意位置按 ?, 焦点搜索栏 → 聚焦搜索栏, 导入控制面板 →
导入仪表板); untranslated example values restored to `input`/`output`;
half-translated strings completed (Spans 表格视图 → 跨度表格视图, Stacktrace 已复制 →
堆栈跟踪已复制).
Notes:
- zh-TW.json was checked for the same error patterns and is clean.
- 跟踪 vs 追踪 for "trace" is still mixed in a few longer sentences; left
as-is since 跟踪 is not incorrect, only inconsistent.
## Test plan
- JSON validated with `python3 -c 'json.load(...)'` after each batch;
keys unchanged, only values edited (~200 lines).
- Grep confirms none of the wrong terms above remain in zh-CN.json.
|
||
|
|
7f74925605 | feat: banner as notification (#13667) | ||
|
|
c246119809 |
fix(i18n): stop translated placeholder names crashing localized pages (#13833)
Fixes #13751 ## The crash vue-i18n compiles messages just-in-time (`__INTLIFY_JIT_COMPILATION__`), and a compile error is **thrown**, not warned — it tears down whatever component asked for the message. The translation pipeline had been localizing placeholder *names*, which is exactly that kind of error: ``` en-US "Are you sure you want to delete {identifier}?" zh-CN "您确定要删除 {标识符} 吗?" -> SyntaxError: 2 (INVALID_TOKEN_IN_PLACEHOLDER) ``` IAM → Service Accounts rendered blank in Chinese for this reason. The two zh-CN strings named in the issue had already been patched by hand in #13707, but the *class* was never swept. ## What was actually broken Compiling every message in every locale file with vue-i18n's own compiler found three groups: | | count | symptom | |---|---|---| | Does not compile | 132 | page blanks with `SyntaxError` — 8 locales: es, fr, it, ja, ko, nl, pt, tr | | Compiles, unknown name | 147 | `{Anzahl}` for `{count}` → value renders as an empty string | | Stale text, dropped placeholder | 5 | `{org}`, `{payer}`, `{endpoint}`, `{service}` — English source no longer has them | Worst of the first group are mangled vue-i18n literal escapes, e.g. `{'{'}team{'}'}` coming back as `{'{'} '}` — an unbalanced brace. All 279 are corrected here. The existing translated prose is kept verbatim; only the tokens are restored. The 5 stale ones are retranslated from the current English text, since restoring a token that no longer exists is not an option. ## Why it can't come back **`web/src/locales/enUsMessages.spec.ts` already did this — for en-US only.** That left the machine-translated locales, the actual source of the bug, uncovered. Renamed to `localeMessages.spec.ts` and extended to every locale, plus a second assertion that a translation only interpolates names en-US defines. That second check is a **subset** rule, not equality: dropping a placeholder the target language does not need stays legal (an English plural suffix like `{plural}` has no Japanese equivalent). Introducing a name en-US never passes a value for is always a bug. Placeholder names are collected by *running* the compiled message against a recording context rather than by pattern-matching the source, because only the compiler knows which braces are placeholders and which are literal escapes — `{'}'}` is one token whose body is the character a `{...}` regex stops at. All plural branches are evaluated. **`scripts/translations/translator.py` — `_validate` had the same regex blind spot** (`{[^{}]*}`) and never checked that the output compiles at all, which is why these landed. It now tokenizes the way vue-i18n does and rejects anything vue-i18n would refuse, so the pipeline stops emitting them rather than CI merely catching them afterwards. Escape drift (`{'{'} rows {'} rows {'}`) is caught too, because literal escapes are now part of the compared token multiset. ## Verification - The Python scanner was cross-checked against vue-i18n's compiler over **all 170,055 messages** in the 15 locale files — identical compile verdicts and identical token sets, 0 divergences. - Injecting the original `{标识符}` string back into zh-CN fails the new spec; injecting a compiling-but-wrong `{bilv}` fails the second assertion. - `npx vitest run --environment jsdom --root src/ locales/` → 45 passed. `prettier --check` and `tsc` clean on the spec. - Only `en-US.json` is imported anywhere in `web/src`, so no existing test depends on the changed locale data. ## Not in scope A handful of translations are awkward but compile and bind correctly (e.g. ko-KR renders "ingestion limit" with the eating sense of the word). Left alone to keep this diff auditable as a mechanical token restoration. |
||
|
|
0dba67d638 |
feat: composite alerts (#13797)
Design at : alerts/composite_alerts/composite_alerts.md ## Summary - add composite alert graph persistence, evaluation, scheduling, lifecycle APIs, and deletion safeguards - add composite alert UI forms, preview, references, list/detail integration, and localization - add Rust, API, Vue, and Playwright contracts ## Verification - cargo fmt --all -- --check - cargo check -p openobserve-core - cargo check -p openobserve-api-management - npm run type-check:composite-alerts - npm run type-check:app - npm run lint:ci -- --quiet - design/token/style checks - targeted Rust/Vitest suites - browser QA against local alerts UI ## Follow-ups (intentionally deferred, documented in the spec) - `RunOutcome::Error`/`NotifyFailed` outcome records on composite delivery failure (§11.5) - Incident detail live-definition resolver for composites + "definition unavailable" retention (§9.6) - `alert_composite_*` observability metrics (§16) - SLO/stream delete-conflict 409 bodies with readable-vs-hidden parent split (§10.3) - Super-cluster startup preflight (§18) <img width="1650" height="979" alt="image" src="https://github.com/user-attachments/assets/3def5246-7bf7-48fe-9a42-c0ac08271ea9" /> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
3fda083f51 |
feat(traces): add trace time index (#13827)
Design at: [https://github.com/openobserve/designs/blob/main/infrastructure/file-list/trace-time-index.md](https://github.com/openobserve/designs/blob/main/infrastructure/file-list/trace-time-index.md) ## Summary - add an hourly Metadata time index per trace stream to resolve a trace ID to its full time range - add external time-range and trace-details APIs, including bounded locate/expand behavior and standard search responses - integrate index generation into trace ingestion and preserve query visibility through the synchronous Metadata write path - synchronize retention and deletion for associated Metadata streams - reuse the shared trace stream permission check across trace APIs ## Why Trace detail lookup currently depends on a caller-provided time range, which can omit spans outside that window. The time index provides a bounded, best-effort range lookup for `stream + trace_id` without scanning the full trace stream. Closes #13823 ## Environment variables | Variable | Default | Effect | | --- | --- | --- | | `ZO_TRACE_TIME_INDEX_ENABLED` | `true` | Enables per-trace-stream Metadata indexes, index writes during trace ingestion, and indexed time-range lookup. Only traces ingested after the feature is enabled are indexed; there is no historical backfill. | | `ZO_QUERY_TIMEOUT` | 600 seconds | Existing setting reused as the cumulative Trace Timer locate/expand deadline and as the default timeout for the trace-details search. | When enabled, each traces stream can create a related Metadata stream named `trace_time_index_{stream}`. Its retention settings follow the source stream, and it is removed with the source stream. ## API changes All timestamp parameters and returned time ranges use microseconds. ### Get a trace time range ```http GET /api/{org_id}/{stream_name}/traces/{trace_id}/time_range ``` Query parameters: - `hint_ts` (optional): timestamp hint used to start the index lookup Returns the source stream, trace ID, and the resolved `start_time` / `end_time`. The `range` field is `null` when the index cannot resolve the trace. ### Get trace details ```http GET /api/{org_id}/{stream_name}/traces/{trace_id}/details ``` Query parameters: - `start_time` and `end_time` (optional, but must be supplied together): caller-provided range - `hint_ts` (optional): timestamp hint for the time-index lookup - `timeout` (optional): trace-details search timeout in seconds The endpoint unions the caller range with the indexed range, so it never narrows a caller-provided range. If neither the caller range nor the index can provide a range, it returns `400`. The response uses the standard search response and includes the effective range in `new_start_time` and `new_end_time`. ## Validation - `cargo test -p openobserve-api-search --lib` — 145 passed - `cargo test -p openobserve-core traces::time_index::tests --lib` — 7 passed - `cargo test -p infra db::trace_time_index::tests::test_coverage_start_cache -- --exact --nocapture` — passed - `cargo check -p openobserve-api-search` - `cd web && npm run type-check:app` - end-to-end ingestion and query validation with the data generator ## Validation notes - targeted ESLint could not start because the local web dependencies are missing `@eslint/css` - enterprise-only compilation could not be completed from this OSS checkout because the local enterprise overlay is unavailable |
||
|
|
dbee572722 |
fix: slo bugs (#13784)
closes https://github.com/openobserve/o2-enterprise/issues/2397 --------- 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: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
6927c2f335 |
fix(synthetics): collapse the variables panel by default (#13825)
## What The variables panel on the browser-test **Journey** step now starts collapsed. ## Why The journey is what that page is for, and the panel was taking a share of the width before the author had asked for it. The toolbar toggle sits right next to the journey and is labelled, so bringing the panel in is one click — and the splitter position is still shared with Configure, so nothing about the panel's own behaviour changes. ## Scope One line plus a comment. `variablesPanelOpen` is journey-only by design (the existing comment above it explains why it is not shared with Configure), so this cannot affect the Configure step. ```diff -const variablesPanelOpen = ref(true); +const variablesPanelOpen = ref(false); ``` ## Testing `npx vitest run src/views/synthetics/CreateBrowserTest.spec.ts` — 44 passing. Split out of a larger synthetics branch so it can land on its own. |
||
|
|
0ed5336bf1 | chore: adding HA mode for o2-ai agent (#13525) | ||
|
|
e490a5c347 |
fix(logs): load the stream list on Visualize when no stream is selected (#13812)
Entering Visualize from the logs page with no stream selected left the
Stream dropdown on "No options found" — enabled, openable, and empty, so
there was no way to pick one.
PanelFieldList defers its initial fetch in edit mode until a stream is
set, exempting only "metrics". The Visualize tab ("build") needs the
same exemption: its select is the user's own, and the list is keyed on
stream_type alone, so waiting for a stream buys nothing.
Also arms the stream_type watcher at mount, so changing Stream Type with
a blank stream now reloads the list instead of doing nothing.
- https://github.com/openobserve/o2-enterprise/issues/2165
|
||
|
|
d1f8941512 | test: stabilize test cases for the Alpha environment (#13551) | ||
|
|
e4503f7fcb | fix: Fix/match all pipe query corruption (#13764) | ||
|
|
3d06ed0423 |
fix(logs): reject LIMIT in filter mode instead of building an invalid query (#13773)
Closes #6915. Without SQL mode the search bar's contents become the WHERE body of a generated `select [FIELD_LIST][QUERY_FUNCTIONS] from "[INDEX_NAME]" [WHERE_CLAUSE]`, and `handleNonSqlMode` splices the input in verbatim after stripping comments and quoting known field names. Nothing checks that the input is actually a predicate, so `k8s_namespace_name = 'nginx-ingress' LIMIT 10` produces valid SQL. The results grid runs it and returns rows, while the histogram query built from the same input is rejected by `is_eligible_for_histogram` and surfaces `SearchHistogramNotAvailable`. That is the split described in the issue — the log list works, the histogram errors. The server side of this already exists, so the guard belongs in the UI, before either request goes out. ## What changed | | | |---|---| | `utils/query/nonSqlLimit.ts` | new — `hasLimitClause()` | | `useSearchQuery.ts` | the guard in `handleNonSqlMode`, using the file's existing `notificationMsg` + `return null` path | Placement note: `hasLimitClause` lives in `utils/query/` rather than in the composable because it holds no state and touches no reactivity — the same split `doubleQuoteWarnings.ts` and `colorizeQuery.ts` already use. The check is deliberately narrow. `LIMIT` matches only when followed by a number, so `limit = 5` and `rate_limit >= 100` pass through. String literals are blanked first, so `msg = 'rate limit 500 exceeded'` is unaffected. Line and block comments are stripped after that, so `code = 200 -- limit 10` — which works today — keeps working. ## Tests - **17** on the derivation — the issue's own query, case variants, whitespace and newlines before the number, a bare `LIMIT 100`, a field named `limit`, `rate_limit >= 100`, the word inside a literal, a literal with a doubled quote, `limit = 'none'`, leading / trailing / block comments, a real LIMIT alongside a comment, and a dash sequence inside a literal. - **6** on `buildSearch` — rejects the reported query and sets the message, still builds without a LIMIT, allows `limit = 5`, ignores commented-out LIMITs, and does not fire in SQL mode. Each rejection test was checked to fail when the guard is reverted. The negative cases stay green either way, which is what separates them from tests that merely restate the implementation. ## Verification - `npx vitest run --root src/ composables/useLogs utils/query` — **1965 passed**, 33 files, 0 failed - `npx vue-tsc --noEmit -p tsconfig.vitest.json` — clean, and identical to `main` - `npx eslint` on all four files — clean - `npx prettier --check` — clean ## Caveats - Not exercised in a running app; covered by unit tests only. - `ORDER BY`, `GROUP BY` and `HAVING` reach the same splice and are **not** handled here. Happy to extend if you want them, but the issue asked about `LIMIT` and I didn't want to widen it uninvited. - `plugins/logs/IndexList.vue` holds an independent copy of the same `[WHERE_CLAUSE]` splice for field-value lookups. It is reached by clicking a field rather than running a search, so it sits outside this path — flagging it rather than changing it. --------- Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com> |
||
|
|
fb50aaea7f |
fix(deps): resolve 39 Dependabot alerts (#13774)
## Summary - update vulnerable web transitive dependencies (`axios`, `brace-expansion`, `fast-uri`, `http-proxy-middleware`, `js-yaml`, `uuid`, and `websocket-driver`) - remove the unused `node-polyfill-webpack-plugin`, eliminating the unpatched `elliptic` dependency chain - update Playwright to 1.55.1 and `node-forge` to 1.4.0 in the UI test lockfile - adapt `BaseImport` to Axios 1.18's stricter response-header type This is expected to resolve 39 of the 41 currently open Dependabot alerts. ## Remaining alerts - `rmcp` remains on the project's custom `rmcp-openapi` fork. Updating it safely requires a coordinated change to the enterprise `Cargo.toml.openobserve`, which currently replaces the OSS manifest during enterprise builds and pins the old API. The compatible intermediate upstream releases also lack the fork's required `allOf`/`anyOf` support. - `thrift` 0.17.0 remains through `parquet` 58.4.0. The patched Thrift line (0.23+) is outside Parquet 58's version constraint. Parquet 59 removes the Thrift dependency, but adopting it requires a coordinated Arrow/DataFusion 59 upgrade. ## Validation - `npm ci` and `npm audit --package-lock-only` in `web/` (0 vulnerabilities) - `npm ci` and `npm audit --package-lock-only` in `tests/ui-testing/` (0 vulnerabilities) - `npm run type-check:app` - `npm run lint:ci -- --quiet` - `npm run lint:design:strict` - `NODE_OPTIONS=--max-old-space-size=8192 npm run build` - `npm run test:unit -- --run` (41,917 passed, 404 skipped) - `npx vitest run src/components/common/BaseImport.spec.ts --environment jsdom` (41 passed) - Playwright test discovery under 1.55.1 (2,076 tests in 265 files) - `cargo fmt --all -- --check` - `cargo test -p openobserve-mcp` (94 passed, 1 ignored) - `cargo audit` (0 vulnerabilities; 2 allowed unmaintained warnings) |
||
|
|
360b989272 |
feat(slos): PromQL support for count and time-sliced SLOs, plus SLO/alert regression fixes (#13761)
Supersedes #13738, whose commit is included here as the first of four. Adds PromQL support to count and time-sliced SLOs, lets metrics streams choose SQL or PromQL, and fixes three shipped bugs found along the way. ## Shipped bug: every SQL time-slice SLO recorded wrong history `fetch_rows`' `SliQueryPlan::Single` arm normalized every hit with `with_good_column: true`, but that arm serves **two** shapes and only one projects `zo_slo_good`: | shape | projects | result | |---|---|---| | count single-query | `zo_slo_good` + `zo_slo_value` | correct | | time slice | `zo_slo_value` only | `good` defaulted to `0.0` | So every SQL time-slice slice was classified from `0.0` instead of its aggregate. With a positive threshold, `<`/`<=` (e.g. `p95 < 300ms`) recorded every slice **good** — the SLO read ~100%, the budget never burned, and no alert on it could fire. `>`/`>=` recorded every slice **bad** and fired continuously. Shipped in v0.92.0 (`4772df1723`); `to_row` had no time-slice test, which is how it got through. Fixed by deriving the flag from the SLI type in a new `single_query_rows`. Deliberately **not** fixed inside `to_row` by falling back to `total` — that would read a count bucket whose `SUM` came back NULL as *fully good*, inventing uptime. A test forbids it. **Stored history is not rewritten.** It ages out within one window; an operator can force a rebuild sooner by making a real edit (a no-op re-save does nothing — `update` bumps only on `definition_changed`). No auto-migration: bumping every time-slice SLO at boot would freeze every attached alert org-wide until backfill cleared the coverage floor, and double each org's row budget for 97 days — a self-inflicted monitoring gap to repair a reporting error. ## PromQL support **Time slice** carried a `query_language` field the planner ignored, so a PromQL time-slice SLO saved cleanly and measured nothing, forever. - `SliQueryPlan::PromQlValue` — one expression, not a good/total pair, planned at slice ends from the same helper the count arm uses. - The expression is passed through **verbatim**. Grouping comes from series labels; wrapping it in `sum by (...)` the way the SQL arm injects GROUP BY would destroy the aggregate (the sum of four pods' p95 is not a p95). - `promql_value_rows` **rejects** two series colliding on one `(slice_start, group_key)` via `RejectReason::AmbiguousSeries` instead of summing. Summing is right for counters (what `promql_rows` does) and meaningless here. Detection is unconditional, so the ungrouped case — an unaggregated `histogram_quantile` returning one series per instance — is covered. Rejects are plumbed through `fetch_rows` into `PassResult.rejected` on both the live and backfill paths. **Count** already had a working `CountSource::PromQl` backend that no UI could reach. ## Metrics streams choose SQL or PromQL `language_suits_stream` refused SQL whenever `stream_type == "metrics"`, and the form derived the language from the stream type — so metrics had no SQL option. A metrics stream is an ordinary stream with a `value` column, and `SELECT histogram(_timestamp, '5 minute'), avg(value) FROM cpu_usage` is a perfectly good SLI. SQL is now valid for any stream type; PromQL stays metrics-only. The form asks via a toggle (defaulting to PromQL) instead of deriving. ## Validation - `scope` refused for PromQL — a SQL `WHERE` fragment with nowhere to go in a PromQL plan. - Empty `query` refused for **both** languages (the SQL aggregate was previously never validated — same silent-freeze shape). - Expressions parsed with `promql-parser` at save, in `core` (`config` has no parser). - **Parse-only by design.** A grouping check requiring the root to be an aggregation whose `by(...)` matches `group_by` wrongly rejects `histogram_quantile(0.95, sum by (le, region)(...))` (function-call root; `le` is a necessary label superset) and binary-op roots like `sum by (region)(increase(a[5m])) - sum by (region)(increase(b[5m]))`. A "warn instead" variant needs a warnings channel the save API doesn't have. ## Also fixed - **Time-slice comparator 422.** `SliConfig::TimeSlice.comparator` has no serde default, so a dropdown the user never opened was omitted and the save died with a bare 422 — blocking creation of *any* time-slice SLO from the UI. Seeded to `<` only when blank, so a stored comparator survives an edit. - **SLO/alert/service-stream regressions** (the commit from #13738): fractional-threshold serde round-trip, `SloAlertCondition` UI, alerts table, service streams. ## Verification - 487 config · 206 core · 45 infra · 418 frontend — all passing; clippy `-D warnings`, `cargo fmt`, prettier, eslint, `vue-tsc` all clean. - Driven through a real browser against a running server (isolated instance, own data dir). All four SLI/language combinations create and store correctly: count·PromQL, count·**SQL over metrics**, time-slice·PromQL, time-slice·**SQL over metrics**. Also verified: the toggle swaps field shapes both ways, scope shows for SQL and hides for PromQL, PromQL-only hints appear only in PromQL mode, and editing a stored SQL-over-metrics SLO reopens as SQL with its predicate intact. - Validation rejections confirmed live with actionable messages: PromQL-with-scope, unparseable PromQL, and an empty SQL aggregate. Known limitation, pre-existing: `threshold` likewise has no serde default and is not seeded, so leaving it blank still 422s. That is genuine user error rather than an untouched-control trap; adding form validation was out of scope. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
b07b3d4229 |
feat(functions): replace language radios with a segmented toggle (#13766)
The Add Function header selected VRL vs JavaScript with a radio group and a single info icon. That icon only ever described the ALREADY-SELECTED language, so learning what the other one was for meant switching to it first. - Radio group -> OFormToggleGroup segmented control with a sliding indicator, each option carrying a language mark (V / JS). The badge variants match the transType column in FunctionList so VRL/JS read the same everywhere. - Give EACH option its own info icon and static tooltip, so both languages are readable without selecting either. Forced-language hosts (workflow function nodes are JS-only) hide the toggle, so the locked language's tip moves to a standalone icon. - Add a pipe divider between the two options, and one between the function-name title and the toggle. data-test renames `...-vrl-radio` -> `...-vrl-option` (same for js): "radio" described the old implementation. E2E page objects would have broken on this change regardless of naming -- toggle items expose data-state="on|off", not the radio group's "checked|unchecked". Verified: FunctionsToolbar.spec.ts 18/18 pass, vue-tsc clean. ESLint could not be run locally (@intlify/eslint-plugin-vue-i18n missing from node_modules). |
||
|
|
4b9204f69f |
feat(synthetics): collapse journey advisories into an on-demand suggestions chip (#13759)
## Problem
The browser journey editor stacked two **always-on** advisory cards
between the toolbar and the first step:
- *"This journey does not verify anything"* — no `assert` step in the
journey
- *"No test attributes found in this recording"* — no step produced a
`test_attribute` locator candidate
Both derived their visibility from the journey's own content, and both
conditions are the normal case for a real recording — so they rendered
on every visit to every affected journey. Each was dismissible, but
dismissal lived in a local `ref(false)`, so it died on remount: authors
closed the same two cards on every visit and still began reading their
steps two cards down the page.
## Change
One warning badge in the Steps toolbar — a warning icon and a count, no
prose:
- **Hover** names it ("1 suggestion for this journey"), from the same
string as the trigger's `aria-label` so the two cannot drift.
- **Click** opens a popover with each suggestion in full, separated by
rules, plus a footer stating that suggestions never block saving or
running.
- **Never opens on its own**, on any render.
- **No dismiss.** The chip costs no vertical space, so suppressing it
buys nothing — and a suggestion that can be waved away is one an author
never has to actually decline. A suggestion leaves when the condition
behind it is resolved.
A zero-assertion journey remains accepted with a warning; nothing here
blocks a save.
Transient banners are deliberately untouched — replay
running/passed/failed/stopped, incognito, pre-flight, recorder error.
They appear because something just happened, and a replay result that
does not announce itself is a worse product.
## Implementation
| File | |
|---|---|
| `web/src/utils/synthetics/journeySuggestions.ts` | new — pure
derivation over the steps; one small producer per rule; carries i18n
**keys** rather than text, so it needs neither Vue nor `useI18n` and a
rule is testable without mounting anything |
| `web/src/components/synthetics/journey/JourneySuggestions.vue` | new —
chip, tooltip, popover; presentation only |
| `web/src/components/synthetics/journey/BrowserJourney.vue` | computes
the suggestions, renders the chip in the toolbar, appends the offered
assertion |
| `ZeroAssertionNotice.vue`, `TestIdMisconfiguredNotice.vue` (+ specs) |
deleted — each was a visibility computation plus a card, and both halves
now have better homes |
Adding a future advisory is one producer and no template change.
Placement note: this lives in `utils/synthetics/` rather than a
composable because it holds no state and touches no reactivity — the
same split `deriveLocatorKind.ts` and `locatorStability.ts` already use
for derivations consumed by these components.
## Tests
- **17** on the derivation — both rules, empty journey, navigate-only
journey, empty candidate list, a test attribute outranked *within* a
step, both conditions at once in stable order, and that the offered
assertion is empty (`element_visible` with no selector/locator) rather
than guessed.
- **15** on the component — no chip at zero, count only and no prose,
pluralization, closed on mount, opens on click, tooltip suppressed while
open, action emits and closes, separators between suggestions.
- **5** on the `BrowserJourney` wiring — old hooks gone, suggestions
handed down, nothing offered when `readonly`, the assertion appended to
the tail with prior step order and ids intact, and the suggestion
dropping once the parent commits.
Two things the tests caught that review would not have:
1. Resolving the last suggestion unmounts the popover but not the
component holding its `open` flag — so a panel left open came *back*
open the next time a suggestion appeared. Regression test written,
confirmed failing, then fixed.
2. One component block runs against the **real** `OPopover` and `OBadge`
instead of a stub. `OBadge` declares `inheritAttrs: false` and the
popover trigger is `as-child` — precisely the pairing that silently
drops a click handler and leaves a chip that looks correct and does
nothing. Every other test stubs the popover and would not see it.
## Accessibility
`⚠ 1` has an accessible name of "1", so the trigger's `aria-label` is
load-bearing and carries the full count string. Child-mode tooltips are
pointer-only, so a keyboard user's path is that label plus the popover
they open with Enter.
Accepted trade-off, stated plainly: the old cards carried
`role="status"` and were announced on appearance. Nothing is announced
now — that announcement is what this change exists to suppress.
## Verification
- `npx vitest run src/components/synthetics src/utils/synthetics
src/views/synthetics` — 1147 passed, 58 files
- `npm run type-check` — clean
- `npm run lint` — clean for every touched file (the repo's pre-existing
`eslint.config.js` / `vitest.config.ts` findings are unchanged and
present on `main`)
|
||
|
|
de0d37e23d |
fix(alerts): stop losing Slack alerts on undeliverable link URLs (#13742) (#13753)
Fixes #13742 Fixes openobserve/o2-enterprise#2394 ## The bug A content template link with a non-http scheme (`javascript:alert(1)`) made Slack reject the **entire** notification with `400 invalid_attachments`. The alert was lost outright and `triggers` recorded `notify_failed`. ## Root cause `safe_url` neutralises a hostile scheme by substituting `BLOCKED_URL` (`"#"`). That is **safe** but not **deliverable** — Slack, Teams, Discord and PagerDuty validate action URLs server-side and reject the whole payload when one is not an absolute `http(s)` URL. A security substitution was turning into total message loss. The two properties are different, and links need both. So the fix splits by medium: | renderer | link handling | |---|---| | Slack buttons, Teams actions, Discord `embed.url`, PagerDuty `href` | `dispatchable_url` → **drop** | | HTML email, email plaintext, SNS plaintext, Discord description | `safe_url` → substitute `#` | | Webhook envelope | unfiltered — versioned machine contract, documented | Dropping beats rewriting: the alert body is worth more than the button, and a button pointing somewhere misleading is worse than no button. `dispatchable_url` requires a **non-empty authority**, not just an allowlisted scheme — `http:javascript:alert(1)` and `https://` are valid *opaque* RFC 3986 http(s) URLs that Slack still rejects. It also rejects raw spaces and control characters, which variable substitution can introduce. ## Related issues fixed in the same area - **Empty `ZO_WEB_URL`** (not in the report): `alert_url` becomes a root-relative `/web/logs?…`, which `safe_url` passes through by design, and it lands in the always-appended "View in OpenObserve" button. Same `invalid_attachments`, on deployments that never authored a hostile template. - **PagerDuty** validates `links[].href` server-side too — same lost-alert class, converted. - **Save-time rejection** (`ContentSpec::validate`): a clear 400 naming the offending link, instead of a template whose link silently never works. Also wired into **preview** and **test-send**, which previously accepted a draft that couldn't be saved and echoed the raw hostile URL back to the UI. - **Slack image-fallback misdiagnosis**: removing the image proves the image was at fault, but only an image pointing at *our* `web_url` justifies tripping the process-wide chart suppression (1h, across every alert) and telling the operator to fix `ZO_WEB_URL`. A custom template's third-party image no longer does either. - **a11y**: `OInput` links its error message to the control via `aria-describedby`; the textarea branch also gained `aria-invalid`. ## o2-enterprise#2394 (fixed here, not in the enterprise repo) Clearing the Monaco body and saving toasted "Please fill required fields" with no indication of *where*. The schema already produced an error on the `body` path — a bare Monaco bridged in via `setFieldValue` just had no `OFormInput` error slot to render it. Now a red border + message driven by the same field state `OFormInput` reads. The aria wiring goes on the **shell**, not on `<QueryEditor>`: `CodeQueryEditor` sets `inheritAttrs: false` and binds `$attrs` to a non-focusable wrapper, so attributes passed to the component would be inert — false assurance for a screen-reader user. > The issue names the title field too. It's an `OFormInput` and already highlights correctly; I added a regression test pinning that rather than changing it. This fix is entirely in OSS (`web/`) since the template form isn't enterprise-gated, so there's no companion enterprise PR. ## Layering note Save-time validation is a **UX gate, not the security boundary**. Link URLs are templates — a scheme that only materialises after `{variable}` substitution can't be judged at save time. The render layer is what actually stops delivery, and it also covers every template saved before this validation existed. Both layers are needed; neither is sufficient. ## Testing - Every fix written test-first (verified RED) and **mutation-tested** — each new test fails when its fix is reverted in substance. - Golden files unchanged: legitimate URLs render byte-identically, so no over-blocking. - Rust: `alerts::notifications` 159 · `config` 3130 · `api-management` 424 — all passing. `cargo clippy --all-targets` and `cargo fmt --check` clean. - Frontend: full suite **41,597 passing** (run because `OInput` is shared library code). `vue-tsc`, `eslint`, and `npm run format:check` clean. - Two independent cold-start review passes; findings from both are folded in, including a P0 where the first version of `dispatchable_url` still let the original bug through. Pre-existing and unrelated: `alerts::destinations::tests::test_alert_destination_template_is_optional` fails locally on a DB connection reset — verified failing on unmodified `main` too. |
||
|
|
883fc97046 |
fix(dashboard): deduplicate panel and layout IDs on import and dashboard load (#13760)
https://github.com/openobserve/openobserve/issues/13104 |
||
|
|
786f4f9f72 |
fix: dashboard label overlap issues (#13725)
1. <img width="727" height="242" alt="image" src="https://github.com/user-attachments/assets/2a84c1bf-2bc0-4fa7-aae5-e7801b99c93b" /> 2. <img width="167" height="380" alt="image" src="https://github.com/user-attachments/assets/6d937583-eb51-458c-8dac-fcf668f1f145" /> 3. <img width="1072" height="150" alt="image" src="https://github.com/user-attachments/assets/4f98ff15-06e4-45d2-a109-c84064cb644b" /> 4. <img width="32" height="289" alt="image" src="https://github.com/user-attachments/assets/9e4ef37f-2e9a-4259-9c6e-041946e1e380" /> 5. <img width="500" height="622" alt="image" src="https://github.com/user-attachments/assets/c4566094-6f58-4692-9ce8-bbcaf61026d7" /> 6. <img width="388" height="644" alt="image" src="https://github.com/user-attachments/assets/03e14424-a59a-4738-b0aa-1f70c7d207f6" /> 7. <img width="388" height="564" alt="image" src="https://github.com/user-attachments/assets/a1acded3-b2d6-4690-b2ba-47397f6a3fb4" /> |
||
|
|
bbd8601c64 |
feat(llm): add annotation queues and datasets (#13719)
## Summary - add annotation queue and dataset storage, management APIs, and review workflows - add discovery, dataset, queue, and review user interfaces - add RBAC synchronization, super-cluster support, tags, version history, and review progress ## Validation - CI should pair this branch with the identically named Enterprise branch for cumulative compilation testing ## Migration note This is an additional cumulative PR created from the committed ud/ebb3 tip. The existing SPR pull requests and branches are intentionally left unchanged. --------- Co-authored-by: sai nikhil kethe <nikhil@openobserve.ai> |
||
|
|
43b531d996 | fix: build warning v2 (#13729) | ||
|
|
b3e6a77270 |
fix(correlation): service-streams P2 behavioral fixes + discovered services flat table (#13710)
Correlation P2 round: behavioral/security fixes across the service-streams backend and correlation FE, plus the Discovered Services UX rework and the correlation e2e suites. **Companion enterprise PR (must merge together):** openobserve/o2-enterprise#2381 — the enterprise side calls the new 3-arg `put(org, record, max_streams_per_type)` introduced here. ## Commit 1 — behavioral fixes (F2–F38) **Backend** - F25/F26: RBAC on `list_services` (`service_streams` GET — the one previously-unenforced endpoint in the module) + validate `distinguish_by` ids on identity-config save - F2: validate trace filter param before WHERE-clause interpolation - F6: `_reset` invalidates caches on all nodes via reload event; org deletion clears service-streams caches - F8: shared coverage-based identity-set ranking for ingest and read - F10: purge rows of removed/changed identity sets on config save - F19: `put` returns deleted orphan keys for cache eviction - F28: discriminate no-match from failure; stop aliasing 404 to no-match - F32: cap DB-side stream union at `max_streams_per_type` - `all_dimensions` unions on put so late-tracked dimensions surface - F14: `StreamInfo.dropped_dimensions` contract field; allow empty `tracked_alias_ids` when identity sets exist **Frontend** - F35/F36/F31: per-stream filter-edit resolution via semantic groups; dimension edits in both key spaces; subject overrides never guess fields - F27/F30: echo `source_stream`/`source_type`; stop guessing another stream's filters; chip dedup - F2/F38: SQL field/value escaping via shared `quoteSqlLiteral` helper ## Commit 2 — Discovered Services UX + e2e - Flat table (one row per instance), same-name services merge their name cell (OTable `pivotRowColumns`); optional per-service collapse with aggregated summary row; search/filters override collapse - Fixes an OTable pivot-merge bug (value-keyed merge map blanked single-column runs) + regression test - Semantic Field Groups: category tabs with counts + cross-category search with match highlighting - Correlation Phase-1 API + Phase-2 UI Playwright suites ## ⚠️ Release note (enterprise + RBAC deployments) Viewing Discovered Services now requires the **Service Streams** permission (previously unenforced). Root/admin users are unaffected; custom roles may need a one-time grant via the role editor (resource already exists in the OFGA model). ## Checks - `cargo fmt --all --check` ✅ · `cargo clippy --all-targets` ✅ enterprise + OSS feature sets (0 warnings) - prettier ✅ · eslint 0 errors · 207 unit tests on touched specs ✅ - Compiles with paired enterprise branch ✅ |
||
|
|
a2f950153e |
fix(logs): pass the expanded row to View Trace (#13722)
#13708 ## Problem Clicking **View Trace** inside an expanded log row on the Logs page does nothing and throws: ``` TypeError: Cannot read properties of undefined (reading '_timestamp') at na (SearchResult.B_xPyti5.js:7:22212) at De (JsonPreview.CX_tRWWx.js:2:9172) ``` The same button in the row-detail drawer works, so the failure reads as intermittent. ## Root cause `JsonPreview` emitted `view-trace` with no payload, while the result grid's expansion slot bound the handler by reference: ```vue <template #expansion="{ row }"> <JsonPreview :value="row" … @view-trace="redirectToTraces" /> </template> ``` `redirectToTraces(log)` then read `log[store.state.zoConfig.timestamp_column]` off `undefined` — and `_timestamp` is that column's default value, which is exactly the reported error. The binding used to work because the table component in between re-emitted the event with the row attached (`emits("view-trace", row)`). That component was removed when the logs result grid migrated from `TenstackTable` to `OTable`, and the payload-less binding was carried over unchanged. The row-detail drawer resolves the hit in its own template, which is why only the inline expansion broke. The correlation drawer's log table (`CorrelatedLogsTable`) had the identical defect — not reported, same fix. ## Fix - `JsonPreview` emits the previewed log with the event, matching its sibling `show-correlation` emit, so every current and future listener receives the record. - Both expansion slots pass `row` explicitly, restoring the pre-migration semantics at the call site. - Both handlers no-op with a warning toast when the record is missing, so a visible, enabled button can never again be a silent dead end during triage. No change to when the button is shown, to the ±15 min window, or to the traces route contract. ## Tests Three regression specs, all failing before the fix with the exact `TypeError` above: - `JsonPreview.spec.ts` — the existing test only asserted *that* `view-trace` fired, never with what; it now asserts the payload, which is why the regression slipped through. - `SearchResult.viewTrace.spec.ts` (new) — expanded row emits a payload-less `view-trace`; asserts navigation to `traceDetails` with the right `trace_id`, `span_id`, and time window. - `CorrelatedLogsTable.viewTrace.spec.ts` (new) — same for the correlation drawer. Both new files are focused specs because neither existing suite installs a router or renders `OTable`'s expansion slot. ``` Test Files 8 passed (8) Tests 316 passed | 3 skipped (319) ``` `npm run type-check` → clean. `eslint` on the touched files → 0 errors. ## Verification Logs page with a trace-id-bearing stream and `service_streams_enabled` off: expand a row inline → **View Trace** lands on the trace with the right id and window. Same from the row-detail drawer and the correlation drawer's log table; console clean in all three. |
||
|
|
bf494ce1de |
fix(synthetics): move check variables into a shared resizable panel (#13699)
## What
Check variables lived inside the **Auth & Network** card on the
Configure page, so an author writing `{{token}}` references into journey
steps could not see them while editing. They now live in a
**`CheckVariablesPanel`** mounted as the right-hand pane on **both**
wizard pages (Journey + Configure), over one source of truth —
`check.variables`, **no schema change**.
## Panel behaviour
- **Cards** — name, masked value for secrets (raw value never rendered),
and a usage count computed from exact `{{name}}` matches across each
step's `value`, `selector`, and locator candidates. The "Used in N
steps" line only appears when the variable is actually referenced.
- **Add / edit** — inline, one form at a time, with the existing
validation rules (`^[A-Za-z_][A-Za-z0-9_]*$`, no duplicates). The add
form appends to the end of the list and scrolls into view; its button
stays pinned below the scroll region so it never scrolls away.
Re-pressing it while the form is open re-scrolls instead of discarding a
half-typed draft.
- **Delete** — confirmed via `ODialog`, and the dialog says what's at
stake: *"baseUrl will be removed from this check. It is referenced by 1
step, which will no longer resolve."* Still backed by the ~6s undo that
restores at the original index.
- **Empty state** — `OEmptyState` whose action is the sole Add
affordance while the list is empty.
- **Layout** — resizable via `OSplitter`; width is shared across both
pages through a new `useCheckWizardUi` composable. The Journey toolbar
gets a collapse toggle beside **Record**, following the field-list
pattern in `logs/SearchResult.vue`.
`CheckAuthNetwork` loses its Variables sub-section; its header summary
is now basic-auth only.
## Two OStepper library fixes this depended on
`OStep` is a multi-root component, so a `class` passed to it was
**silently dropped**. Every `h-full` below it then resolved against an
indefinite height — which left the splitter separator **0px tall and
impossible to grab**. (It predates this branch; step 1 already carried a
no-op `h-full!`.)
- `OStep` now forwards attrs explicitly — onto the **whole step** in
vertical mode, where they used to auto-inherit, and onto the content
panel in horizontal mode.
- `OStepper`'s horizontal pane gets `min-h-0` so a height-constrained
stepper clamps its content instead of growing with it (without it the
Configure separator measured 1818px and the panel was not truly pinned).
Verified the other horizontal-stepper consumers
(`CreateDestinationForm`, `OrgStorageEditor`) and the vertical
`BrowserJourneyStepEditor` are unaffected.
## Testing
**Automated** — 1147 tests pass across `components/synthetics`,
`views/synthetics`, `lib/navigation`, and `composables/synthetics`,
including a new 26-test `CheckVariablesPanel.spec.ts`
(add/edit/validation/masking/usage counts/scroll-to-form/confirm+undo
with fake timers). `type-check:app`, `lint:design:strict`, and ESLint
are clean — ESLint warning count is identical to baseline (0 errors).
**Manual, in the running app** — full flow driven end to end: gate →
journey → add with an invalid name rejected → valid add → splitter drag
(separator now 467px tall, drag moves it) → collapse/reopen preserving
the dragged width → step referencing `{{baseUrl}}` flipping the usage
badge to 1 → delete confirmation warning about the broken step → cancel
keeps it → confirm + undo restores it → Configure page showing the same
panel at the same width with the Auth & Network card carrying no
Variables section.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||
|
|
a338597481 |
fix(lib): re-place toggle pill after an item reorder (#13721)
The sliding selection pill in OToggleGroup was re-measured only on a modelValue change or a track resize. A drag-to-reorder moves the active item but leaves the track exactly the same size, so neither trigger fired: the pill kept the previous item's position and width, landing under the wrong item and overlapping its neighbour, while the active text colour — being data-state driven — correctly followed the moved item. On the traces detail tab bar that read as the highlight and the colour coming apart. Observe the track's childList and snap-measure on a change, mirroring OTabs, which already did this for its underline. Attributes are deliberately not observed: data-state flips on a real selection change, which the modelValue watcher handles with a slide, and snapping there would cancel it. Also covers items being added or removed, e.g. the traces Thread tab appearing for a trace with LLM spans. |
||
|
|
087e1498ab |
feat(slos): add SLO burn-rate alerts (#13704)
design at /slo ## What Adds **SLO burn-rate alerts** — an alert family that fires off an SLO's error budget rather than a raw query — and finishes the SLO surface around it: navigation entry, detail-page fixes, and the flag removal now that SLOs have shipped. ## Changes **SLO burn-rate alerts (backend)** - New burn-rate evaluation (`config/src/meta/slo/burn.rs`, `condition.rs`) with multi-window burn conditions, and `core/src/slo/evaluate.rs` extended to evaluate them on the SLO job. - Alerts carry an `slo_id`; `infra/src/table/alerts` gains the column, filtering, and query support so an SLO's alerts can be listed and deleted with it. - Alert levels (`meta/alerts/level.rs`) and tags extended for the SLO family; scheduler handlers route SLO alerts through the same notification path. **SLO alert UI** - `SloAlertForm` + `AlertDetailSlo`: create, edit and view burn-rate alerts from the SLO detail page and the alert list. - Payload/routing helpers (`utils/alerts/sloAlertPayload.ts`, `sloAlertRouting.ts`, `alertPayload.ts`) with unit tests. - `AlertDestinationsField` extracted as the complete Destination form field — side label, tooltip, combined destinations/workflows picker, inline error, refresh, and create-in-new-tab. It replaces two verbatim copies in the generic alert form and is reused by the SLO form and synthetics `CheckAlerts` (which sets `supportsWorkflows: false`, since a check has no workflow routing). Fixes the SLO form's previously unwired refresh and Add Destination buttons. **SLO detail page fixes** - Burndown and burn-rate charts drew as bare axes when coverage was sparse: `showSymbol: false` means an isolated measured bucket between gaps has no segment and paints nothing. Symbols are now sized per point, and a sparse-coverage note states how many buckets actually recorded events. - Nothing scrolled below ~700px of viewport height — `OPageLayout`'s fixed flex body plus `OTabPanels` `scroll="none"` clipped the panels. Panels now grow and scroll; the stat strip and tab bar stay pinned. Verified at 1024x500, 1280x620, 1512x945. **Other** - `ZO_SLO_ENABLED` removed — SLOs have shipped, so the flag and its status/route gating are gone. - SLOs surfaced in the main nav. - Dashboard chart panel header gets its own tint via new `--color-panel-bar-bg` / `--color-panel-bar-border` tokens, and the bar is extracted into `PanelBar.vue` (it existed as five hand-copied class strings that had already drifted). - `tsconfig.vitest.tsbuildinfo` untracked; third-party vendor name removed from comments and test names. ## Testing - New Rust tests across `meta/slo/burn.rs`, `condition.rs`, `core/src/alerts/alert.rs` and `infra/src/table/alerts`. - New frontend suites: `sloAlertPayload.spec.ts`, `sloAlertRouting.spec.ts`, `alertPayload.spec.ts`, `AlertDetailSlo.spec.ts`, `SloDetailAlerts.spec.ts`, `SloListDelete.spec.ts`, `SloTimeSlicePreview.spec.ts`. - `cargo clippy --all-targets` and `web` `lint:ci` clean. |
||
|
|
d93d599918 |
chore: update translations from en-US.json (#13694)
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: ktx-vaidehi <vaidehi.akhani@kiara.tech> |
||
|
|
dd5ff2c131 |
feat(iam): serve the MCP Server setup page on the OSS build (#13720)
## Summary IAM > MCP Server was gated to enterprise/cloud, but the endpoint it documents is not. The backend registers api-endpoint outside the ent block and it initialises the MCP tools "for all editions" — only the OAuth *discovery* endpoints are enterprise-only. OSS users could reach the MCP server, just not the page that tells them how. Removes the build/runtime gates so the page ships everywhere, and hides the one part that genuinely is enterprise-only. ### Gates removed - `useEnterpriseRoutes.ts`: the `mcpServer` child was pushed inside the `isCloud || isEnterprise` branch, so on OSS the route did not exist at all. Moved into the base `children` array. - `IdentityAccessManagement.vue`: the tab's `visible` was `isEnt && zoConfig.ai_enabled`. Dropped. `ai_enabled` is `enterprise_value!(false, o2cfg.ai.enabled)`, i.e. always false on OSS, so that condition could never have let the tab through. - `useIngestionRoutes.ts` / `Recommended.vue`: the Ingestion > Recommended cross-link carried the same gate, explicitly to match where `mcpServer` existed. Un-gated to stay consistent. ### Card corrections - Drop the "MCP server is an Enterprise feature." note and delete the now-dead `ingestion.mcp.enterpriseNote` key from all 15 locale files. - OAuth *is* enterprise-only: `oauth_authorization_server_metadata` and `oauth_protected_resource_metadata` are `cfg(not(enterprise))` 404 stubs. The OAuth tab is now hidden on OSS and `authMode` defaults to `token`, rather than landing users on a flow that cannot complete. With one method left the tab picker is hidden too. The token path works unchanged on OSS: the snippets authenticate with `Basic base64(email:passcode)`. "Generate read-only credential" stays hidden there — `useMcpCredential` requires `rbac_enabled` to attach the read-only role — which degrades cleanly to the quick-start passcode and produces identical snippets. ### Tests Updated the OSS IAM child-count assertion (5 -> 6), the only test the change broke. Added OSS-presence coverage in `useEnterpriseRoutes.spec`, `useIngestionRoutes.spec`, `IdentityAccessManagement.spec` (with `ai_enabled` off) and `Recommended.spec`. Verified with `format:check`, `verify` (type-check:app + 5 lint gates, 0 errors) and 457 tests across the 7 affected specs. Refs #13717 |
||
|
|
e1aad76283 |
fix(dashboards): use bookmark-add for the panel annotation button (#13718)
The panel header's Add Annotation toggle rendered the same 'edit' glyph that the kebab menu uses for Edit Panel, so one shape stood for two unrelated actions on the same panel. Annotations are markLines pinned to a point on the x-axis, which bookmark-add states without borrowing the pencil. |
||
|
|
9cf4933f15 | fix: Browser sdk test 0.4.2 (#13584) | ||
|
|
62528b4c12 |
fix(synthetics): sequential recorder setup checklist with state-safe refresh and incognito failure recovery (#13684)
## Summary Follow-up to #13658 — redesigns the recorder setup flow as a sequential-gated checklist and closes the UX holes around refresh, stale connections, and incognito failures. ### Sequential-gated setup checklist (shared by the create-page setup phase and the journey dialog) - Only one task is actionable at a time; later tasks render locked, done tasks collapse to a green check row. - **Task 1 (install)**: Web Store button + an "I've added it to Chrome" attestation (the install happens in another tab the page can't observe). Live bridge detection auto-completes it ("Detected automatically"); checkbox-only completion offers Undo. - **Task 2 (incognito)**: "Do this in Chrome" callout with inline Chrome-UI icons + first-person attestation, collapsing to "Allowed in Incognito" with Undo. - **Task 3 (connect)**: completes only on the real probe signal — attestations can't skip into a recording that would hang. Icon-click is the primary instruction (injects without reloading); refresh is the secondary link. - Journey dialog: per-action subtitle, "n of 3 done" badge, full-width CTA reading "<action> — finish the tasks above first" while locked, a hint naming the exact blocking task, skip link (record only). - Attestations are session-only by design — persisting them would keep tasks pre-completed after the extension is removed. ### State-safe refresh + gate bypass - Entering the setup phase mirrors url/name into the query (`setup=1`); mount restores them, so a mid-setup F5 returns to the checklist with fields intact. - The checklist's "refresh this page" strips the setup flag; when url+name are present and the warm probe detects the extension, the gate auto-commits straight into the editor (recording stays a deliberate click). `?url=&name=` deep links work as a byproduct. ### Incognito failure recovery - Both the replay preflight classification and the recording-start refusal (the extension's raw "Recording needs incognito access…" message) now revoke the disproved attestation and auto-open the setup dialog on its incognito task, with the failed action as the CTA. The warning card slims to Retry / Dismiss / Show setup steps (its chrome://extensions walkthrough duplicated the checklist, and `window.open("chrome://…")` is blocked by Chrome anyway). ### Compulsory re-verification after the incognito toggle - Toggling "Allow in Incognito" **reloads the extension and orphans the tab's bridge** (per the takeover-handshake contract in the extension's content script), so giving the ack invalidates `extensionReady` and re-probes — the connect task stays open until a fresh probe passes. The install fact is latched first so task 1 doesn't regress. ## Test plan - 141 tests across the four specs: ExtensionSetupChecklist 18, ExtensionSetupDialog 19, BrowserJourney 60, CreateBrowserTest 44 — including the deferred-probe assertions that the CTA follows the *fresh* probe verdict, not stale state - `npm run lint` / `npm run type-check` / `npm run lint:design:strict` clean - Manual: full install → incognito → connect flow against the published extension, both failure paths (record + replay without incognito), refresh at each task |
||
|
|
4d23d85fcb | fix(i18n): improve Simplified Chinese translations (#13707) | ||
|
|
f0e12bb913 |
fix(traces): scope "View Logs" correlated query to the clicked span (#13700)
## Problem In enterprise, the span sidebar's **View Logs** goes through `navigateToCorrelatedLogs()`, which built its WHERE clause purely from the per-stream `filters` returned by `_correlate`. The result was a service/namespace-wide log query with no reference to the span the user actually clicked. The OSS path (`buildQueryDetails`) pins both `span_id` and `trace_id`. The enterprise path did not. ## Change Append `span_id` and `trace_id` conditions in `navigateToCorrelatedLogs()`: - **Field names** from the org's `span_id_field_name` / `trace_id_field_name` settings - **Values** from `searchObj.data.traceDetails.selectedSpanId` and `selectedTrace?.trace_id` — the same sources `buildQueryDetails` reads, and `selectedSpanId` is what drives the sidebar's `:span` prop, so it always matches the clicked span - Each condition is missing-value guarded and routed through the existing semantic-group keying, so an id field that is also a tracked dimension yields one condition rather than two — with the exact id winning over a stream's alias ## Deduplication The new code would otherwise have been a third copy of logic already present twice, so: - Extracted `getSpanIdField()` / `getTraceIdField()`; `buildQueryDetails` and `navigateToCorrelatedLogs` now share them. This also fixes a latent bug — `buildQueryDetails` did `String(spanIdField)` with no fallback, emitting a column literally named `undefined` when the org setting was absent. Defaults now mirror `stores/index.ts`. - Extracted `groupIdFor()` / `setCondition()` so the stream-filter loop and the id loop share one implementation. - Dropped the `usedGroups` Set — every `add()` was paired with a `conditions.set()` on the same key, making `usedGroups.has(x)` always equivalent to `conditions.has(x)`. - Replaced the hand-rolled `String(v).replace(/'/g, "''")` with `quoteSqlLiteral()` from `utils/telemetryCorrelation` (byte-identical output). Deliberately *not* `buildSqlCondition()` — it wraps identifiers via `quoteSqlIdentifier` (always quotes), which would change emitted SQL from `field = 'v'` to `"field" = 'v'`. |
||
|
|
8303be0b4c |
refactor: rename AlertManager node role to Scheduler (#13696)
## Summary - rename the `AlertManager` node role to `Scheduler` across Rust services, jobs, protobuf bindings, UI labels, and tests - emit `scheduler` as the canonical role name - continue accepting legacy `alertmanager` and `alert_manager` configuration values - keep protobuf enum value `5` unchanged for wire compatibility ## Why The role schedules and executes alerts, reports, pipelines, synthetics, and other background work. `Scheduler` describes that broader responsibility more accurately. ## Compatibility - existing role configuration values remain accepted through parser and serde aliases - the protobuf numeric value remains stable - coordinated changes are included in the Enterprise, Helm chart, and documentation repositories ## Verification - `cargo test -p config test_role` - `cargo test -p openobserve-node` - `cargo check -p openobserve-jobs` - targeted web tests: 307 passed, 13 skipped - Rust formatting and targeted Prettier checks |
||
|
|
735dc7d58d |
feat(traces): restore in-page Service Graph / Service Catalog tabs alongside standalone routes (#13698)
## What #13659 converted Service Graph and Services Catalog from in-page tabs on the Traces page into standalone routes reached from the nav-rail flyout. This PR restores the in-page tabs as a **second access path** — both now coexist, with distinct semantics: | Path | Semantics | |---|---| | Toolbar tabs on `/traces` | In-page view switch (`?tab=service-graph` / `?tab=services-catalog`), shares the page's stream + time context — the pre-#13659 UX, including old `?tab=` bookmarks | | Nav-rail flyout | Navigates to the standalone routes `/traces/service-graph`, `/traces/services` — unchanged from #13659 | Both paths render the same inner components (`ServiceGraph.vue`, `ServicesCatalog.vue`); only toolbar chrome differs. ## How A guided **reverse-apply of #13659's diff to `Index.vue` + `SearchBar.vue` only** (verified byte-identical to the pre-PR files — both were untouched on main since), with four deliberate adaptations: - **Re-added `applyHandoffFilter`** + its two hook call sites, which the revert would have deleted — the standalone pages' "View Traces" handoff (`?filter=` landing) depends on it. Covered by a new unit regression test and verified live. - The restored in-page `view-traces` handlers call `viewTracesHandoff.ts` (`buildViewTracesFilter` / `normalizeViewTracesPayload`) instead of resurrecting the inline filter builders that #13659 extracted from them — no re-duplication. - **Fixed a latent pre-#13659 bug**: the graph tab's refresh button called `serviceGraphRef?.loadServiceGraph()`, which was never in `ServiceGraph.vue`'s `expose()` — now `refresh()`. - **Flyout highlight now follows the visible view** on both paths: new `SubnavChild.activeOnTab` alias marks the Service Graph / Service Catalog flyout items active when `/traces?tab=…` shows their view in-page. Previously the same view highlighted different flyout items depending on how you reached it — the only submenu that deviated. Also: - Renamed the "Services" submenu / page header / route title to **"Service Catalog"**, matching the toolbar tab label (single `menu.services` locale value covers all). - `global-setup.js` login verification moved to `navbar-main-nav` — the same stale-selector fix #13659 applied to `enhanced-baseFixtures.js`; suites fail setup on main without it. ## Tests | Suite | Result | |---|---| | Unit: `SearchBar` 69, `Index` 76, `ONavGroup` 18 (5 new `activeOnTab` cases), `viewTracesHandoff` 21, `navGroups` 28 | all pass (233 total, 2 pre-existing skips) | | E2E (new) `Traces/traces-toolbar-tabs.spec.js` — in-page tab switches, shared-datetime carry, `?tab=` bookmark reload, flyout→standalone-route coexistence | 4/4 vs live enterprise build | | E2E `Traces/service-catalog.spec.js` (standalone-route regression) | 18 pass | | `type-check`, `eslint` (0 errors), `prettier`, `lint:design:strict` | clean | Not run: `Traces/service-graph.spec.js` — its `beforeAll` ingests via `ZO_BASE_URL`, which requires a single-origin instance (CI); the dev vite+backend split can't satisfy it. Nothing in this PR touches `ServiceGraph.vue` or the standalone views. ## Notes for review - `Index.vue` / `SearchBar.vue` restored regions are intentionally verbatim pre-#13659 (including its 16 pre-existing lint *warnings*) — deviations are limited to the four adaptations above, so the diff-vs-pre-PR is auditable. - Two known-inert quirks restored deliberately, not bugs to fix here: `hide-splitter-separator` has no CSS rule (was a no-op pre-#13659 too), and `@update:activeTab` writes to a getter-only computed. --------- Co-authored-by: Shrinath Rao <shnath@openobserve.ai> |
||
|
|
47d510aa16 |
feat: rebuild the RUM error detail page around issue impact (#13697)
Design at: designs/mobile-rum-sdk-evaluation/design-docs The page showed a single error event: header, tag strip, stack trace, replay button, event list. It could not say how bad the error was, who it reached, whether it was new, or where it concentrated — it never queried anything beyond that one row. It is now a two-column triage surface: the diagnosis path (occurrences chart, stack trace, breadcrumbs) on the left, corroborating evidence (replay, backend trace, breakdown, who hit it) on the right. - ErrorHeader: error type as the title with handling/source badges, the message in an alert banner, and a context line carrying event id, route and the service/version/env chips. Copy-permalink and copy-event-id actions. - ErrorImpactStrip: occurrences, users, sessions, first/last seen. A dash, not a zero, when a figure is unavailable. - ErrorOccurrencesChart: this signature over time, marking the bucket that holds the event the page was opened on. - ErrorFacetBreakdown: browser / OS / release / page as share-of-occurrences bars, calling out any value that owns 80%+ of the traffic — usually the fix. - ErrorContextCard: identity, device, geo and deployment for this occurrence. Supersedes ErrorTags, which is removed. Backed by useErrorDetail + errorDetailQueries: an impact aggregate gates a histogram and two facet group-bys. Three searches, staged inside the server's work-group cap and aborted when the view is left. Facets are split across two group-bys on purpose — one query over all four columns returns their cross product. Also fixes the breadcrumb trail: it read an hour of the whole stream with no session filter, so "what the user did before the crash" could be other people's clicks. It is now scoped to the session id. |
||
|
|
6c43e01823 | fix: px to rem (#13541) | ||
|
|
eb2ab67f5a | fix: dashboard table column formatting via column header (#13695) | ||
|
|
74805cf8ae |
chore(deps): update web npm dependencies (2026-08-06) (#13673)
## 📦 Weekly NPM Dependencies Update This automated PR updates `web/` npm packages to their latest versions and regenerates `package-lock.json`. ### Updated Packages - **@rudderstack/analytics-js**: 3.6.0 → 3.31.6 - **@tanstack/vue-form**: ^1.29.1 → ^1.33.3 - **@tanstack/vue-table**: ^8.21.3 → ^9.0.0 - **@tanstack/vue-virtual**: ^3.13.16 → ^3.13.35 - **@vue-flow/core**: ^1.48.1 → ^1.48.2 - **acorn**: ^8.15.0 → ^8.18.0 - **acorn-walk**: ^8.3.4 → ^8.3.5 - **cron-parser**: ^5.4.0 → ^5.7.0 - **date-fns**: ^4.1.0 → ^4.4.0 - **dompurify**: ^3.4.12 → ^3.4.13 - **gridstack**: ^12.4.2 → ^13.0.2 - **js-beautify**: ^1.15.4 → ^2.0.3 - **js-cookie**: ^3.0.7 → ^3.0.8 - **js-yaml**: ^4.3.0 → ^5.2.3 - **lucide-vue-next**: ^0.562.0 → ^1.0.0 - **marked**: ^17.0.1 → ^18.0.9 - **moment-timezone**: ^0.6.0 → ^0.6.3 - **monaco-editor**: ^0.52.2 → ^0.56.0 - **node-polyfill-webpack-plugin**: ^4.0.0 → ^4.1.0 - **reka-ui**: ^2.9.6 → ^2.10.1 - **reodotdev**: ^1.0.0 → ^1.1.0 - **sql-formatter**: ^15.6.12 → ^15.8.2 - **uuid**: ^14.0.0 → ^14.0.1 - **vue**: ^3.5.26 → ^3.5.41 - **vue-i18n**: ^11.2.8 → ^11.4.8 - **vue-router**: ^4.6.4 → ^5.2.0 - **@cypress/vue**: ^6.0.2 → ^6.0.3 - **@cypress/webpack-dev-server**: ^5.4.1 → ^5.6.2 - **@iconify-json/majesticons**: ^1.2.4 → ^1.2.5 - **@iconify-json/material-symbols**: ^1.2.72 → ^1.2.88 - **@iconify-json/octicon**: ^1.2.25 → ^1.2.31 - **@intlify/core-base**: ^11.2.8 → ^11.4.8 - **@rushstack/eslint-patch**: ^1.15.0 → ^1.16.1 - **@tailwindcss/postcss**: ^4.1.18 → ^4.3.3 - **@tailwindcss/typography**: ^0.5.19 → ^0.5.20 - **@tailwindcss/vite**: ^4.1.18 → ^4.3.3 - **@types/jsdom**: ^27.0.0 → ^28.0.3 - **@types/leaflet**: ^1.9.21 → ^1.9.22 - **@types/luxon**: ^3.7.1 → ^3.7.3 - **@types/node**: ^25.0.3 → ^26.1.2 - **@vitejs/plugin-vue**: ^6.0.3 → ^6.0.8 - **@vitejs/plugin-vue-jsx**: ^5.1.3 → ^5.1.6 - **@vitest/coverage-v8**: ^4.0.16 → ^4.1.10 - **@vitest/ui**: ^4.0.16 → ^4.1.10 - **@vue/eslint-config-typescript**: ^14.6.0 → ^14.9.0 - **@vue/test-utils**: ^2.4.6 → ^2.4.11 - **@vue/tsconfig**: ^0.8.1 → ^0.9.1 - **autoprefixer**: ^10.4.23 → ^10.5.4 - **c8**: ^10.1.3 → ^12.0.0 - **cypress**: ^15.19.0 → ^15.20.0 - **cypress-localstorage-commands**: ^2.2.8 → ^2.3.0 - **dotenv**: ^17.2.3 → ^17.4.2 - **eslint**: ^9.39.2 → ^10.8.0 - **eslint-plugin-cypress**: ^5.2.0 → ^7.0.0 - **eslint-plugin-vue**: ^10.6.2 → ^10.10.0 - **fs-extra**: ^11.3.3 → ^11.4.0 - **happy-dom**: ^20.8.9 → ^20.11.1 - **jsdom**: ^27.4.0 → ^30.0.1 - **msw**: ^2.12.7 → ^2.15.0 - **postcss**: ^8.5.10 → ^8.5.26 - **postcss-html**: ^1.8.1 → ^2.0.0 - **prettier**: ^3.7.4 → ^3.9.6 - **rollup-plugin-visualizer**: ^6.0.5 → ^7.0.1 - **sass**: ^1.97.1 → ^1.102.0 - **sass-loader**: ^16.0.6 → ^17.0.0 - **start-server-and-test**: ^2.1.3 → ^3.0.12 - **stylelint**: ^17.14.0 → ^17.14.1 - **vite**: ^7.3.2 → ^8.2.0 - **vite-plugin-istanbul**: ^7.2.1 → ^9.0.1 - **vitest-canvas-mock**: ^1.1.3 → ^1.1.4 - **vue-tsc**: ^3.2.1 → ^3.3.9 - **typescript**: ~5.9.3 → ~7.0.2 - **vitest**: ^4.0.16 → ^4.1.10 ### Validation This workflow does **not** run any checks — type check, unit tests and build all run as normal PR checks below. Review the results there before merging; a red check usually means one of the upgrades above needs to be pinned back or accompanied by a code change. --- 🤖 This PR was automatically created by the Weekly NPM Update workflow --------- Co-authored-by: Bhargav <551527+bjp232004@users.noreply.github.com> Co-authored-by: Bhargav <BJP232004@GMAIL.COM> Co-authored-by: ktx-abhay <abhay.padamani@kiara.tech> Co-authored-by: Abhay Padamani <141122205+ktx-abhay@users.noreply.github.com> |
||
|
|
79fbd566b3 | fix: ai page improvements (#13689) | ||
|
|
e420432f2c |
chore: bundle the SIL OFL 1.1 license for the vendored Geist fonts (#13691)
Geist and Geist Mono are vendored under web/src/styles/fonts/ and, like
the rest of web/dist, are compiled into the binary by rust-embed. Both
are licensed under the SIL Open Font License 1.1, which requires the
copyright notice and license text to be redistributed with the fonts.
Neither was present.
- OFL.txt, copied verbatim from vercel/geist-font, next to the .woff2
files.
- A font-license Vite plugin copying it to dist/fonts/OFL.txt, since
Vite only emits assets something imports and the license has to reach
the binary too.
- README.md recording family, version, upstream and how to re-vendor.
DejaVu Sans (src/core/src/alerts/notifications/chart/font/) already
ships its license and needs no change.
Also drops the fonts.googleapis.com / fonts.gstatic.com allowances from
the serve.json CSP and its commented twin in vite.config.ts — dead since
|
||
|
|
93cfbee117 |
fix: Issue ent 2343 alert improvements v3 (#13670)
Co-authored-by: ktx-akshay <akshay.patil@kiara.tech> |
||
|
|
d18f21e51f | fix: update enterprise feature (#13679) | ||
|
|
4887d67214 |
chore(deps): bump fast-uri from 3.1.2 to 3.1.5 in /web (#13611)
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.2 to 3.1.5. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/fastify/fast-uri/releases">fast-uri's releases</a>.</em></p> <blockquote> <h2>v3.1.5</h2> <h2>⚠️ Security Warning</h2> <p>Fix for <a href="https://github.com/fastify/fast-uri/security/advisories/GHSA-7p8r-x3mc-p8w7">https://github.com/fastify/fast-uri/security/advisories/GHSA-7p8r-x3mc-p8w7</a></p> <p><strong>Full Changelog</strong>: <a href="https://github.com/fastify/fast-uri/compare/v3.1.4...v3.1.5">https://github.com/fastify/fast-uri/compare/v3.1.4...v3.1.5</a></p> <h2>v3.1.4</h2> <h2>⚠️ Security Release</h2> <p>Fix for <a href="https://github.com/fastify/fast-uri/security/advisories/GHSA-v2hh-gcrm-f6hx">https://github.com/fastify/fast-uri/security/advisories/GHSA-v2hh-gcrm-f6hx</a></p> <p><strong>Full Changelog</strong>: <a href="https://github.com/fastify/fast-uri/compare/v3.1.3...v3.1.4">https://github.com/fastify/fast-uri/compare/v3.1.3...v3.1.4</a></p> <h2>v3.1.3</h2> <h2>⚠️ Security Release</h2> <ul> <li>Fixes: <a href="https://github.com/fastify/fast-uri/security/advisories/GHSA-4c8g-83qw-93j6">https://github.com/fastify/fast-uri/security/advisories/GHSA-4c8g-83qw-93j6</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/fastify/fast-uri/compare/v3.1.2...v3.1.3">https://github.com/fastify/fast-uri/compare/v3.1.2...v3.1.3</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/fastify/fast-uri/commit/5e179cbb4636d5f773ed21126e5bd3068e87e94e"><code>5e179cb</code></a> Bumped v3.1.5</li> <li><a href="https://github.com/fastify/fast-uri/commit/2cad02d6ed428a720499bb7a3c3d6c3d41f10f5a"><code>2cad02d</code></a> Merge commit from fork</li> <li><a href="https://github.com/fastify/fast-uri/commit/6aeece669e4166b2446a89f17c07a3b15dfb7ed4"><code>6aeece6</code></a> Bumped v3.1.4</li> <li><a href="https://github.com/fastify/fast-uri/commit/2d50fbabc80e4d0884fe0f6a98fe118ce6faa353"><code>2d50fba</code></a> fix: reject literal backslash in URI authority</li> <li><a href="https://github.com/fastify/fast-uri/commit/0549fe35b0d482233f3be2816439f3ec803603fa"><code>0549fe3</code></a> Bumped v3.1.3</li> <li><a href="https://github.com/fastify/fast-uri/commit/2a6d357a18a68e6d812824379fd3388a1ae50d05"><code>2a6d357</code></a> Merge commit from fork</li> <li>See full diff in <a href="https://github.com/fastify/fast-uri/compare/v3.1.2...v3.1.5">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com> |
||
|
|
739054c7bd |
feat: metric chart improvement (#13546)
Design At: designs/dashboards/metric-chart-override-support/ 1. For metric chart conditional text color, background color, value override support. 2. sparkline for metric chart. --------- Co-authored-by: ktx-akshay <akshay.patil@kiara.tech> |
||
|
|
88051c7ec1 |
chore(deps): bump js-yaml from 4.3.0 to 4.3.1 in /web (#13678)
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.3.0 to 4.3.1. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/nodeca/js-yaml/blob/4.3.1/CHANGELOG.md">js-yaml's changelog</a>.</em></p> <blockquote> <h2>4.3.1 - 2026-07-31</h2> <h3>Security</h3> <ul> <li>[backport] Remove quadratic complexity from <code>!!omap</code> duplicate key detection.</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/nodeca/js-yaml/commit/86e91b815b8794c3c73a179c1770871e37ec2df8"><code>86e91b8</code></a> 4.3.1 released</li> <li><a href="https://github.com/nodeca/js-yaml/commit/c3cc4b0bb9ddb9af2dd9b61e0d56f5ce7983cd4a"><code>c3cc4b0</code></a> Backport quadratic complexity fix for !!omap</li> <li>See full diff in <a href="https://github.com/nodeca/js-yaml/compare/4.3.0...4.3.1">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) 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> Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com> |