@perses-dev/loki-plugin 0.3.0 → 0.5.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__mf/js/Loki.b64c7408.js +6 -0
- package/__mf/js/async/1238.71fd7843.js +1 -0
- package/__mf/js/async/1490.0d8dcc42.js +22 -0
- package/__mf/js/async/1501.eefd56b9.js +1 -0
- package/__mf/js/async/1616.60c9a082.js +1 -0
- package/__mf/js/async/1728.21a8f690.js +1 -0
- package/__mf/js/async/1811.a291a38b.js +28 -0
- package/__mf/js/async/1825.5005b3af.js +1 -0
- package/__mf/js/async/1969.53d223ca.js +1 -0
- package/__mf/js/async/2043.eb7e1c61.js +2 -0
- package/__mf/js/async/2386.a3cfef97.js +2 -0
- package/__mf/js/async/3059.cb101ca2.js +1 -0
- package/__mf/js/async/3181.d2b90b95.js +2 -0
- package/__mf/js/async/3849.85df5535.js +7 -0
- package/__mf/js/async/392.c0f9d49a.js +2 -0
- package/__mf/js/async/{1964.7b2e7223.js → 4121.328a1e93.js} +2 -2
- package/__mf/js/async/4466.21ddc88c.js +74 -0
- package/__mf/js/async/{2651.ef335482.js → 5002.29685f8e.js} +1 -1
- package/__mf/js/async/5071.a03a64fd.js +1 -0
- package/__mf/js/async/5440.3fedd5ea.js +2 -0
- package/__mf/js/async/5501.01af8b43.js +2 -0
- package/__mf/js/async/{5214.fee648bb.js → 5587.55dbc663.js} +1 -1
- package/__mf/js/async/6100.e2898f9c.js +1 -0
- package/__mf/js/async/6274.293b47c4.js +2 -0
- package/__mf/js/async/6283.78af4bc8.js +2 -0
- package/__mf/js/async/6498.903f2a94.js +2 -0
- package/__mf/js/async/7177.b50a1c64.js +1 -0
- package/__mf/js/async/7192.4dea1fd0.js +1 -0
- package/__mf/js/async/7370.0ddd349a.js +2 -0
- package/__mf/js/async/7968.ec040694.js +1 -0
- package/__mf/js/async/7978.38078276.js +1 -0
- package/__mf/js/async/8035.8dab4893.js +38 -0
- package/__mf/js/async/8356.5635696c.js +1 -0
- package/__mf/js/async/8470.c67049a2.js +2 -0
- package/__mf/js/async/8482.07caae1a.js +1 -0
- package/__mf/js/async/873.02aa55af.js +1 -0
- package/__mf/js/async/8988.1c565f12.js +1 -0
- package/__mf/js/async/9071.ed72bdac.js +2 -0
- package/__mf/js/async/9235.f2e0e95c.js +1 -0
- package/__mf/js/async/9389.a8ea42a0.js +2 -0
- package/__mf/js/async/941.0bce16fe.js +2 -0
- package/__mf/js/async/9588.2d82f477.js +1 -0
- package/__mf/js/async/9754.5d7b21c2.js +10 -0
- package/__mf/js/async/9836.de786d07.js +1 -0
- package/__mf/js/async/__federation_expose_LokiDatasource.3da46ee2.js +2 -0
- package/__mf/js/async/__federation_expose_LokiLogQuery.c1be0273.js +1 -0
- package/__mf/js/async/__federation_expose_LokiTimeSeriesQuery.cf876f4b.js +1 -0
- package/__mf/js/main.de30f7e6.js +6 -0
- package/lib/bootstrap.js +3 -3
- package/lib/bootstrap.js.map +1 -1
- package/lib/cjs/bootstrap.js +1 -1
- package/lib/cjs/components/complete.js +258 -0
- package/lib/cjs/components/logql-editor.js +6 -3
- package/lib/cjs/components/logql-extension.js +15 -1
- package/lib/cjs/model/index.js +1 -0
- package/lib/cjs/model/loki-client.js +10 -10
- package/lib/cjs/model/loki-selectors.js +5 -5
- package/lib/cjs/queries/constants.js +3 -3
- package/lib/cjs/queries/loki-log-query/LokiLogQueryEditor.js +21 -17
- package/lib/cjs/queries/loki-time-series-query/LokiTimeSeriesQueryEditor.js +5 -16
- package/lib/components/complete.d.ts +37 -0
- package/lib/components/complete.d.ts.map +1 -0
- package/lib/components/complete.js +249 -0
- package/lib/components/complete.js.map +1 -0
- package/lib/components/logql-editor.d.ts +4 -1
- package/lib/components/logql-editor.d.ts.map +1 -1
- package/lib/components/logql-editor.js +7 -4
- package/lib/components/logql-editor.js.map +1 -1
- package/lib/components/logql-extension.d.ts +9 -1
- package/lib/components/logql-extension.d.ts.map +1 -1
- package/lib/components/logql-extension.js +15 -1
- package/lib/components/logql-extension.js.map +1 -1
- package/lib/datasources/loki-datasource/LokiDatasourceEditor.js +1 -1
- package/lib/datasources/loki-datasource/LokiDatasourceEditor.js.map +1 -1
- package/lib/model/index.d.ts +1 -0
- package/lib/model/index.d.ts.map +1 -1
- package/lib/model/index.js +1 -0
- package/lib/model/index.js.map +1 -1
- package/lib/queries/loki-log-query/LokiLogQueryEditor.d.ts.map +1 -1
- package/lib/queries/loki-log-query/LokiLogQueryEditor.js +23 -19
- package/lib/queries/loki-log-query/LokiLogQueryEditor.js.map +1 -1
- package/lib/queries/loki-log-query/get-loki-log-data.js.map +1 -1
- package/lib/queries/loki-log-query/log-query-plugin-interface.d.ts +0 -1
- package/lib/queries/loki-log-query/log-query-plugin-interface.d.ts.map +1 -1
- package/lib/queries/loki-log-query/log-query-plugin-interface.js.map +1 -1
- package/lib/queries/loki-time-series-query/LokiTimeSeriesQueryEditor.d.ts.map +1 -1
- package/lib/queries/loki-time-series-query/LokiTimeSeriesQueryEditor.js +5 -16
- package/lib/queries/loki-time-series-query/LokiTimeSeriesQueryEditor.js.map +1 -1
- package/lib/queries/loki-time-series-query/get-loki-time-series-data.d.ts +1 -4
- package/lib/queries/loki-time-series-query/get-loki-time-series-data.d.ts.map +1 -1
- package/lib/queries/loki-time-series-query/get-loki-time-series-data.js.map +1 -1
- package/mf-manifest.json +107 -102
- package/mf-stats.json +107 -102
- package/package.json +7 -6
- package/__mf/js/Loki.2f631825.js +0 -5
- package/__mf/js/async/1360.2348e2a7.js +0 -10
- package/__mf/js/async/1540.6b797827.js +0 -74
- package/__mf/js/async/1580.c7d3c3f1.js +0 -2
- package/__mf/js/async/2178.c22bac1c.js +0 -2
- package/__mf/js/async/2226.a056d1a3.js +0 -1
- package/__mf/js/async/2292.35c2eeec.js +0 -2
- package/__mf/js/async/2472.75bb97e0.js +0 -22
- package/__mf/js/async/2652.7b7038d2.js +0 -28
- package/__mf/js/async/2708.9651e2da.js +0 -1
- package/__mf/js/async/282.6c4c5a94.js +0 -1
- package/__mf/js/async/3224.b1170acc.js +0 -1
- package/__mf/js/async/3431.2270637c.js +0 -1
- package/__mf/js/async/3863.16343b76.js +0 -2
- package/__mf/js/async/3960.6091bb00.js +0 -2
- package/__mf/js/async/3980.08ab4aef.js +0 -2
- package/__mf/js/async/4075.19dee570.js +0 -1
- package/__mf/js/async/4238.155e3b8a.js +0 -1
- package/__mf/js/async/4269.b4d0f49d.js +0 -2
- package/__mf/js/async/4310.b96a5c66.js +0 -7
- package/__mf/js/async/4421.5adcbc2d.js +0 -1
- package/__mf/js/async/529.f12e49de.js +0 -2
- package/__mf/js/async/5409.ff95cf63.js +0 -1
- package/__mf/js/async/5780.d837c3cd.js +0 -1
- package/__mf/js/async/5981.a46c5157.js +0 -2
- package/__mf/js/async/6134.f7ee513c.js +0 -38
- package/__mf/js/async/6292.9997ca36.js +0 -1
- package/__mf/js/async/6329.9c3a3698.js +0 -2
- package/__mf/js/async/6333.01fb6457.js +0 -2
- package/__mf/js/async/6377.9f308c7f.js +0 -2
- package/__mf/js/async/6770.ba5a38f3.js +0 -1
- package/__mf/js/async/694.c25a1f84.js +0 -1
- package/__mf/js/async/7376.0459aaf7.js +0 -1
- package/__mf/js/async/738.a16c93b6.js +0 -1
- package/__mf/js/async/7740.6f193fac.js +0 -1
- package/__mf/js/async/8216.d9cc6234.js +0 -1
- package/__mf/js/async/8488.5b4b7170.js +0 -1
- package/__mf/js/async/8537.dc791586.js +0 -1
- package/__mf/js/async/9173.75bbe78a.js +0 -2
- package/__mf/js/async/9563.0375701c.js +0 -2
- package/__mf/js/async/__federation_expose_LokiDatasource.a9871645.js +0 -2
- package/__mf/js/async/__federation_expose_LokiLogQuery.9b430d01.js +0 -1
- package/__mf/js/async/__federation_expose_LokiTimeSeriesQuery.61feff51.js +0 -1
- package/__mf/js/main.174be1bc.js +0 -5
- /package/__mf/css/async/{1580.d3010b86.css → 3061.d3010b86.css} +0 -0
- /package/__mf/css/async/{2341.d3010b86.css → 5442.d3010b86.css} +0 -0
- /package/__mf/css/async/{6759.d3010b86.css → 7370.d3010b86.css} +0 -0
- /package/__mf/js/async/{2472.75bb97e0.js.LICENSE.txt → 1490.0d8dcc42.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{2292.35c2eeec.js.LICENSE.txt → 2043.eb7e1c61.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{1580.c7d3c3f1.js.LICENSE.txt → 2386.a3cfef97.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{3863.16343b76.js.LICENSE.txt → 3181.d2b90b95.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{4310.b96a5c66.js.LICENSE.txt → 3849.85df5535.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{5981.a46c5157.js.LICENSE.txt → 392.c0f9d49a.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{1964.7b2e7223.js.LICENSE.txt → 4121.328a1e93.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{6377.9f308c7f.js.LICENSE.txt → 5440.3fedd5ea.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{2178.c22bac1c.js.LICENSE.txt → 5501.01af8b43.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{3960.6091bb00.js.LICENSE.txt → 6274.293b47c4.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{3980.08ab4aef.js.LICENSE.txt → 6283.78af4bc8.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{529.f12e49de.js.LICENSE.txt → 6498.903f2a94.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{4269.b4d0f49d.js.LICENSE.txt → 7370.0ddd349a.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{9173.75bbe78a.js.LICENSE.txt → 8470.c67049a2.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{6329.9c3a3698.js.LICENSE.txt → 9071.ed72bdac.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{6333.01fb6457.js.LICENSE.txt → 9389.a8ea42a0.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{9563.0375701c.js.LICENSE.txt → 941.0bce16fe.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{1360.2348e2a7.js.LICENSE.txt → 9754.5d7b21c2.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{__federation_expose_LokiDatasource.a9871645.js.LICENSE.txt → __federation_expose_LokiDatasource.3da46ee2.js.LICENSE.txt} +0 -0
|
@@ -17,35 +17,35 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
17
17
|
function _export(target, all) {
|
|
18
18
|
for(var name in all)Object.defineProperty(target, name, {
|
|
19
19
|
enumerable: true,
|
|
20
|
-
get: all
|
|
20
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
_export(exports, {
|
|
24
|
-
indexStats
|
|
24
|
+
get indexStats () {
|
|
25
25
|
return indexStats;
|
|
26
26
|
},
|
|
27
|
-
labelValues
|
|
27
|
+
get labelValues () {
|
|
28
28
|
return labelValues;
|
|
29
29
|
},
|
|
30
|
-
labels
|
|
30
|
+
get labels () {
|
|
31
31
|
return labels;
|
|
32
32
|
},
|
|
33
|
-
query
|
|
33
|
+
get query () {
|
|
34
34
|
return query;
|
|
35
35
|
},
|
|
36
|
-
queryRange
|
|
36
|
+
get queryRange () {
|
|
37
37
|
return queryRange;
|
|
38
38
|
},
|
|
39
|
-
series
|
|
39
|
+
get series () {
|
|
40
40
|
return series;
|
|
41
41
|
},
|
|
42
|
-
toUnixSeconds
|
|
42
|
+
get toUnixSeconds () {
|
|
43
43
|
return toUnixSeconds;
|
|
44
44
|
},
|
|
45
|
-
volume
|
|
45
|
+
get volume () {
|
|
46
46
|
return volume;
|
|
47
47
|
},
|
|
48
|
-
volumeRange
|
|
48
|
+
get volumeRange () {
|
|
49
49
|
return volumeRange;
|
|
50
50
|
}
|
|
51
51
|
});
|
|
@@ -17,20 +17,20 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
17
17
|
function _export(target, all) {
|
|
18
18
|
for(var name in all)Object.defineProperty(target, name, {
|
|
19
19
|
enumerable: true,
|
|
20
|
-
get: all
|
|
20
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
_export(exports, {
|
|
24
|
-
DEFAULT_LOKI
|
|
24
|
+
get DEFAULT_LOKI () {
|
|
25
25
|
return DEFAULT_LOKI;
|
|
26
26
|
},
|
|
27
|
-
LOKI_DATASOURCE_KIND
|
|
27
|
+
get LOKI_DATASOURCE_KIND () {
|
|
28
28
|
return LOKI_DATASOURCE_KIND;
|
|
29
29
|
},
|
|
30
|
-
isDefaultLokiSelector
|
|
30
|
+
get isDefaultLokiSelector () {
|
|
31
31
|
return isDefaultLokiSelector;
|
|
32
32
|
},
|
|
33
|
-
isLokiDatasourceSelector
|
|
33
|
+
get isLokiDatasourceSelector () {
|
|
34
34
|
return isLokiDatasourceSelector;
|
|
35
35
|
}
|
|
36
36
|
});
|
|
@@ -5,14 +5,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
function _export(target, all) {
|
|
6
6
|
for(var name in all)Object.defineProperty(target, name, {
|
|
7
7
|
enumerable: true,
|
|
8
|
-
get: all
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
-
DATASOURCE_KIND
|
|
12
|
+
get DATASOURCE_KIND () {
|
|
13
13
|
return DATASOURCE_KIND;
|
|
14
14
|
},
|
|
15
|
-
DEFAULT_DATASOURCE
|
|
15
|
+
get DEFAULT_DATASOURCE () {
|
|
16
16
|
return DEFAULT_DATASOURCE;
|
|
17
17
|
}
|
|
18
18
|
});
|
|
@@ -26,16 +26,30 @@ const _material = require("@mui/material");
|
|
|
26
26
|
const _react = require("react");
|
|
27
27
|
const _immer = require("immer");
|
|
28
28
|
const _components = require("@perses-dev/components");
|
|
29
|
-
const
|
|
29
|
+
const _components1 = require("../../components");
|
|
30
30
|
const _model = require("../../model");
|
|
31
31
|
const _constants = require("../constants");
|
|
32
32
|
const _queryeditormodel = require("../query-editor-model");
|
|
33
33
|
function LokiLogQueryEditor(props) {
|
|
34
|
-
const { onChange, value
|
|
34
|
+
const { onChange, value } = props;
|
|
35
35
|
const { datasource } = value;
|
|
36
36
|
const datasourceSelectValue = datasource ?? _constants.DEFAULT_DATASOURCE;
|
|
37
37
|
const selectedDatasource = (0, _pluginsystem.useDatasourceSelectValueToSelector)(datasourceSelectValue, _model.LOKI_DATASOURCE_KIND);
|
|
38
38
|
const { query, handleQueryChange, handleQueryBlur } = (0, _queryeditormodel.useQueryState)(props);
|
|
39
|
+
// Get client and time range for autocompletion
|
|
40
|
+
const { data: client } = (0, _pluginsystem.useDatasourceClient)(selectedDatasource);
|
|
41
|
+
const { absoluteTimeRange } = (0, _pluginsystem.useTimeRange)();
|
|
42
|
+
// Create completion config for autocompletion
|
|
43
|
+
const completionConfig = (0, _react.useMemo)(()=>{
|
|
44
|
+
if (!client) return undefined;
|
|
45
|
+
return {
|
|
46
|
+
client,
|
|
47
|
+
timeRange: absoluteTimeRange
|
|
48
|
+
};
|
|
49
|
+
}, [
|
|
50
|
+
client,
|
|
51
|
+
absoluteTimeRange
|
|
52
|
+
]);
|
|
39
53
|
const handleDatasourceChange = (newDatasourceSelection)=>{
|
|
40
54
|
if (!(0, _pluginsystem.isVariableDatasource)(newDatasourceSelection) && newDatasourceSelection.kind === _constants.DATASOURCE_KIND) {
|
|
41
55
|
onChange((0, _immer.produce)(value, (draft)=>{
|
|
@@ -43,10 +57,6 @@ function LokiLogQueryEditor(props) {
|
|
|
43
57
|
const nextDatasource = (0, _model.isDefaultLokiSelector)(newDatasourceSelection) ? undefined : newDatasourceSelection;
|
|
44
58
|
draft.datasource = nextDatasource;
|
|
45
59
|
}));
|
|
46
|
-
if (queryHandlerSettings?.setWatchOtherSpecs) queryHandlerSettings.setWatchOtherSpecs({
|
|
47
|
-
...value,
|
|
48
|
-
datasource: newDatasourceSelection
|
|
49
|
-
});
|
|
50
60
|
return;
|
|
51
61
|
}
|
|
52
62
|
throw new Error('Got unexpected non LokiQuery datasource selection');
|
|
@@ -56,21 +66,14 @@ function LokiLogQueryEditor(props) {
|
|
|
56
66
|
}));
|
|
57
67
|
// Immediate query execution on Enter or blur
|
|
58
68
|
const handleQueryExecute = (query)=>{
|
|
59
|
-
if (queryHandlerSettings?.watchQueryChanges) {
|
|
60
|
-
queryHandlerSettings.watchQueryChanges(query);
|
|
61
|
-
}
|
|
62
69
|
onChange((0, _immer.produce)(value, (draft)=>{
|
|
63
70
|
draft.query = query;
|
|
64
71
|
}));
|
|
65
72
|
};
|
|
66
73
|
const handleLogsQueryChange = (0, _react.useCallback)((e)=>{
|
|
67
74
|
handleQueryChange(e);
|
|
68
|
-
if (queryHandlerSettings?.watchQueryChanges) {
|
|
69
|
-
queryHandlerSettings.watchQueryChanges(e);
|
|
70
|
-
}
|
|
71
75
|
}, [
|
|
72
|
-
handleQueryChange
|
|
73
|
-
queryHandlerSettings
|
|
76
|
+
handleQueryChange
|
|
74
77
|
]);
|
|
75
78
|
return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
|
|
76
79
|
spacing: 1.5,
|
|
@@ -105,17 +108,18 @@ function LokiLogQueryEditor(props) {
|
|
|
105
108
|
},
|
|
106
109
|
children: "LogQL Query"
|
|
107
110
|
}),
|
|
108
|
-
/*#__PURE__*/ (0, _jsxruntime.jsx)(
|
|
111
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_components1.LogQLEditor, {
|
|
109
112
|
value: query,
|
|
110
113
|
onChange: handleLogsQueryChange,
|
|
111
|
-
onBlur:
|
|
114
|
+
onBlur: handleQueryBlur,
|
|
112
115
|
onKeyDown: (event)=>{
|
|
113
116
|
if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
|
|
114
117
|
event.preventDefault();
|
|
115
118
|
handleQueryExecute(query);
|
|
116
119
|
}
|
|
117
120
|
},
|
|
118
|
-
placeholder: 'Enter LogQL query (e.g. {job="mysql"} |= "error")'
|
|
121
|
+
placeholder: 'Enter LogQL query (e.g. {job="mysql"} |= "error")',
|
|
122
|
+
completionConfig: completionConfig
|
|
119
123
|
})
|
|
120
124
|
]
|
|
121
125
|
}),
|
|
@@ -25,12 +25,12 @@ const _pluginsystem = require("@perses-dev/plugin-system");
|
|
|
25
25
|
const _material = require("@mui/material");
|
|
26
26
|
const _react = require("react");
|
|
27
27
|
const _immer = require("immer");
|
|
28
|
-
const
|
|
28
|
+
const _components = require("../../components");
|
|
29
29
|
const _model = require("../../model");
|
|
30
30
|
const _constants = require("../constants");
|
|
31
31
|
const _queryeditormodel = require("../query-editor-model");
|
|
32
32
|
function LokiQueryEditor(props) {
|
|
33
|
-
const { onChange, value
|
|
33
|
+
const { onChange, value } = props;
|
|
34
34
|
const { datasource } = value;
|
|
35
35
|
const datasourceSelectValue = datasource ?? _constants.DEFAULT_DATASOURCE;
|
|
36
36
|
const selectedDatasource = (0, _pluginsystem.useDatasourceSelectValueToSelector)(datasourceSelectValue, _model.LOKI_DATASOURCE_KIND);
|
|
@@ -40,31 +40,20 @@ function LokiQueryEditor(props) {
|
|
|
40
40
|
onChange((0, _immer.produce)(value, (draft)=>{
|
|
41
41
|
draft.datasource = newDatasourceSelection;
|
|
42
42
|
}));
|
|
43
|
-
if (queryHandlerSettings?.setWatchOtherSpecs) queryHandlerSettings.setWatchOtherSpecs({
|
|
44
|
-
...value,
|
|
45
|
-
datasource: newDatasourceSelection
|
|
46
|
-
});
|
|
47
43
|
return;
|
|
48
44
|
}
|
|
49
45
|
throw new Error('Got unexpected non LokiQuery datasource selection');
|
|
50
46
|
};
|
|
51
47
|
// Immediate query execution on Enter or blur
|
|
52
48
|
const handleQueryExecute = (query)=>{
|
|
53
|
-
if (queryHandlerSettings?.watchQueryChanges) {
|
|
54
|
-
queryHandlerSettings.watchQueryChanges(query);
|
|
55
|
-
}
|
|
56
49
|
onChange((0, _immer.produce)(value, (draft)=>{
|
|
57
50
|
draft.query = query;
|
|
58
51
|
}));
|
|
59
52
|
};
|
|
60
53
|
const handleLogsQueryChange = (0, _react.useCallback)((e)=>{
|
|
61
54
|
handleQueryChange(e);
|
|
62
|
-
if (queryHandlerSettings?.watchQueryChanges) {
|
|
63
|
-
queryHandlerSettings.watchQueryChanges(e);
|
|
64
|
-
}
|
|
65
55
|
}, [
|
|
66
|
-
handleQueryChange
|
|
67
|
-
queryHandlerSettings
|
|
56
|
+
handleQueryChange
|
|
68
57
|
]);
|
|
69
58
|
return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Stack, {
|
|
70
59
|
spacing: 1.5,
|
|
@@ -99,10 +88,10 @@ function LokiQueryEditor(props) {
|
|
|
99
88
|
},
|
|
100
89
|
children: "LogQL Query"
|
|
101
90
|
}),
|
|
102
|
-
/*#__PURE__*/ (0, _jsxruntime.jsx)(
|
|
91
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_components.LogQLEditor, {
|
|
103
92
|
value: query,
|
|
104
93
|
onChange: handleLogsQueryChange,
|
|
105
|
-
onBlur:
|
|
94
|
+
onBlur: handleQueryBlur,
|
|
106
95
|
onKeyDown: (event)=>{
|
|
107
96
|
if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
|
|
108
97
|
event.preventDefault();
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
|
|
2
|
+
import { EditorState } from '@codemirror/state';
|
|
3
|
+
import { Tree } from '@lezer/common';
|
|
4
|
+
import { EditorView } from '@uiw/react-codemirror';
|
|
5
|
+
import { CompletionConfig } from './logql-extension';
|
|
6
|
+
/** CompletionScope specifies the completion kind, e.g. whether to complete label names or values */
|
|
7
|
+
type CompletionScope = {
|
|
8
|
+
kind: 'LabelName';
|
|
9
|
+
} | {
|
|
10
|
+
kind: 'LabelValue';
|
|
11
|
+
label: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* CompletionInfo specifies the identified scope and position of the completion in the current editor text.
|
|
15
|
+
*/
|
|
16
|
+
export interface CompletionInfo {
|
|
17
|
+
scope: CompletionScope;
|
|
18
|
+
from: number;
|
|
19
|
+
to?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function complete(completionCfg: CompletionConfig, { state, pos }: CompletionContext): Promise<CompletionResult | null>;
|
|
22
|
+
/**
|
|
23
|
+
* Identify completion scope (e.g. LabelName, LabelValue) and position, based on the current node in the syntax tree.
|
|
24
|
+
*
|
|
25
|
+
* Function is exported for tests only.
|
|
26
|
+
*/
|
|
27
|
+
export declare function identifyCompletion(state: EditorState, pos: number, tree: Tree): CompletionInfo | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Add quotes to the completion text in case quotes are not present already.
|
|
30
|
+
* This handles the following cases:
|
|
31
|
+
* { name=HTTP
|
|
32
|
+
* { name="x
|
|
33
|
+
* { name="x" where cursor is after the 'x'
|
|
34
|
+
*/
|
|
35
|
+
export declare function applyQuotedCompletion(view: EditorView, completion: Completion, from: number, to: number): void;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=complete.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../../src/components/complete.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,gBAAgB,EAAwB,MAAM,0BAA0B,CAAC;AAEjH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,oGAAoG;AACpG,KAAK,eAAe,GAAG;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAKD,wBAAsB,QAAQ,CAC5B,aAAa,EAAE,gBAAgB,EAC/B,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,iBAAiB,GAChC,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAWlC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,cAAc,GAAG,SAAS,CA6G1G;AAkDD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAmB9G"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
// Copyright 2025 The Perses Authors
|
|
2
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
// you may not use this file except in compliance with the License.
|
|
4
|
+
// You may obtain a copy of the License at
|
|
5
|
+
//
|
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
//
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
13
|
+
import { insertCompletionText } from '@codemirror/autocomplete';
|
|
14
|
+
import { syntaxTree } from '@codemirror/language';
|
|
15
|
+
import { Selector, Matchers, Matcher, Identifier, Eq, Neq, Re, Nre, String as StringType } from '@grafana/lezer-logql';
|
|
16
|
+
import { toUnixSeconds } from '../model/loki-client';
|
|
17
|
+
const quoteChars = [
|
|
18
|
+
'"',
|
|
19
|
+
'`'
|
|
20
|
+
];
|
|
21
|
+
const defaultQuoteChar = '"';
|
|
22
|
+
export async function complete(completionCfg, { state, pos }) {
|
|
23
|
+
// First, identify the completion scope
|
|
24
|
+
const completion = identifyCompletion(state, pos, syntaxTree(state));
|
|
25
|
+
if (!completion) {
|
|
26
|
+
// No completion scope found for current cursor position.
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
// Then, retrieve completion options for the identified scope (from the Loki API).
|
|
30
|
+
const options = await retrieveOptions(completionCfg, completion.scope);
|
|
31
|
+
return {
|
|
32
|
+
options,
|
|
33
|
+
from: completion.from,
|
|
34
|
+
to: completion.to
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Identify completion scope (e.g. LabelName, LabelValue) and position, based on the current node in the syntax tree.
|
|
39
|
+
*
|
|
40
|
+
* Function is exported for tests only.
|
|
41
|
+
*/ export function identifyCompletion(state, pos, tree) {
|
|
42
|
+
const node = tree.resolveInner(pos, -1);
|
|
43
|
+
switch(node.type.id){
|
|
44
|
+
case Selector:
|
|
45
|
+
// Selector is the entire {label matchers} expression
|
|
46
|
+
// Autocomplete at start: {▯ or empty: {}
|
|
47
|
+
// Do not autocomplete if cursor is after closing brace: {job="mysql"}▯
|
|
48
|
+
if ((node.firstChild === null || node.firstChild?.type.id === 0) && !state.sliceDoc(node.from, pos).includes('}')) {
|
|
49
|
+
return {
|
|
50
|
+
scope: {
|
|
51
|
+
kind: 'LabelName'
|
|
52
|
+
},
|
|
53
|
+
from: pos
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
break;
|
|
57
|
+
case Matchers:
|
|
58
|
+
{
|
|
59
|
+
// Matchers node contains all label matchers inside {}
|
|
60
|
+
// Autocomplete after comma: { job="mysql",▯ or { job="mysql", ▯
|
|
61
|
+
const text = state.sliceDoc(node.from, pos);
|
|
62
|
+
if (text.endsWith(',') || text.endsWith(', ')) {
|
|
63
|
+
return {
|
|
64
|
+
scope: {
|
|
65
|
+
kind: 'LabelName'
|
|
66
|
+
},
|
|
67
|
+
from: pos
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
case Matcher:
|
|
73
|
+
// Single matcher like job="mysql"
|
|
74
|
+
// Autocomplete when cursor is after a complete matcher: { job="mysql" ▯
|
|
75
|
+
if (node.parent?.type.id === Matchers) {
|
|
76
|
+
return {
|
|
77
|
+
scope: {
|
|
78
|
+
kind: 'LabelName'
|
|
79
|
+
},
|
|
80
|
+
from: pos
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
case Identifier:
|
|
85
|
+
// Identifier is a label name being typed
|
|
86
|
+
// Autocomplete partial label names: { jo▯ or { job="mysql", na▯
|
|
87
|
+
if (node.parent?.type.id === Matcher) {
|
|
88
|
+
return {
|
|
89
|
+
scope: {
|
|
90
|
+
kind: 'LabelName'
|
|
91
|
+
},
|
|
92
|
+
from: node.from
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case Eq:
|
|
97
|
+
case Neq:
|
|
98
|
+
case Re:
|
|
99
|
+
case Nre:
|
|
100
|
+
// Operators for label matching: =, !=, =~, !~
|
|
101
|
+
// Autocomplete label values right after operator: { job=▯ or { job!=▯
|
|
102
|
+
if (node.parent?.type.id === Matcher) {
|
|
103
|
+
const labelNode = node.parent.firstChild;
|
|
104
|
+
if (labelNode?.type.id === Identifier) {
|
|
105
|
+
const label = state.sliceDoc(labelNode.from, labelNode.to);
|
|
106
|
+
return {
|
|
107
|
+
scope: {
|
|
108
|
+
kind: 'LabelValue',
|
|
109
|
+
label
|
|
110
|
+
},
|
|
111
|
+
from: pos
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
case StringType:
|
|
117
|
+
// String value in a matcher: { job="▯
|
|
118
|
+
// Do not autocomplete if cursor is after closing quotes: { job=""▯
|
|
119
|
+
if (node.parent?.type.id === Matcher && !/^".*"$/.test(state.sliceDoc(node.from, pos))) {
|
|
120
|
+
const labelNode = node.parent.firstChild;
|
|
121
|
+
if (labelNode?.type.id === Identifier) {
|
|
122
|
+
const label = state.sliceDoc(labelNode.from, labelNode.to);
|
|
123
|
+
return {
|
|
124
|
+
scope: {
|
|
125
|
+
kind: 'LabelValue',
|
|
126
|
+
label
|
|
127
|
+
},
|
|
128
|
+
from: node.from + 1
|
|
129
|
+
}; // +1 to skip opening quote
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
break;
|
|
133
|
+
case 0 /* error node */ :
|
|
134
|
+
// Error nodes represent incomplete or malformed syntax
|
|
135
|
+
// Autocomplete incomplete value after operator: { job=mys▯ or { job="mys▯
|
|
136
|
+
if ((node.prevSibling?.type.id === Eq || node.prevSibling?.type.id === Neq || node.prevSibling?.type.id === Re || node.prevSibling?.type.id === Nre) && node.parent?.type.id === Matcher) {
|
|
137
|
+
const labelNode = node.parent.firstChild;
|
|
138
|
+
if (labelNode?.type.id === Identifier) {
|
|
139
|
+
const label = state.sliceDoc(labelNode.from, labelNode.to);
|
|
140
|
+
// Skip leading quote if present: { name="HT▯
|
|
141
|
+
const from = quoteChars.includes(state.sliceDoc(node.from, node.from + 1)) ? node.from + 1 : node.from;
|
|
142
|
+
return {
|
|
143
|
+
scope: {
|
|
144
|
+
kind: 'LabelValue',
|
|
145
|
+
label
|
|
146
|
+
},
|
|
147
|
+
from
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Autocomplete partial label name: { j▯ or { job="mysql", n▯
|
|
152
|
+
if (node.parent?.type.id === Selector || node.parent?.type.id === Matchers) {
|
|
153
|
+
return {
|
|
154
|
+
scope: {
|
|
155
|
+
kind: 'LabelName'
|
|
156
|
+
},
|
|
157
|
+
from: node.from
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Retrieve completion options based on the identified completion scope.
|
|
165
|
+
*/ async function retrieveOptions(completionCfg, completion) {
|
|
166
|
+
switch(completion.kind){
|
|
167
|
+
case 'LabelName':
|
|
168
|
+
return completeLabelName(completionCfg);
|
|
169
|
+
case 'LabelValue':
|
|
170
|
+
return completeLabelValue(completionCfg, completion.label);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async function completeLabelName(completionCfg) {
|
|
174
|
+
if (!completionCfg.client) {
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
177
|
+
const start = completionCfg.timeRange?.start ? toUnixSeconds(new Date(completionCfg.timeRange.start).getTime()) : undefined;
|
|
178
|
+
const end = completionCfg.timeRange?.end ? toUnixSeconds(new Date(completionCfg.timeRange.end).getTime()) : undefined;
|
|
179
|
+
try {
|
|
180
|
+
const response = await completionCfg.client.labels(start, end);
|
|
181
|
+
if (response.status === 'success') {
|
|
182
|
+
return response.data.map((label)=>({
|
|
183
|
+
label
|
|
184
|
+
}));
|
|
185
|
+
}
|
|
186
|
+
return [];
|
|
187
|
+
} catch (error) {
|
|
188
|
+
console.error('Error fetching label names:', error);
|
|
189
|
+
return [];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function escapeString(input, quoteChar) {
|
|
193
|
+
// do not escape raw strings (when using backticks)
|
|
194
|
+
if (quoteChar === '`') {
|
|
195
|
+
return input;
|
|
196
|
+
}
|
|
197
|
+
let escaped = input;
|
|
198
|
+
// escape backslashes and quotes
|
|
199
|
+
escaped = escaped.replaceAll('\\', '\\\\');
|
|
200
|
+
escaped = escaped.replaceAll('"', '\\"');
|
|
201
|
+
return escaped;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Add quotes to the completion text in case quotes are not present already.
|
|
205
|
+
* This handles the following cases:
|
|
206
|
+
* { name=HTTP
|
|
207
|
+
* { name="x
|
|
208
|
+
* { name="x" where cursor is after the 'x'
|
|
209
|
+
*/ export function applyQuotedCompletion(view, completion, from, to) {
|
|
210
|
+
let quoteChar = defaultQuoteChar;
|
|
211
|
+
if (quoteChars.includes(view.state.sliceDoc(from - 1, from))) {
|
|
212
|
+
quoteChar = view.state.sliceDoc(from - 1, from);
|
|
213
|
+
from--;
|
|
214
|
+
}
|
|
215
|
+
if (quoteChars.includes(view.state.sliceDoc(to, to + 1))) {
|
|
216
|
+
quoteChar = view.state.sliceDoc(to, to + 1);
|
|
217
|
+
to++;
|
|
218
|
+
}
|
|
219
|
+
// When using raw strings (`), we cannot escape a backtick.
|
|
220
|
+
// Therefore, switch the quote character.
|
|
221
|
+
if (completion.label.includes('`')) {
|
|
222
|
+
quoteChar = '"';
|
|
223
|
+
}
|
|
224
|
+
const insertText = `${quoteChar}${escapeString(completion.label, quoteChar)}${quoteChar}`;
|
|
225
|
+
view.dispatch(insertCompletionText(view.state, insertText, from, to));
|
|
226
|
+
}
|
|
227
|
+
async function completeLabelValue(completionCfg, label) {
|
|
228
|
+
if (!completionCfg.client) {
|
|
229
|
+
return [];
|
|
230
|
+
}
|
|
231
|
+
const start = completionCfg.timeRange?.start ? toUnixSeconds(new Date(completionCfg.timeRange.start).getTime()) : undefined;
|
|
232
|
+
const end = completionCfg.timeRange?.end ? toUnixSeconds(new Date(completionCfg.timeRange.end).getTime()) : undefined;
|
|
233
|
+
try {
|
|
234
|
+
const response = await completionCfg.client.labelValues(label, start, end);
|
|
235
|
+
if (response.status === 'success') {
|
|
236
|
+
return response.data.map((value)=>({
|
|
237
|
+
label: value ?? '',
|
|
238
|
+
displayLabel: value ?? '(empty string)',
|
|
239
|
+
apply: applyQuotedCompletion
|
|
240
|
+
}));
|
|
241
|
+
}
|
|
242
|
+
return [];
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.error(`Error fetching values for label ${label}:`, error);
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
//# sourceMappingURL=complete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/complete.ts"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Completion, CompletionContext, CompletionResult, insertCompletionText } from '@codemirror/autocomplete';\nimport { syntaxTree } from '@codemirror/language';\nimport { EditorState } from '@codemirror/state';\nimport { Tree } from '@lezer/common';\nimport { Selector, Matchers, Matcher, Identifier, Eq, Neq, Re, Nre, String as StringType } from '@grafana/lezer-logql';\nimport { EditorView } from '@uiw/react-codemirror';\nimport { toUnixSeconds } from '../model/loki-client';\nimport { CompletionConfig } from './logql-extension';\n\n/** CompletionScope specifies the completion kind, e.g. whether to complete label names or values */\ntype CompletionScope = { kind: 'LabelName' } | { kind: 'LabelValue'; label: string };\n\n/**\n * CompletionInfo specifies the identified scope and position of the completion in the current editor text.\n */\nexport interface CompletionInfo {\n scope: CompletionScope;\n from: number;\n to?: number;\n}\n\nconst quoteChars = ['\"', '`'];\nconst defaultQuoteChar = '\"';\n\nexport async function complete(\n completionCfg: CompletionConfig,\n { state, pos }: CompletionContext\n): Promise<CompletionResult | null> {\n // First, identify the completion scope\n const completion = identifyCompletion(state, pos, syntaxTree(state));\n if (!completion) {\n // No completion scope found for current cursor position.\n return null;\n }\n\n // Then, retrieve completion options for the identified scope (from the Loki API).\n const options = await retrieveOptions(completionCfg, completion.scope);\n return { options, from: completion.from, to: completion.to };\n}\n\n/**\n * Identify completion scope (e.g. LabelName, LabelValue) and position, based on the current node in the syntax tree.\n *\n * Function is exported for tests only.\n */\nexport function identifyCompletion(state: EditorState, pos: number, tree: Tree): CompletionInfo | undefined {\n const node = tree.resolveInner(pos, -1);\n\n switch (node.type.id) {\n case Selector:\n // Selector is the entire {label matchers} expression\n // Autocomplete at start: {▯ or empty: {}\n // Do not autocomplete if cursor is after closing brace: {job=\"mysql\"}▯\n if (\n (node.firstChild === null || node.firstChild?.type.id === 0) &&\n !state.sliceDoc(node.from, pos).includes('}')\n ) {\n return {\n scope: { kind: 'LabelName' },\n from: pos,\n };\n }\n break;\n\n case Matchers: {\n // Matchers node contains all label matchers inside {}\n // Autocomplete after comma: { job=\"mysql\",▯ or { job=\"mysql\", ▯\n const text = state.sliceDoc(node.from, pos);\n if (text.endsWith(',') || text.endsWith(', ')) {\n return {\n scope: { kind: 'LabelName' },\n from: pos,\n };\n }\n break;\n }\n\n case Matcher:\n // Single matcher like job=\"mysql\"\n // Autocomplete when cursor is after a complete matcher: { job=\"mysql\" ▯\n if (node.parent?.type.id === Matchers) {\n return {\n scope: { kind: 'LabelName' },\n from: pos,\n };\n }\n break;\n\n case Identifier:\n // Identifier is a label name being typed\n // Autocomplete partial label names: { jo▯ or { job=\"mysql\", na▯\n if (node.parent?.type.id === Matcher) {\n return {\n scope: { kind: 'LabelName' },\n from: node.from,\n };\n }\n break;\n\n case Eq:\n case Neq:\n case Re:\n case Nre:\n // Operators for label matching: =, !=, =~, !~\n // Autocomplete label values right after operator: { job=▯ or { job!=▯\n if (node.parent?.type.id === Matcher) {\n const labelNode = node.parent.firstChild;\n if (labelNode?.type.id === Identifier) {\n const label = state.sliceDoc(labelNode.from, labelNode.to);\n return { scope: { kind: 'LabelValue', label }, from: pos };\n }\n }\n break;\n\n case StringType:\n // String value in a matcher: { job=\"▯\n // Do not autocomplete if cursor is after closing quotes: { job=\"\"▯\n if (node.parent?.type.id === Matcher && !/^\".*\"$/.test(state.sliceDoc(node.from, pos))) {\n const labelNode = node.parent.firstChild;\n if (labelNode?.type.id === Identifier) {\n const label = state.sliceDoc(labelNode.from, labelNode.to);\n return { scope: { kind: 'LabelValue', label }, from: node.from + 1 }; // +1 to skip opening quote\n }\n }\n break;\n\n case 0 /* error node */:\n // Error nodes represent incomplete or malformed syntax\n // Autocomplete incomplete value after operator: { job=mys▯ or { job=\"mys▯\n if (\n (node.prevSibling?.type.id === Eq ||\n node.prevSibling?.type.id === Neq ||\n node.prevSibling?.type.id === Re ||\n node.prevSibling?.type.id === Nre) &&\n node.parent?.type.id === Matcher\n ) {\n const labelNode = node.parent.firstChild;\n if (labelNode?.type.id === Identifier) {\n const label = state.sliceDoc(labelNode.from, labelNode.to);\n // Skip leading quote if present: { name=\"HT▯\n const from = quoteChars.includes(state.sliceDoc(node.from, node.from + 1)) ? node.from + 1 : node.from;\n return { scope: { kind: 'LabelValue', label }, from };\n }\n }\n\n // Autocomplete partial label name: { j▯ or { job=\"mysql\", n▯\n if (node.parent?.type.id === Selector || node.parent?.type.id === Matchers) {\n return {\n scope: { kind: 'LabelName' },\n from: node.from,\n };\n }\n break;\n }\n}\n\n/**\n * Retrieve completion options based on the identified completion scope.\n */\nasync function retrieveOptions(completionCfg: CompletionConfig, completion: CompletionScope): Promise<Completion[]> {\n switch (completion.kind) {\n case 'LabelName':\n return completeLabelName(completionCfg);\n\n case 'LabelValue':\n return completeLabelValue(completionCfg, completion.label);\n }\n}\n\nasync function completeLabelName(completionCfg: CompletionConfig): Promise<Completion[]> {\n if (!completionCfg.client) {\n return [];\n }\n\n const start = completionCfg.timeRange?.start\n ? toUnixSeconds(new Date(completionCfg.timeRange.start).getTime())\n : undefined;\n const end = completionCfg.timeRange?.end ? toUnixSeconds(new Date(completionCfg.timeRange.end).getTime()) : undefined;\n\n try {\n const response = await completionCfg.client.labels(start, end);\n if (response.status === 'success') {\n return response.data.map((label: string) => ({ label }));\n }\n return [];\n } catch (error) {\n console.error('Error fetching label names:', error);\n return [];\n }\n}\n\nfunction escapeString(input: string, quoteChar: string) {\n // do not escape raw strings (when using backticks)\n if (quoteChar === '`') {\n return input;\n }\n\n let escaped = input;\n // escape backslashes and quotes\n escaped = escaped.replaceAll('\\\\', '\\\\\\\\');\n escaped = escaped.replaceAll('\"', '\\\\\"');\n return escaped;\n}\n\n/**\n * Add quotes to the completion text in case quotes are not present already.\n * This handles the following cases:\n * { name=HTTP\n * { name=\"x\n * { name=\"x\" where cursor is after the 'x'\n */\nexport function applyQuotedCompletion(view: EditorView, completion: Completion, from: number, to: number): void {\n let quoteChar = defaultQuoteChar;\n if (quoteChars.includes(view.state.sliceDoc(from - 1, from))) {\n quoteChar = view.state.sliceDoc(from - 1, from);\n from--;\n }\n if (quoteChars.includes(view.state.sliceDoc(to, to + 1))) {\n quoteChar = view.state.sliceDoc(to, to + 1);\n to++;\n }\n\n // When using raw strings (`), we cannot escape a backtick.\n // Therefore, switch the quote character.\n if (completion.label.includes('`')) {\n quoteChar = '\"';\n }\n\n const insertText = `${quoteChar}${escapeString(completion.label, quoteChar)}${quoteChar}`;\n view.dispatch(insertCompletionText(view.state, insertText, from, to));\n}\n\nasync function completeLabelValue(completionCfg: CompletionConfig, label: string): Promise<Completion[]> {\n if (!completionCfg.client) {\n return [];\n }\n\n const start = completionCfg.timeRange?.start\n ? toUnixSeconds(new Date(completionCfg.timeRange.start).getTime())\n : undefined;\n const end = completionCfg.timeRange?.end ? toUnixSeconds(new Date(completionCfg.timeRange.end).getTime()) : undefined;\n\n try {\n const response = await completionCfg.client.labelValues(label, start, end);\n if (response.status === 'success') {\n return response.data.map((value: string) => ({\n label: value ?? '',\n displayLabel: value ?? '(empty string)',\n apply: applyQuotedCompletion,\n }));\n }\n return [];\n } catch (error) {\n console.error(`Error fetching values for label ${label}:`, error);\n return [];\n }\n}\n"],"names":["insertCompletionText","syntaxTree","Selector","Matchers","Matcher","Identifier","Eq","Neq","Re","Nre","String","StringType","toUnixSeconds","quoteChars","defaultQuoteChar","complete","completionCfg","state","pos","completion","identifyCompletion","options","retrieveOptions","scope","from","to","tree","node","resolveInner","type","id","firstChild","sliceDoc","includes","kind","text","endsWith","parent","labelNode","label","test","prevSibling","completeLabelName","completeLabelValue","client","start","timeRange","Date","getTime","undefined","end","response","labels","status","data","map","error","console","escapeString","input","quoteChar","escaped","replaceAll","applyQuotedCompletion","view","insertText","dispatch","labelValues","value","displayLabel","apply"],"mappings":"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"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
2
|
import { ReactCodeMirrorProps } from '@uiw/react-codemirror';
|
|
3
|
-
|
|
3
|
+
import { CompletionConfig } from './logql-extension';
|
|
4
|
+
export type LogQLEditorProps = Omit<ReactCodeMirrorProps, 'theme' | 'extensions'> & {
|
|
5
|
+
completionConfig?: CompletionConfig;
|
|
6
|
+
};
|
|
4
7
|
export declare function LogQLEditor(props: LogQLEditorProps): ReactElement;
|
|
5
8
|
//# sourceMappingURL=logql-editor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logql-editor.d.ts","sourceRoot":"","sources":["../../../src/components/logql-editor.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAW,MAAM,OAAO,CAAC;AAE9C,OAAmB,EAAc,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"logql-editor.d.ts","sourceRoot":"","sources":["../../../src/components/logql-editor.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAW,MAAM,OAAO,CAAC;AAE9C,OAAmB,EAAc,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAkB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,YAAY,CAAC,GAAG;IAClF,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,YAAY,CA0CjE"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
2
|
// Copyright 2025 The Perses Authors
|
|
2
3
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
4
|
// you may not use this file except in compliance with the License.
|
|
@@ -10,17 +11,19 @@
|
|
|
10
11
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
12
|
// See the License for the specific language governing permissions and
|
|
12
13
|
// limitations under the License.
|
|
13
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
14
|
import { useMemo } from 'react';
|
|
15
15
|
import { useTheme } from '@mui/material';
|
|
16
16
|
import CodeMirror, { EditorView } from '@uiw/react-codemirror';
|
|
17
17
|
import { LogQLExtension } from './logql-extension';
|
|
18
18
|
export function LogQLEditor(props) {
|
|
19
|
+
const { completionConfig, ...codemirrorProps } = props;
|
|
19
20
|
const theme = useTheme();
|
|
20
21
|
const isDarkMode = theme.palette.mode === 'dark';
|
|
21
22
|
const logqlExtension = useMemo(()=>{
|
|
22
|
-
return LogQLExtension();
|
|
23
|
-
}, [
|
|
23
|
+
return LogQLExtension(completionConfig);
|
|
24
|
+
}, [
|
|
25
|
+
completionConfig
|
|
26
|
+
]);
|
|
24
27
|
const codemirrorTheme = useMemo(()=>{
|
|
25
28
|
const borderColor = theme.palette.mode === 'light' ? 'rgba(0, 0, 0, 0.23)' : 'rgba(255, 255, 255, 0.23)';
|
|
26
29
|
return EditorView.theme({
|
|
@@ -40,7 +43,7 @@ export function LogQLEditor(props) {
|
|
|
40
43
|
theme
|
|
41
44
|
]);
|
|
42
45
|
return /*#__PURE__*/ _jsx(CodeMirror, {
|
|
43
|
-
...
|
|
46
|
+
...codemirrorProps,
|
|
44
47
|
theme: isDarkMode ? 'dark' : 'light',
|
|
45
48
|
basicSetup: {
|
|
46
49
|
lineNumbers: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/logql-editor.tsx"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useMemo } from 'react';\nimport { useTheme } from '@mui/material';\nimport CodeMirror, { EditorView, ReactCodeMirrorProps } from '@uiw/react-codemirror';\nimport { LogQLExtension } from './logql-extension';\n\nexport type LogQLEditorProps = Omit<ReactCodeMirrorProps, 'theme' | 'extensions'
|
|
1
|
+
{"version":3,"sources":["../../../src/components/logql-editor.tsx"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useMemo } from 'react';\nimport { useTheme } from '@mui/material';\nimport CodeMirror, { EditorView, ReactCodeMirrorProps } from '@uiw/react-codemirror';\nimport { LogQLExtension, CompletionConfig } from './logql-extension';\n\nexport type LogQLEditorProps = Omit<ReactCodeMirrorProps, 'theme' | 'extensions'> & {\n completionConfig?: CompletionConfig;\n};\n\nexport function LogQLEditor(props: LogQLEditorProps): ReactElement {\n const { completionConfig, ...codemirrorProps } = props;\n const theme = useTheme();\n const isDarkMode = theme.palette.mode === 'dark';\n\n const logqlExtension = useMemo(() => {\n return LogQLExtension(completionConfig);\n }, [completionConfig]);\n\n const codemirrorTheme = useMemo(() => {\n const borderColor = theme.palette.mode === 'light' ? 'rgba(0, 0, 0, 0.23)' : 'rgba(255, 255, 255, 0.23)';\n\n return EditorView.theme({\n '&': {\n backgroundColor: 'transparent !important', // required for dark mode\n border: `1px solid ${borderColor}`,\n borderRadius: `${theme.shape.borderRadius}px`,\n },\n '&.cm-focused.cm-editor': {\n outline: 'none',\n },\n '.cm-content': {\n padding: '8px',\n },\n });\n }, [theme]);\n\n return (\n <CodeMirror\n {...codemirrorProps}\n theme={isDarkMode ? 'dark' : 'light'}\n basicSetup={{\n lineNumbers: false,\n highlightActiveLine: false,\n highlightActiveLineGutter: false,\n foldGutter: false,\n syntaxHighlighting: true,\n }}\n extensions={[EditorView.lineWrapping, logqlExtension, codemirrorTheme]}\n placeholder='Example: {job=\"my-service\"} |= \"error\"'\n />\n );\n}\n"],"names":["useMemo","useTheme","CodeMirror","EditorView","LogQLExtension","LogQLEditor","props","completionConfig","codemirrorProps","theme","isDarkMode","palette","mode","logqlExtension","codemirrorTheme","borderColor","backgroundColor","border","borderRadius","shape","outline","padding","basicSetup","lineNumbers","highlightActiveLine","highlightActiveLineGutter","foldGutter","syntaxHighlighting","extensions","lineWrapping","placeholder"],"mappings":";AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAAuBA,OAAO,QAAQ,QAAQ;AAC9C,SAASC,QAAQ,QAAQ,gBAAgB;AACzC,OAAOC,cAAcC,UAAU,QAA8B,wBAAwB;AACrF,SAASC,cAAc,QAA0B,oBAAoB;AAMrE,OAAO,SAASC,YAAYC,KAAuB;IACjD,MAAM,EAAEC,gBAAgB,EAAE,GAAGC,iBAAiB,GAAGF;IACjD,MAAMG,QAAQR;IACd,MAAMS,aAAaD,MAAME,OAAO,CAACC,IAAI,KAAK;IAE1C,MAAMC,iBAAiBb,QAAQ;QAC7B,OAAOI,eAAeG;IACxB,GAAG;QAACA;KAAiB;IAErB,MAAMO,kBAAkBd,QAAQ;QAC9B,MAAMe,cAAcN,MAAME,OAAO,CAACC,IAAI,KAAK,UAAU,wBAAwB;QAE7E,OAAOT,WAAWM,KAAK,CAAC;YACtB,KAAK;gBACHO,iBAAiB;gBACjBC,QAAQ,CAAC,UAAU,EAAEF,aAAa;gBAClCG,cAAc,GAAGT,MAAMU,KAAK,CAACD,YAAY,CAAC,EAAE,CAAC;YAC/C;YACA,0BAA0B;gBACxBE,SAAS;YACX;YACA,eAAe;gBACbC,SAAS;YACX;QACF;IACF,GAAG;QAACZ;KAAM;IAEV,qBACE,KAACP;QACE,GAAGM,eAAe;QACnBC,OAAOC,aAAa,SAAS;QAC7BY,YAAY;YACVC,aAAa;YACbC,qBAAqB;YACrBC,2BAA2B;YAC3BC,YAAY;YACZC,oBAAoB;QACtB;QACAC,YAAY;YAACzB,WAAW0B,YAAY;YAAEhB;YAAgBC;SAAgB;QACtEgB,aAAY;;AAGlB"}
|