mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-05 00:09:35 +00:00
fix: use selected stream type for validating query (#9897)
### **User description**
1. This PR fixes below issue
use selected stream type for validating query previously we were using
default logs
___
### **PR Type**
Bug fix, Tests, Enhancement
___
### **Description**
- Query component: use selected stream_type for validation
- Query.vue: replace hardcoded "logs" with dynamic stream_type
- ScheduledPipeline.vue: improve PromQL support and conditional spinner
- Added tests for SQL/PromQL workflows and bug fixes
___
<details> <summary><h3> File Walkthrough</h3></summary>
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Tests</strong></td><td><table>
<tr>
<td>
<details>
<summary><strong>Query.spec.ts</strong><dd><code>Add dynamic streamType
validation tests</code>
</dd></summary>
<hr>
web/src/components/pipeline/NodeForm/Query.spec.ts
<ul><li>Added tests for <code>validateSqlQuery</code> using dynamic
stream_type<br> <li> Verified <code>searchService.search</code> called
with logs, metrics, traces<br> <li> Ensured no hardcoded "logs"
page_type in validation</ul>
</details>
</td>
<td><a
href="https://github.com/openobserve/openobserve/pull/9897/files#diff-28606cc9e509c3f1c132551ed29c46ef168444b4425cf5e81e0eff65302a9d16">+75/-9</a>
</td>
</tr>
<tr>
<td>
<details>
<summary><strong>ScheduledPipeline.spec.js</strong><dd><code>Expand
tests for PromQL and SQL workflows</code>
</dd></summary>
<hr>
web/src/components/pipeline/NodeForm/ScheduledPipeline.spec.js
<ul><li>Added tests for PromQL tab behaviors and loader logic<br> <li>
Verified query initialization from props and stream extraction<br> <li>
Integration tests covering combined SQL/PromQL fixes</ul>
</details>
</td>
<td><a
href="https://github.com/openobserve/openobserve/pull/9897/files#diff-4961fda8934ec900d20729ed7835abb5063179a09a64fbf5337ff704357e285c">+325/-4</a>
</td>
</tr>
</table></td></tr><tr><td><strong>Bug fix</strong></td><td><table>
<tr>
<td>
<details>
<summary><strong>Query.vue</strong><dd><code>Use dynamic stream_type in
validateSqlQuery</code>
</dd></summary>
<hr>
web/src/components/pipeline/NodeForm/Query.vue
<ul><li>Replaced hardcoded <code>page_type: "logs"</code> with
<br><code>streamRoute.value.stream_type</code><br> <li> Search
invocation now uses selected stream type for SQL validation</ul>
</details>
</td>
<td><a
href="https://github.com/openobserve/openobserve/pull/9897/files#diff-6247cbd506bcf963372f2e429507fc579af95f003df246889b478da11326a657">+1/-1</a>
</td>
</tr>
</table></td></tr><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
<td>
<details>
<summary><strong>ScheduledPipeline.vue</strong><dd><code>Enhance
ScheduledPipeline UI and PromQL support</code>
</dd></summary>
<hr>
web/src/components/pipeline/NodeForm/ScheduledPipeline.vue
<ul><li>Show loader only when output expanded and tab == 'sql'<br> <li>
Move spinner above table, wrap in v-if loading & expanded<br> <li> Only
render PromQL preview when output expanded<br> <li> Initialize
<code>tab</code>, <code>query</code>, <code>stream_type</code> props
correctly<br> <li> Extract PromQL stream name on mount and fetch
fields<br> <li> Use <code>nextTick</code> before refreshing
PreviewPromqlQuery</ul>
</details>
</td>
<td><a
href="https://github.com/openobserve/openobserve/pull/9897/files#diff-63d8f838bb880356e7804b4a57fd9223d4f2c189de7aadc7cf33cba723b29aaf">+28/-15</a>
</td>
</tr>
</table></td></tr></tr></tbody></table>
</details>
___
This commit is contained in:
@@ -909,10 +909,10 @@ describe("Query Component", () => {
|
||||
it("should complete full workflow: create, validate, and save", async () => {
|
||||
// Clear all previous mocks first
|
||||
vi.clearAllMocks();
|
||||
|
||||
|
||||
// Setup successful search mock
|
||||
vi.mocked(searchService.search).mockResolvedValueOnce({ hits: [] });
|
||||
|
||||
|
||||
// Setup the component state
|
||||
wrapper.vm.streamRoute.name = "integration-test";
|
||||
wrapper.vm.streamRoute.query_condition.sql = "SELECT * FROM logs WHERE level = 'ERROR'";
|
||||
@@ -920,10 +920,10 @@ describe("Query Component", () => {
|
||||
wrapper.vm.scheduledPipelineRef = {
|
||||
validateInputs: vi.fn().mockReturnValue(true),
|
||||
};
|
||||
|
||||
|
||||
// Execute the save operation (which includes validation)
|
||||
await wrapper.vm.saveQueryData();
|
||||
|
||||
|
||||
// Verify that the workflow completed successfully
|
||||
expect(mockAddNode).toHaveBeenCalled();
|
||||
expect(wrapper.emitted("cancel:hideform")).toBeTruthy();
|
||||
@@ -932,7 +932,7 @@ describe("Query Component", () => {
|
||||
it("should handle complete deletion workflow", () => {
|
||||
wrapper.vm.openDeleteDialog();
|
||||
wrapper.vm.dialog.okCallback();
|
||||
|
||||
|
||||
expect(mockDeletePipelineNode).toHaveBeenCalled();
|
||||
expect(wrapper.emitted("cancel:hideform")).toBeTruthy();
|
||||
});
|
||||
@@ -940,12 +940,78 @@ describe("Query Component", () => {
|
||||
it("should handle complete cancellation workflow with changes", () => {
|
||||
wrapper.vm.streamRoute.name = "changed";
|
||||
wrapper.vm.openCancelDialog();
|
||||
|
||||
|
||||
expect(wrapper.vm.dialog.show).toBe(true);
|
||||
|
||||
|
||||
wrapper.vm.dialog.okCallback();
|
||||
|
||||
|
||||
expect(wrapper.emitted("cancel:hideform")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Bug Fix: Stream Type Validation (Issue #1)", () => {
|
||||
it("should use correct stream type for logs validation", async () => {
|
||||
vi.mocked(searchService.search).mockResolvedValueOnce({ hits: [] });
|
||||
|
||||
wrapper.vm.streamRoute.stream_type = "logs";
|
||||
wrapper.vm.streamRoute.query_condition.type = "sql";
|
||||
wrapper.vm.streamRoute.query_condition.sql = "SELECT * FROM logs";
|
||||
|
||||
await wrapper.vm.validateSqlQuery();
|
||||
|
||||
expect(searchService.search).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
page_type: "logs",
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("should use correct stream type for metrics validation", async () => {
|
||||
vi.mocked(searchService.search).mockResolvedValueOnce({ hits: [] });
|
||||
|
||||
wrapper.vm.streamRoute.stream_type = "metrics";
|
||||
wrapper.vm.streamRoute.query_condition.type = "sql";
|
||||
wrapper.vm.streamRoute.query_condition.sql = "SELECT * FROM metrics";
|
||||
|
||||
await wrapper.vm.validateSqlQuery();
|
||||
|
||||
expect(searchService.search).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
page_type: "metrics",
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("should use correct stream type for traces validation", async () => {
|
||||
vi.mocked(searchService.search).mockResolvedValueOnce({ hits: [] });
|
||||
|
||||
wrapper.vm.streamRoute.stream_type = "traces";
|
||||
wrapper.vm.streamRoute.query_condition.type = "sql";
|
||||
wrapper.vm.streamRoute.query_condition.sql = "SELECT * FROM traces";
|
||||
|
||||
await wrapper.vm.validateSqlQuery();
|
||||
|
||||
expect(searchService.search).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
page_type: "traces",
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("should not hardcode logs stream type for validation", async () => {
|
||||
vi.mocked(searchService.search).mockResolvedValueOnce({ hits: [] });
|
||||
|
||||
wrapper.vm.streamRoute.stream_type = "metrics";
|
||||
wrapper.vm.streamRoute.query_condition.type = "sql";
|
||||
|
||||
await wrapper.vm.validateSqlQuery();
|
||||
|
||||
// Ensure it's NOT using hardcoded "logs"
|
||||
expect(searchService.search).not.toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
page_type: "logs",
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -516,7 +516,7 @@ const validateSqlQuery = async () => {
|
||||
.search({
|
||||
org_identifier: store.state.selectedOrganization.identifier,
|
||||
query,
|
||||
page_type: "logs",
|
||||
page_type: streamRoute.value.stream_type, //use the selected stream type
|
||||
validate: true,
|
||||
})
|
||||
.then((res: any) => {
|
||||
|
||||
@@ -398,22 +398,343 @@ describe("ScheduledPipeline Component", () => {
|
||||
|
||||
|
||||
it("handles function selection", async () => {
|
||||
const testFunction = {
|
||||
const testFunction = {
|
||||
name: 'avg',
|
||||
description: 'Average function',
|
||||
function: 'avg(value)'
|
||||
};
|
||||
|
||||
|
||||
// Initialize the component's state
|
||||
wrapper.vm.selectedFunction = null;
|
||||
wrapper.vm.vrlFunctionContent = null;
|
||||
|
||||
|
||||
// Call the method and wait for updates
|
||||
await wrapper.vm.onFunctionSelect(testFunction);
|
||||
await nextTick();
|
||||
|
||||
|
||||
// Verify the state changes
|
||||
expect(wrapper.vm.selectedFunction).toBe('avg');
|
||||
});
|
||||
});
|
||||
|
||||
describe("Bug Fix: PromQL Tab Auto-Open Output Section (Issue #2)", () => {
|
||||
it("should not auto-expand output section when switching to promql tab", async () => {
|
||||
wrapper.vm.expandState.output = false;
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.selectedStreamType = "metrics";
|
||||
|
||||
await wrapper.vm.updateTab();
|
||||
await nextTick();
|
||||
|
||||
// Output should remain collapsed after switching to promql
|
||||
expect(wrapper.vm.expandState.output).toBe(false);
|
||||
});
|
||||
|
||||
it("should only show promql preview when output is expanded", () => {
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.expandState.output = false;
|
||||
|
||||
// PreviewPromqlQuery component should not render when output is collapsed
|
||||
// This is tested through the v-else-if condition: tab == 'promql' && expandState.output
|
||||
expect(wrapper.vm.expandState.output).toBe(false);
|
||||
});
|
||||
|
||||
it("should show promql preview when output is manually expanded", async () => {
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.expandState.output = false;
|
||||
|
||||
// Manually expand output
|
||||
wrapper.vm.expandState.output = true;
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.expandState.output).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Bug Fix: Loader Pushing Footer (Issue #3)", () => {
|
||||
it("should only show loader when output section is expanded", async () => {
|
||||
wrapper.vm.loading = true;
|
||||
wrapper.vm.tab = "sql";
|
||||
wrapper.vm.expandState.output = false;
|
||||
|
||||
await nextTick();
|
||||
|
||||
// Loader should not be visible when output is collapsed
|
||||
expect(wrapper.vm.expandState.output).toBe(false);
|
||||
});
|
||||
|
||||
it("should show loader when output is expanded and loading", async () => {
|
||||
wrapper.vm.loading = true;
|
||||
wrapper.vm.tab = "sql";
|
||||
wrapper.vm.expandState.output = true;
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.loading).toBe(true);
|
||||
expect(wrapper.vm.expandState.output).toBe(true);
|
||||
});
|
||||
|
||||
it("should not show table while loading", async () => {
|
||||
wrapper.vm.loading = true;
|
||||
wrapper.vm.tab = "sql";
|
||||
wrapper.vm.expandState.output = true;
|
||||
wrapper.vm.rows = [{ test: "data" }];
|
||||
|
||||
await nextTick();
|
||||
|
||||
// When loading is true, table should not be shown (tested via v-else-if)
|
||||
expect(wrapper.vm.loading).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Bug Fix: PromQL First Click Not Running Query (Issue #4)", () => {
|
||||
it("should run promql query on first click using nextTick", async () => {
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.expandState.output = false;
|
||||
wrapper.vm.query = "test_metric{}";
|
||||
wrapper.vm.selectedStreamName = "test_metric";
|
||||
|
||||
// Mock the previewPromqlQueryRef
|
||||
const mockRefreshData = vi.fn();
|
||||
wrapper.vm.previewPromqlQueryRef = {
|
||||
refreshData: mockRefreshData
|
||||
};
|
||||
|
||||
// Simulate run query button click
|
||||
wrapper.vm.expandState.output = true;
|
||||
await wrapper.vm.runQuery();
|
||||
|
||||
// Wait for nextTick to complete
|
||||
await nextTick();
|
||||
|
||||
// refreshData should be called after nextTick
|
||||
expect(mockRefreshData).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should handle null previewPromqlQueryRef gracefully", async () => {
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.previewPromqlQueryRef = null;
|
||||
|
||||
// Should not throw error
|
||||
await expect(wrapper.vm.runQuery()).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
it("should only call refreshData if ref exists after nextTick", async () => {
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.previewPromqlQueryRef = null;
|
||||
|
||||
// Run query without ref
|
||||
await wrapper.vm.runQuery();
|
||||
|
||||
// Should complete without error
|
||||
expect(wrapper.vm.tab).toBe("promql");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Bug Fix: PromQL Query and Stream Not Restored on Edit (Issue #5)", () => {
|
||||
it("should initialize query from props.promql when query_type is promql", () => {
|
||||
const promqlQuery = "cpu_usage{instance='server1'}";
|
||||
const newWrapper = mount(ScheduledPipeline, {
|
||||
global: {
|
||||
plugins: [i18n],
|
||||
provide: { store: mockStore },
|
||||
stubs: {
|
||||
'q-splitter': true,
|
||||
'DateTime': true,
|
||||
'FieldList': true,
|
||||
'QueryEditor': true,
|
||||
'TenstackTable': true,
|
||||
'PreviewPromqlQuery': true,
|
||||
'O2AIChat': true,
|
||||
'FullViewContainer': true
|
||||
}
|
||||
},
|
||||
props: {
|
||||
columns: [],
|
||||
trigger: wrapper.vm.triggerData,
|
||||
sql: "SELECT * FROM logs",
|
||||
promql: promqlQuery,
|
||||
query_type: "promql",
|
||||
streamType: "metrics",
|
||||
delay: 0
|
||||
}
|
||||
});
|
||||
|
||||
expect(newWrapper.vm.query).toBe(promqlQuery);
|
||||
newWrapper.unmount();
|
||||
});
|
||||
|
||||
it("should initialize query from props.sql when query_type is sql", () => {
|
||||
const sqlQuery = "SELECT * FROM logs";
|
||||
const newWrapper = mount(ScheduledPipeline, {
|
||||
global: {
|
||||
plugins: [i18n],
|
||||
provide: { store: mockStore },
|
||||
stubs: {
|
||||
'q-splitter': true,
|
||||
'DateTime': true,
|
||||
'FieldList': true,
|
||||
'QueryEditor': true,
|
||||
'TenstackTable': true,
|
||||
'PreviewPromqlQuery': true,
|
||||
'O2AIChat': true,
|
||||
'FullViewContainer': true
|
||||
}
|
||||
},
|
||||
props: {
|
||||
columns: [],
|
||||
trigger: wrapper.vm.triggerData,
|
||||
sql: sqlQuery,
|
||||
promql: "metric{}",
|
||||
query_type: "sql",
|
||||
streamType: "logs",
|
||||
delay: 0
|
||||
}
|
||||
});
|
||||
|
||||
expect(newWrapper.vm.query).toBe(sqlQuery);
|
||||
newWrapper.unmount();
|
||||
});
|
||||
|
||||
it("should extract stream name from promql query on mount", async () => {
|
||||
const promqlQuery = "cpu_usage{instance='server1'}";
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.query = promqlQuery;
|
||||
|
||||
// Simulate the onMounted extraction
|
||||
const match = promqlQuery.match(/^([a-zA-Z0-9_-]+)/);
|
||||
if (match) {
|
||||
wrapper.vm.selectedStreamName = match[1];
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.selectedStreamName).toBe("cpu_usage");
|
||||
});
|
||||
|
||||
it("should handle promql query with complex label selectors", async () => {
|
||||
const promqlQuery = "http_requests_total{method='GET',status='200'}";
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.query = promqlQuery;
|
||||
|
||||
const match = promqlQuery.match(/^([a-zA-Z0-9_-]+)/);
|
||||
if (match) {
|
||||
wrapper.vm.selectedStreamName = match[1];
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.selectedStreamName).toBe("http_requests_total");
|
||||
});
|
||||
|
||||
it("should handle promql query with hyphens and underscores", async () => {
|
||||
const promqlQuery = "my-metric_name_123{}";
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.query = promqlQuery;
|
||||
|
||||
const match = promqlQuery.match(/^([a-zA-Z0-9_-]+)/);
|
||||
if (match) {
|
||||
wrapper.vm.selectedStreamName = match[1];
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.selectedStreamName).toBe("my-metric_name_123");
|
||||
});
|
||||
|
||||
it("should not extract stream name from invalid promql query", async () => {
|
||||
const promqlQuery = "{invalid}";
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.query = promqlQuery;
|
||||
wrapper.vm.selectedStreamName = "";
|
||||
|
||||
const match = promqlQuery.match(/^([a-zA-Z0-9_-]+)/);
|
||||
if (match) {
|
||||
wrapper.vm.selectedStreamName = match[1];
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.selectedStreamName).toBe("");
|
||||
});
|
||||
|
||||
it("should call getStreamFields after extracting stream name", async () => {
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.query = "test_metric{}";
|
||||
wrapper.vm.selectedStreamName = "test_metric";
|
||||
|
||||
// Track initial state
|
||||
const initialFieldsLength = wrapper.vm.streamFields.length;
|
||||
|
||||
// Call getStreamFields
|
||||
await wrapper.vm.getStreamFields();
|
||||
await flushPromises();
|
||||
|
||||
// Verify that streamFields was updated (function was executed)
|
||||
expect(wrapper.vm.streamFields.length).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Integration: All Bug Fixes Together", () => {
|
||||
it("should handle complete promql workflow with all fixes", async () => {
|
||||
// Setup: Create a node with PromQL query
|
||||
const promqlQuery = "cpu_usage{instance='server1'}";
|
||||
|
||||
// Fix #5: Initialize with promql query
|
||||
wrapper.vm.tab = "promql";
|
||||
wrapper.vm.query = promqlQuery;
|
||||
wrapper.vm.selectedStreamType = "metrics";
|
||||
|
||||
// Fix #5: Extract stream name
|
||||
const match = promqlQuery.match(/^([a-zA-Z0-9_-]+)/);
|
||||
if (match) {
|
||||
wrapper.vm.selectedStreamName = match[1];
|
||||
}
|
||||
expect(wrapper.vm.selectedStreamName).toBe("cpu_usage");
|
||||
|
||||
// Fix #2: Output should not auto-expand when switching tabs
|
||||
wrapper.vm.expandState.output = false;
|
||||
expect(wrapper.vm.expandState.output).toBe(false);
|
||||
|
||||
// Fix #3: Loader should respect output expand state
|
||||
wrapper.vm.loading = true;
|
||||
expect(wrapper.vm.expandState.output).toBe(false);
|
||||
|
||||
// Manually expand output
|
||||
wrapper.vm.expandState.output = true;
|
||||
wrapper.vm.loading = false;
|
||||
|
||||
// Fix #4: First click should work with nextTick
|
||||
const mockRefreshData = vi.fn();
|
||||
wrapper.vm.previewPromqlQueryRef = {
|
||||
refreshData: mockRefreshData
|
||||
};
|
||||
|
||||
await wrapper.vm.runQuery();
|
||||
await nextTick();
|
||||
|
||||
expect(mockRefreshData).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should handle SQL workflow with stream type fix", async () => {
|
||||
// Fix #1: Should use correct stream type
|
||||
wrapper.vm.tab = "sql";
|
||||
wrapper.vm.selectedStreamType = "traces";
|
||||
wrapper.vm.query = "SELECT * FROM traces_stream";
|
||||
|
||||
searchService.search.mockResolvedValueOnce({
|
||||
data: { hits: [] }
|
||||
});
|
||||
|
||||
await wrapper.vm.runQuery();
|
||||
|
||||
expect(searchService.search).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
page_type: "traces"
|
||||
}),
|
||||
expect.any(String)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1108,11 +1108,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
class="tw:mt-1"
|
||||
/>
|
||||
</span>
|
||||
<TenstackTable
|
||||
<div
|
||||
v-if="loading && expandState.output && tab == 'sql'"
|
||||
style="height: calc(100vh - 190px) !important"
|
||||
v-show="
|
||||
class="flex justify-center items-center"
|
||||
>
|
||||
<q-spinner-hourglass color="primary" size="lg" />
|
||||
</div>
|
||||
|
||||
<TenstackTable
|
||||
v-else-if="
|
||||
expandState.output && rows.length > 0 && tab == 'sql'
|
||||
"
|
||||
style="height: calc(100vh - 190px) !important"
|
||||
ref="searchTableRef"
|
||||
:columns="getColumns"
|
||||
:rows="rows"
|
||||
@@ -1122,13 +1130,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
@copy="copyLogToClipboard"
|
||||
@sendToAiChat="sendToAiChat"
|
||||
/>
|
||||
<div
|
||||
v-if="loading"
|
||||
style="height: calc(100vh - 190px) !important"
|
||||
class="flex justify-center items-center"
|
||||
>
|
||||
<q-spinner-hourglass color="primary" size="lg" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else-if="
|
||||
@@ -1164,7 +1165,7 @@ size="md" />
|
||||
</h6>
|
||||
</div>
|
||||
|
||||
<div v-else-if="tab == 'promql'">
|
||||
<div v-else-if="tab == 'promql' && expandState.output">
|
||||
<PreviewPromqlQuery
|
||||
ref="previewPromqlQueryRef"
|
||||
:query="query"
|
||||
@@ -1189,6 +1190,7 @@ size="md" />
|
||||
class="o2-secondary-button tw:h-[36px]"
|
||||
flat
|
||||
no-caps
|
||||
@mousedown.prevent
|
||||
@click="$emit('delete:node')"
|
||||
>
|
||||
<q-icon name="delete" class="q-mr-xs" />
|
||||
@@ -1201,6 +1203,7 @@ size="md" />
|
||||
:label="t('alerts.cancel')"
|
||||
flat
|
||||
no-caps
|
||||
@mousedown.prevent
|
||||
@click="$emit('cancel:form')"
|
||||
/>
|
||||
<q-btn
|
||||
@@ -1210,6 +1213,7 @@ size="md" />
|
||||
"
|
||||
class="no-border q-ml-md o2-primary-button tw:h-[36px]"
|
||||
no-caps
|
||||
@mousedown.prevent
|
||||
@click.prevent="$emit('submit:form')"
|
||||
:disable="validatingSqlQuery"
|
||||
/>
|
||||
@@ -1414,13 +1418,13 @@ const { t } = useI18n();
|
||||
|
||||
const triggerData = ref(props.trigger);
|
||||
|
||||
const query = ref(props.sql);
|
||||
const tab = ref(props.query_type || "custom");
|
||||
|
||||
const query = ref(tab.value === "promql" ? props.promql : props.sql);
|
||||
|
||||
const promqlQuery = ref(props.promql);
|
||||
|
||||
const delayCondition = ref(props.delay);
|
||||
|
||||
const tab = ref(props.query_type || "custom");
|
||||
const stream_type = ref(props.streamType || "logs");
|
||||
const collapseFields = ref(false);
|
||||
|
||||
@@ -1559,6 +1563,14 @@ onMounted(async () => {
|
||||
selectedStreamName.value = parsedQuery?.ast.from[0].table;
|
||||
|
||||
getStreamFields();
|
||||
} else if (tab.value === "promql" && query.value != "") {
|
||||
// Extract stream name from PromQL query
|
||||
// PromQL query format: stream_name{} or stream_name{label="value"}
|
||||
const match = query.value.match(/^([a-zA-Z0-9_-]+)/);
|
||||
if (match) {
|
||||
selectedStreamName.value = match[1];
|
||||
getStreamFields();
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
|
||||
@@ -2201,7 +2213,7 @@ const updateDateChange = (date: any) => {
|
||||
|
||||
const runQuery = async () => {
|
||||
notificationMsgValue.value = "";
|
||||
//check if datetime is present or not
|
||||
//check if datetime is present or not
|
||||
//else show the error message
|
||||
if(!dateTime.value.startTime) {
|
||||
notificationMsgValue.value = "The selected start time is invalid. Please choose a valid time.";
|
||||
@@ -2250,7 +2262,11 @@ const runQuery = async () => {
|
||||
loading.value = false;
|
||||
});
|
||||
} else if (tab.value == "promql") {
|
||||
previewPromqlQueryRef.value.refreshData();
|
||||
// Wait for next tick to ensure PreviewPromqlQuery component is mounted
|
||||
await nextTick();
|
||||
if (previewPromqlQueryRef.value) {
|
||||
previewPromqlQueryRef.value.refreshData();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user