Skip to content

Commit 8824acd

Browse files
committed
fix: dashboard panel fixes
1 parent e9af417 commit 8824acd

File tree

6 files changed

+149
-48
lines changed

6 files changed

+149
-48
lines changed

src/components/QueryEditor.tsx

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@ import { cloneDeep } from 'lodash';
1111

1212
type Props = QueryEditorProps<DataSource, MyQuery, MyDataSourceOptions>;
1313

14-
export const QueryEditor = ({ query, onChange, onRunQuery, datasource }: Props) => {
14+
export const QueryEditor = ({ query, onChange, onRunQuery, datasource, app, data }: Props) => {
1515
const [streamDetails, setStreamDetails]: any = useState({});
1616
const [streamOptions, setStreamOptions]: any = useState([]);
1717
const [orgOptions, setOrgOptions]: any = useState([]);
1818
const [isMounted, setIsMounted]: any = useState(false);
1919

20+
const isInDashboard = useMemo(() => app === 'panel-editor', [app]);
21+
22+
const getTimeStampColumnName = () => {
23+
return datasource.instanceSettings?.jsonData?.timestamp_column || '_timestamp';
24+
};
25+
2026
useEffect(() => {
2127
getOrganizations({ url: datasource.url, page_num: 0, page_size: 1000, sort_by: 'id' })
2228
.then((orgs: any) => {
@@ -39,7 +45,7 @@ export const QueryEditor = ({ query, onChange, onRunQuery, datasource }: Props)
3945
...query,
4046
stream: streams[0].name,
4147
organization: orgs.data[0].name,
42-
sqlMode: false,
48+
sqlMode: isInDashboard ? true : false,
4349
});
4450
}
4551
setIsMounted(true);
@@ -82,8 +88,14 @@ export const QueryEditor = ({ query, onChange, onRunQuery, datasource }: Props)
8288
};
8389

8490
const updateQuery = () => {
85-
let newQuery = query.query;
86-
if (query.sqlMode) {
91+
let newQuery = query.query || '';
92+
if (isInDashboard) {
93+
if (!newQuery) {
94+
newQuery = `select histogram(${getTimeStampColumnName()}) AS x_axis_1, count(*) AS y_axis_1 from "${
95+
query.stream
96+
}" GROUP BY x_axis_1 ORDER BY x_axis_1`;
97+
}
98+
} else if (query.sqlMode) {
8799
let whereClause = '';
88100
if (newQuery.trim().length) {
89101
whereClause = 'WHERE ' + newQuery.trim();
@@ -203,24 +215,26 @@ export const QueryEditor = ({ query, onChange, onRunQuery, datasource }: Props)
203215
/>
204216
</div>
205217
</div>
206-
<div
207-
className={css`
208-
display: flex;
209-
align-items: center;
210-
padding-bottom: 0.5rem;
211-
`}
212-
>
213-
<InlineLabel
214-
data-testid="query-editor-sql-mode-label"
218+
{!isInDashboard && (
219+
<div
215220
className={css`
216-
width: fit-content;
221+
display: flex;
222+
align-items: center;
223+
padding-bottom: 0.5rem;
217224
`}
218-
transparent={true}
219225
>
220-
SQL Mode
221-
</InlineLabel>
222-
<Switch data-testid="query-editor-sql-mode-switch" value={!!query.sqlMode} onChange={toggleSqlMode} />
223-
</div>
226+
<InlineLabel
227+
data-testid="query-editor-sql-mode-label"
228+
className={css`
229+
width: fit-content;
230+
`}
231+
transparent={true}
232+
>
233+
SQL Mode
234+
</InlineLabel>
235+
<Switch data-testid="query-editor-sql-mode-switch" value={!!query.sqlMode} onChange={toggleSqlMode} />
236+
</div>
237+
)}
224238
{query.stream && (
225239
<ZincEditor
226240
key={generateEditorId}
@@ -230,6 +244,7 @@ export const QueryEditor = ({ query, onChange, onRunQuery, datasource }: Props)
230244
getFields={streamDetails[query.stream]?.schema || []}
231245
isSQLMode={query.sqlMode}
232246
runQuery={onRunQuery}
247+
timestamp_column={datasource.instanceSettings?.jsonData.timestamp_column}
233248
id={generateEditorId}
234249
/>
235250
)}

src/components/ZincEditor.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ interface Props {
1010
runQuery: () => void;
1111
isSQLMode: boolean;
1212
id: string;
13+
timestamp_column: string | undefined;
1314
}
1415

15-
export const ZincEditor = ({ query, onChange, getFields, runQuery, isSQLMode, id }: Props): any => {
16+
export const ZincEditor = ({ query, onChange, getFields, runQuery, isSQLMode, id, timestamp_column }: Props): any => {
1617
const options: monacoTypes.editor.IStandaloneEditorConstructionOptions = {
1718
wordWrap: 'on',
1819
lineNumbers: 'on',
@@ -148,7 +149,7 @@ export const ZincEditor = ({ query, onChange, getFields, runQuery, isSQLMode, id
148149
];
149150

150151
getFields.forEach((field: any) => {
151-
if (field.name === '_timestamp') {
152+
if (field.name === (timestamp_column || '_timestamp')) {
152153
return;
153154
}
154155
let itemObj = {

src/components/config/ConfigEditor.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,12 @@ export function ConfigEditor(props: Props) {
1212
const [timestampName, setTimestampName] = useState('');
1313

1414
useEffect(() => {
15-
const timestamp_column = options?.jsonData?.timestamp_column || '_timestamp';
16-
if (timestamp_column) {
17-
setTimestampName(timestamp_column);
18-
}
19-
15+
updateTimestampName(options?.jsonData?.timestamp_column);
2016
// eslint-disable-next-line react-hooks/exhaustive-deps
2117
}, []);
2218

2319
const updateTimestampName = (name: string) => {
24-
if (name === '') {
20+
if (!!!name) {
2521
name = '_timestamp';
2622
}
2723
setTimestampName(name);

src/datasource.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export class DataSource
2929
url: string;
3030
streamFields: any[];
3131
cachedQuery: CachedQuery;
32+
timestampColumn: string;
3233

3334
constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>) {
3435
super(instanceSettings);
@@ -41,6 +42,7 @@ export class DataSource
4142
data: null,
4243
promise: null,
4344
};
45+
this.timestampColumn = instanceSettings.jsonData.timestamp_column;
4446
}
4547

4648
async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse> {
@@ -54,8 +56,9 @@ export class DataSource
5456
};
5557
});
5658
}
57-
const reqData = buildQuery(target, timestamps, this.streamFields);
59+
const reqData = buildQuery(target, timestamps, this.streamFields, options.app, this.timestampColumn);
5860
if (JSON.stringify(reqData) === this.cachedQuery.requestQuery) {
61+
console.log('returning cached data');
5962
return this.cachedQuery.data
6063
?.then((res) => {
6164
if (target?.refId?.includes(REF_ID_STARTER_LOG_VOLUME)) {
@@ -68,17 +71,25 @@ export class DataSource
6871
});
6972
}
7073

71-
if (target?.refId?.includes(REF_ID_STARTER_LOG_VOLUME) && target.sqlMode) {
72-
return getGraphDataFrame({}, target);
74+
// As we don't show histogram for sql mode in explore
75+
if (options.app === 'explore' && target?.refId?.includes(REF_ID_STARTER_LOG_VOLUME) && target.sqlMode) {
76+
return getGraphDataFrame([], target, options.app);
7377
}
7478

7579
this.cachedQuery.requestQuery = JSON.stringify(reqData);
7680
this.cachedQuery.isFetching = true;
7781
return this.doRequest(target, reqData)
7882
.then((response) => {
79-
const graphDataFrame = getGraphDataFrame(response, target);
80-
const logsDataFrame = getLogsDataFrame(response, target, this.streamFields);
83+
if (options.app === 'panel-editor' || options.app === 'dashboard') {
84+
return getGraphDataFrame(response.hits, target, options.app);
85+
}
86+
87+
const logsDataFrame = getLogsDataFrame(response.hits, target, this.streamFields, this.timestampColumn);
88+
89+
const graphDataFrame = getGraphDataFrame(response?.aggs?.histogram || [], target, options.app);
90+
8191
this.cachedQuery.promise?.resolve({ graph: graphDataFrame, logs: logsDataFrame });
92+
8293
if (target?.refId?.includes(REF_ID_STARTER_LOG_VOLUME)) {
8394
return graphDataFrame;
8495
}

src/features/log/queryResponseBuilder.ts

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import { FieldType, MutableDataFrame, PreferredVisualisationType } from '@grafan
22
import { MyQuery } from '../../types';
33
import { convertTimeToMs, getFieldType } from '../../utils/zincutils';
44

5-
export const getLogsDataFrame = (data: any, target: MyQuery, streamFields: any = []) => {
5+
export const getLogsDataFrame = (
6+
data: any,
7+
target: MyQuery,
8+
streamFields: any = [],
9+
timestampColumn = '_timestamp'
10+
) => {
611
const logsData = getDefaultDataFrame(target.refId, 'logs');
712

813
logsData.addField({
@@ -24,36 +29,64 @@ export const getLogsDataFrame = (data: any, target: MyQuery, streamFields: any =
2429
});
2530
});
2631

27-
data.hits.forEach((log: any) => {
28-
logsData.add({ ...log, Content: JSON.stringify(log), Time: convertTimeToMs(log._timestamp) });
32+
data.forEach((log: any) => {
33+
logsData.add({ ...log, Content: JSON.stringify(log), Time: convertTimeToMs(log[timestampColumn]) });
2934
});
3035

3136
return logsData;
3237
};
3338

34-
export const getGraphDataFrame = (data: any, target: MyQuery) => {
39+
export const getGraphDataFrame = (data: any, target: MyQuery, app: string) => {
3540
const graphData = getDefaultDataFrame(target.refId, 'graph');
3641

42+
let fields = ['zo_sql_key', 'zo_sql_num'];
43+
44+
if (app !== 'explore') {
45+
const columns = getColumnsFromQuery(target.query);
46+
47+
if (columns.length) {
48+
fields = columns;
49+
}
50+
}
51+
3752
graphData.addField({
3853
config: {
3954
filterable: true,
4055
},
4156
name: 'Time',
4257
type: FieldType.time,
4358
});
44-
graphData.addField({
45-
name: 'Value',
46-
type: FieldType.number,
47-
});
4859

49-
data.aggs?.histogram.forEach((log: any) => {
50-
let histDate = new Date(log.zo_sql_key + 'Z').getTime();
51-
graphData.add({ Time: histDate, Value: log.zo_sql_num });
60+
for (let i = 1; i < fields.length; i++) {
61+
graphData.addField({
62+
name: fields[i],
63+
type: FieldType.number,
64+
});
65+
}
66+
67+
if (!data.length) {
68+
return graphData;
69+
}
70+
71+
data.forEach((log: any) => {
72+
graphData.add(getField(log, fields));
5273
});
5374

5475
return graphData;
5576
};
5677

78+
const getField = (log: any, columns: any) => {
79+
let field: any = {
80+
Time: new Date(log[columns[0]] + 'Z').getTime(),
81+
};
82+
83+
for (let i = 1; i < columns.length; i++) {
84+
field[columns[i]] = log[columns[i]];
85+
}
86+
87+
return field;
88+
};
89+
5790
export const getDefaultDataFrame = (refId: string, visualisationType: PreferredVisualisationType = 'logs') => {
5891
return new MutableDataFrame({
5992
refId: refId,
@@ -63,3 +96,41 @@ export const getDefaultDataFrame = (refId: string, visualisationType: PreferredV
6396
fields: [],
6497
});
6598
};
99+
100+
const getColumnsFromQuery = (query: string) => {
101+
// Regular expression pattern to find the select column statements with optional alias
102+
let pattern = /\bselect\b(.+?)\bfrom\b/i;
103+
104+
// Get the selected columns
105+
let match = pattern.exec(query);
106+
107+
// If there's no select statement, return an empty list
108+
if (!match) {
109+
return [];
110+
}
111+
112+
// Split the selected columns by comma, then trim extra whitespace
113+
let selectedColumns = match[1].split(',').map(function (column) {
114+
return column.trim();
115+
});
116+
117+
// Prepare array to store final column names or aliases
118+
let columnNames: any = [];
119+
120+
// Iterate over selected columns
121+
selectedColumns.forEach(function (column) {
122+
// Regular expression pattern to find alias
123+
let aliasPattern = /\s+as\s+(.+)$/i;
124+
125+
// Get the alias
126+
let aliasMatch = aliasPattern.exec(column);
127+
128+
// If alias exists, use that, otherwise use column name
129+
if (aliasMatch) {
130+
columnNames.push(aliasMatch[1]);
131+
} else {
132+
columnNames.push(column);
133+
}
134+
});
135+
return columnNames;
136+
};

src/features/query/queryBuilder.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { MyQuery, TimeRange } from 'types';
22
import { b64EncodeUnicode } from 'utils/zincutils';
33

4-
export const buildQuery = (queryData: MyQuery, timestamps: TimeRange, streamFields: any[]) => {
4+
export const buildQuery = (
5+
queryData: MyQuery,
6+
timestamps: TimeRange,
7+
streamFields: any[],
8+
app: string,
9+
timestampColumn: string
10+
) => {
511
try {
612
let query: string = queryData.query || '';
713

@@ -13,10 +19,7 @@ export const buildQuery = (queryData: MyQuery, timestamps: TimeRange, streamFiel
1319
size: 300,
1420
},
1521
aggs: {
16-
histogram:
17-
'select histogram(' +
18-
'_timestamp' +
19-
", '[INTERVAL]') AS zo_sql_key, count(*) AS zo_sql_num from query GROUP BY zo_sql_key ORDER BY zo_sql_key",
22+
histogram: `select histogram(${timestampColumn}, '[INTERVAL]') AS zo_sql_key, count(*) AS zo_sql_num from query GROUP BY zo_sql_key ORDER BY zo_sql_key`,
2023
},
2124
};
2225

@@ -64,6 +67,10 @@ export const buildQuery = (queryData: MyQuery, timestamps: TimeRange, streamFiel
6467
return false;
6568
}
6669

70+
if (app !== 'explore') {
71+
req.query.size = 0;
72+
}
73+
6774
if (queryData.sqlMode) {
6875
req.query.sql = queryData.query;
6976
req.query['sql_mode'] = 'full';

0 commit comments

Comments
 (0)