Compare commits

...

2 Commits

Author SHA1 Message Date
nityanandagohain
20f3e78f1d fix: add ai_observability to saved views 2026-08-24 23:22:52 +05:30
Vinicius Lourenço
9997c3da9c chore(packages): bump @signozhq/ui to 0.1.0 (#12634)
Some checks failed
build-staging / prepare (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
cacheci / tests (push) Has been cancelled
build-staging / js-build (push) Has been cancelled
build-staging / go-build (push) Has been cancelled
build-staging / staging (push) Has been cancelled
<!--A few plain bullets saying what changed and why, for a reviewer
skimming it - not a wall of text, not a restatement of the diff, not
generated boilerplate.-->
#### Description

This bumps the version from 0.2.3 to 0.1.0 (which also requires the bump
in the design-token to latest version), the changes can be found at
https://github.com/SigNoz/components/releases/tag/v0.1.0

<!--Reference issues using `Closes #issue-number` to enable automatic
closure on merge. -->
#### Issues closed by this PR

Closes https://github.com/SigNoz/engineering-pod/issues/5926

<!--If applicable, include screenshots or screen recordings that clearly
show the behavior before the change and the result after the change. -->
#### Screenshots / Screen Recordings

The main diffs is the breaking changes in the vars names, other than
that, we mainly added new features for the components instead of
changing their look/usage, so we can expect no breaking-change in the
behavior or UI.

About Triggered Alerts (with new rewrite version of combobox simple).


https://github.com/user-attachments/assets/18cb117b-9a24-428e-8f6b-7dbf5012f7ea

The combobox also now emits `undefined` in case you have `allowClear`
enabled, this does not affect existing usages:


https://github.com/user-attachments/assets/70ca146f-0145-46d7-bf51-57f93b973ce4
2026-08-21 14:09:48 +00:00
20 changed files with 611 additions and 385 deletions

View File

@@ -8010,6 +8010,7 @@ components:
- logs
- metrics
- meter
- ai_observability
type: string
SavedviewtypesUpdatableSavedView:
properties:

View File

@@ -62,6 +62,40 @@ if (typeof window.ResizeObserver === 'undefined') {
(window as any).ResizeObserver = ResizeObserverMock;
}
if (typeof globalThis.DOMRect === 'undefined') {
(globalThis as any).DOMRect = class DOMRect {
x = 0;
y = 0;
width = 0;
height = 0;
top = 0;
right = 0;
bottom = 0;
left = 0;
constructor(x = 0, y = 0, width = 0, height = 0) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.top = y;
this.right = x + width;
this.bottom = y + height;
this.left = x;
}
toJSON(): any {
return { x: this.x, y: this.y, width: this.width, height: this.height };
}
static fromRect(rect?: {
x?: number;
y?: number;
width?: number;
height?: number;
}): DOMRect {
return new DOMRect(rect?.x, rect?.y, rect?.width, rect?.height);
}
};
}
// Patch getComputedStyle to handle CSS parsing errors from @signozhq/* packages.
// These packages inject CSS at import time via style-inject / vite-plugin-css-injected-by-js.
// jsdom's nwsapi cannot parse some of the injected selectors (e.g. Tailwind's :animate-in),

View File

@@ -48,9 +48,9 @@
"@monaco-editor/react": "^4.7.0",
"@sentry/react": "10.57.0",
"@sentry/vite-plugin": "5.3.0",
"@signozhq/design-tokens": "2.1.4",
"@signozhq/design-tokens": "2.1.6",
"@signozhq/icons": "0.4.0",
"@signozhq/ui": "0.0.23",
"@signozhq/ui": "0.1.0",
"@tanstack/react-table": "8.21.3",
"@tanstack/react-virtual": "3.13.22",
"@uiw/codemirror-theme-copilot": "4.23.11",
@@ -238,4 +238,4 @@
"tmp@<0.2.6": ">=0.2.6 <0.3.0",
"yaml@>=1.0.0 <1.10.3": ">=1.10.3 <2"
}
}
}

