Skip to content

Commit 7d2ea15

Browse files
committed
test(integ-test): add CalcitePPLDashboardPatternsIT pinning BRAIN-label dashboard query
OpenSearch Dashboards renders BRAIN-pattern panels with the shape: patterns ... method=BRAIN mode=label | stats count() as pattern_count, take(message, 1) as sample_logs by patterns_field | sort -pattern_count | fields patterns_field, pattern_count, sample_logs This integration test pins that shape on the analytics-engine route so regressions surface immediately. Schema-only assertions because BRAIN's clustering output is dataset-version-sensitive — the contract we care about is "the query plans, executes, and returns three columns in the right order". Currently red end-to-end pending the BRAIN label window-UDF type-cascade fix (see the OpenSearch-side WIP commit "BRAIN window UDF + dashboard query path scaffolding" — the {@code PplWindowCallRewriter} stub documents the remaining gap). Signed-off-by: Kai Huang <ahkcs@amazon.com>
1 parent 6bb8b7a commit 7d2ea15

1 file changed

Lines changed: 74 additions & 0 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.calcite.remote;
7+
8+
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_HDFS_LOGS;
9+
import static org.opensearch.sql.util.MatcherUtils.schema;
10+
import static org.opensearch.sql.util.MatcherUtils.verifySchemaInOrder;
11+
12+
import java.io.IOException;
13+
import org.json.JSONObject;
14+
import org.junit.Test;
15+
import org.opensearch.sql.ppl.PPLIntegTestCase;
16+
17+
/**
18+
* Pins the exact PPL query shape OpenSearch Dashboards uses to render BRAIN-pattern
19+
* panels: {@code patterns ... method=BRAIN mode=label} followed by
20+
* {@code stats count(), take(message, 1) by patterns_field | sort -pattern_count |
21+
* fields patterns_field, pattern_count, sample_logs}.
22+
*
23+
* <p>The combination exercises three pieces that all have to be wired through the
24+
* analytics-engine route together:
25+
*
26+
* <ul>
27+
* <li>{@code INTERNAL_PATTERN} as a window function (label mode emits one
28+
* matched wildcard pattern per row, broadcast across the partition).</li>
29+
* <li>{@code take(field, n)} aggregate to capture a representative sample log
30+
* per discovered pattern group.</li>
31+
* <li>{@code count()} aggregate + {@code sort} on the result.</li>
32+
* </ul>
33+
*
34+
* <p>Schema-only assertions: BRAIN's clustering depends on a corpus large enough
35+
* that the default heuristics fire, so per-row pattern strings are sensitive to
36+
* dataset version. The schema check guarantees the query plans, executes, and
37+
* returns the dashboard's three expected columns in the right order.
38+
*
39+
* @opensearch.internal
40+
*/
41+
public class CalcitePPLDashboardPatternsIT extends PPLIntegTestCase {
42+
@Override
43+
public void init() throws Exception {
44+
super.init();
45+
enableCalcite();
46+
loadIndex(Index.HDFS_LOGS);
47+
}
48+
49+
/**
50+
* Mirrors the canonical Dashboards BRAIN-label pattern panel query. Unfiltered
51+
* variant — pins the end-to-end plan compiles and returns the dashboard's
52+
* three-column shape (matched wildcard pattern + occurrence count + sample log).
53+
*/
54+
@Test
55+
public void testDashboardBrainLabelStatsByPatternsField() throws IOException {
56+
JSONObject result =
57+
executeQuery(
58+
String.format(
59+
"source=%s"
60+
+ " | patterns content method=BRAIN mode=label"
61+
+ " max_sample_count=5 variable_count_threshold=5"
62+
+ " frequency_threshold_percentage=0.2"
63+
+ " | stats count() as pattern_count, take(content, 1) as sample_logs"
64+
+ " by patterns_field"
65+
+ " | sort - pattern_count"
66+
+ " | fields patterns_field, pattern_count, sample_logs",
67+
TEST_INDEX_HDFS_LOGS));
68+
verifySchemaInOrder(
69+
result,
70+
schema("patterns_field", "string"),
71+
schema("pattern_count", "bigint"),
72+
schema("sample_logs", "array"));
73+
}
74+
}

0 commit comments

Comments
 (0)