823
frontend/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -9021,6 +9021,7 @@ export enum SavedviewtypesSourceDTO {
logs = 'logs',
metrics = 'metrics',
meter = 'meter',
ai_observability = 'ai_observability',
}
export interface SavedviewtypesSavedViewSpecDTO {
display?: SavedviewtypesDisplayDTO;

View File

@@ -664,6 +664,7 @@ function TanStackTableInner<TData, TItemKey = string>(
value={limit?.toString()}
defaultValue="10"
onChange={(value): void => {
value ??= '10';
setLimit(+value);
pagination.onLimitChange?.(+value);
if (page !== 1) {

View File

@@ -4,9 +4,9 @@
gap: var(--spacing-4);
padding: var(--spacing-2) var(--spacing-2);
--tab-content-padding: 0;
--tab-text-color: var(--l1-foreground);
--tab-active-text-color: var(--l1-foreground);
--tabs-content-padding: 0;
--tabs-text-color: var(--l1-foreground);
--tabs-active-text-color: var(--l1-foreground);
}
.pageError {

View File

@@ -4,8 +4,8 @@
height: 100%;
margin-top: var(--spacing-2);
margin-left: var(--spacing-2);
--tab-text-color: var(--l1-foreground);
--tab-active-text-color: var(--l1-foreground);
--tabs-text-color: var(--l1-foreground);
--tabs-active-text-color: var(--l1-foreground);
[role='tabpanel'] {
margin: 0;
padding: var(--spacing-0) var(--spacing-4);

View File

@@ -2,10 +2,10 @@
display: flex;
flex-direction: column;
gap: var(--spacing-8);
--tab-content-padding: 0;
--tabs-content-padding: 0;
margin-top: var(--spacing-3);
--tab-text-color: var(--l1-foreground);
--tab-active-text-color: var(--l1-foreground);
--tabs-text-color: var(--l1-foreground);
--tabs-active-text-color: var(--l1-foreground);
}
.tabLabel {

View File

@@ -6,8 +6,8 @@
}
// Remove default tab content padding/margin — the card provides spacing.
--tab-content-padding: 0;
--tab-content-margin: var(--spacing-4) 0 0;
--tabs-content-padding: 0;
--tabs-content-margin: var(--spacing-4) 0 0;
}
.mcp-client-tabs {

View File

@@ -35,7 +35,7 @@ exports[`Value panel wrappper tests should render tooltip when there are conflic
class="c0"
>
<p
class="_typography_ulrzs_1"
class="_typography_j4pmm_1"
data-slot="typography"
data-variant="text"
/>
@@ -50,7 +50,7 @@ exports[`Value panel wrappper tests should render tooltip when there are conflic
class="value-text-container"
>
<p
class="_typography_ulrzs_1 value-graph-text"
class="_typography_j4pmm_1 value-graph-text"
data-slot="typography"
data-testid="value-graph-text"
data-variant="text"
@@ -59,7 +59,7 @@ exports[`Value panel wrappper tests should render tooltip when there are conflic
295.43
</p>
<p
class="_typography_ulrzs_1 value-graph-unit"
class="_typography_j4pmm_1 value-graph-unit"
data-slot="typography"
data-testid="value-graph-suffix-unit"
data-variant="text"

View File

@@ -22,11 +22,11 @@ exports[`PipelinePage container test should render DragAction section 1`] = `
class="c0"
>
<div
class="_switch-wrapper_jbsv7_1"
class="_switch-wrapper_1a8sn_6"
>
<button
aria-checked="true"
class="_switch_jbsv7_1"
class="_switch_1a8sn_6"
data-color="robin"
data-state="checked"
id=":r0:"
@@ -35,7 +35,7 @@ exports[`PipelinePage container test should render DragAction section 1`] = `
value="on"
>
<span
class="_switch__thumb_jbsv7_59"
class="_switch__thumb_1a8sn_71"
data-state="checked"
/>
</button>

View File

@@ -74,7 +74,7 @@ exports[`PipelinePage container test should render PipelinePageLayout section 1`
/>
<div>
<p
class="_typography_ulrzs_1"
class="_typography_j4pmm_1"
data-slot="typography"
data-variant="text"
>

View File

@@ -105,7 +105,7 @@
flex-direction: column;
flex: 1;
min-height: 0;
--tab-content-padding: 0px;
--tabs-content-padding: 0px;
[role='tabpanel'] {
display: flex;

View File

@@ -35,7 +35,7 @@
}
.filterSelect {
min-width: 300px;
min-width: 400px;
flex: 1;
}
@@ -57,8 +57,6 @@
--tanstack-cell-padding-top-override: 5px;
--tanstack-cell-padding-bottom-override: 5px;
--tanstack-cell-padding-left-override: 5px;
--tanstack-cell-padding-right-override: 5px;
--tanstack-cell-padding-left-override: 16px;
--tanstack-cell-padding-right-override: 16px;

View File

@@ -116,7 +116,7 @@
is hidden — the row stays a single crisp line and scrolls only when narrow. */
.typeTabsScroll {
justify-self: flex-end;
--tab-list-wrapper-secondary-padding-left: 0;
--tabs-list-wrapper-secondary-padding-left: 0;
}
/* Connected segmented control, mirroring Overview's SegmentedControl: no outer

View File

@@ -23,10 +23,11 @@ var (
const savedViewNameSuffixLen = 8
var (
SourceTraces = Source{valuer.NewString("traces")}
SourceLogs = Source{valuer.NewString("logs")}
SourceMetrics = Source{valuer.NewString("metrics")}
SourceMeter = Source{valuer.NewString("meter")}
SourceTraces = Source{valuer.NewString("traces")}
SourceLogs = Source{valuer.NewString("logs")}
SourceMetrics = Source{valuer.NewString("metrics")}
SourceMeter = Source{valuer.NewString("meter")}
SourceAIObservability = Source{valuer.NewString("ai_observability")}
)
type SavedView struct {
@@ -117,12 +118,13 @@ func (Source) Enum() []any {
SourceLogs,
SourceMetrics,
SourceMeter,
SourceAIObservability,
}
}
func (s Source) Validate() error {
switch s {
case SourceTraces, SourceLogs, SourceMetrics, SourceMeter:
case SourceTraces, SourceLogs, SourceMetrics, SourceMeter, SourceAIObservability:
return nil
default:
return errors.NewInvalidInputf(ErrCodeSavedViewInvalidInput, "invalid source: %s", s.StringValue())

View File

@@ -39,6 +39,7 @@ func TestSourceValidate(t *testing.T) {
{name: "logs", source: SourceLogs},
{name: "metrics", source: SourceMetrics},
{name: "meter", source: SourceMeter},
{name: "ai_observability", source: SourceAIObservability},
{name: "unknown is rejected", source: Source{valuer.NewString("bogus")}, expectError: true},
}

View File

@@ -173,6 +173,21 @@ func TestSavedViewSpecValidate(t *testing.T) {
},
expectError: false,
},
{
name: "builder_ai_query is valid",
spec: SavedViewSpec{
DisplayName: "My View",
PanelType: PanelTypeList,
RequestType: qbtypes.RequestTypeRaw,
Queries: []qbtypes.QueryEnvelope{{
Type: qbtypes.QueryTypeBuilderAI,
Spec: qbtypes.QueryBuilderQuery[qbtypes.TraceAggregation]{
Signal: telemetrytypes.SignalTraces,
},
}},
},
expectError: false,
},
{
name: "graph panel query with no aggregation is still rejected",
spec: SavedViewSpec{

View File

@@ -592,6 +592,66 @@ def test_saved_view_lifecycle(
assert response.status_code == HTTPStatus.NOT_FOUND
def test_ai_observability_view_with_builder_ai_query_roundtrip(
signoz: SigNoz,
create_user_admin: Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
):
"""builder_ai_query implies the traces signal -- the spec is sent without
one and must read back with signal pinned to "traces"."""
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
headers = {"Authorization": f"Bearer {token}"}
response = requests.post(
signoz.self.host_configs["8080"].get(BASE_URL),
json={
"name": "ai-observability-overview",
"generateName": False,
"source": "ai_observability",
"schemaVersion": "v2",
"spec": {
"displayName": "ai-observability-overview",
"requestType": "scalar",
"queries": [{"type": "builder_ai_query", "spec": {"name": "A", "aggregations": [{"expression": "count()"}], "disabled": False, "legend": ""}}],
"selectedFields": [],
"panelType": "table",
"display": {"maxLines": 0, "fontSize": "", "format": "", "color": ""},
},
},
headers=headers,
timeout=5,
)
assert response.status_code == HTTPStatus.CREATED, response.text
view_id = response.json()["data"]["id"]
try:
response = requests.get(
signoz.self.host_configs["8080"].get(f"{BASE_URL}/{view_id}"),
headers=headers,
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
got = response.json()["data"]
assert got["source"] == "ai_observability"
assert got["spec"]["queries"][0]["type"] == "builder_ai_query"
assert got["spec"]["queries"][0]["spec"]["signal"] == "traces"
response = requests.get(
signoz.self.host_configs["8080"].get(BASE_URL),
params={"source": "ai_observability"},
headers=headers,
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
assert {v["name"] for v in response.json()["data"]} == {"ai-observability-overview"}
finally:
requests.delete(
signoz.self.host_configs["8080"].get(f"{BASE_URL}/{view_id}"),
headers=headers,
timeout=5,
)
def test_empty_name_derives_a_slug_from_display_name(
signoz: SigNoz,
create_user_admin: Operation, # pylint: disable=unused-argument