Skip to content
This repository was archived by the owner on May 12, 2026. It is now read-only.

Commit 7ca50de

Browse files
committed
Merge remote-tracking branch 'upstream/main' into fix/log-panel-flickering
# Conflicts: # src/datasource/processResponse.ts
2 parents 6374958 + 5ed484d commit 7ca50de

76 files changed

Lines changed: 7670 additions & 6014 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.config/bundler/externals.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
3+
*
4+
*/
5+
6+
import type { Configuration, ExternalItemFunctionData } from 'webpack';
7+
8+
type ExternalsType = Configuration['externals'];
9+
10+
export const externals: ExternalsType = [
11+
// Required for dynamic publicPath resolution
12+
{ 'amd-module': 'module' },
13+
'lodash',
14+
'jquery',
15+
'moment',
16+
'slate',
17+
'emotion',
18+
'@emotion/react',
19+
'@emotion/css',
20+
'prismjs',
21+
'slate-plain-serializer',
22+
'@grafana/slate-react',
23+
'react',
24+
'react/jsx-runtime',
25+
'react/jsx-dev-runtime',
26+
'react-dom',
27+
'react-redux',
28+
'redux',
29+
'rxjs',
30+
'i18next',
31+
'react-router',
32+
'd3',
33+
'angular',
34+
/^@grafana\/ui/i,
35+
/^@grafana\/runtime/i,
36+
/^@grafana\/data/i,
37+
38+
// Mark legacy SDK imports as external if their name starts with the "grafana/" prefix
39+
({ request }: ExternalItemFunctionData, callback: (error?: Error, result?: string) => void) => {
40+
const prefix = 'grafana/';
41+
const hasPrefix = (request: string) => request.indexOf(prefix) === 0;
42+
const stripPrefix = (request: string) => request.slice(prefix.length);
43+
44+
if (request && hasPrefix(request)) {
45+
return callback(undefined, stripPrefix(request));
46+
}
47+
48+
callback();
49+
},
50+
];

.config/webpack/webpack.config.ts

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { Configuration } from 'webpack';
1616
import { getPackageJson, getPluginJson, hasReadme, getEntries, isWSL } from './utils';
1717
import { SOURCE_DIR, DIST_DIR } from './constants';
1818

19+
import { externals } from '../bundler/externals.ts';
20+
1921
const pluginJson = getPluginJson();
2022

2123
const config = async (env): Promise<Configuration> => {
@@ -33,43 +35,7 @@ const config = async (env): Promise<Configuration> => {
3335

3436
entry: await getEntries(),
3537

36-
externals: [
37-
'lodash',
38-
'jquery',
39-
'moment',
40-
'slate',
41-
'emotion',
42-
'@emotion/react',
43-
'@emotion/css',
44-
'prismjs',
45-
'slate-plain-serializer',
46-
'@grafana/slate-react',
47-
'react',
48-
'react-dom',
49-
'react-redux',
50-
'redux',
51-
'rxjs',
52-
'react-router',
53-
'react-router-dom',
54-
'd3',
55-
'angular',
56-
'@grafana/ui',
57-
'@grafana/runtime',
58-
'@grafana/data',
59-
60-
// Mark legacy SDK imports as external if their name starts with the "grafana/" prefix
61-
({ request }, callback) => {
62-
const prefix = 'grafana/';
63-
const hasPrefix = (request) => request.indexOf(prefix) === 0;
64-
const stripPrefix = (request) => request.substr(prefix.length);
65-
66-
if (hasPrefix(request)) {
67-
return callback(undefined, stripPrefix(request));
68-
}
69-
70-
callback();
71-
},
72-
],
38+
externals,
7339

7440
mode: env.production ? 'production' : 'development',
7541

.github/workflows/ci.yml

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ on:
1414
jobs:
1515
build:
1616
runs-on: ubuntu-latest
17+
outputs:
18+
e2e-matrix: ${{ steps.resolve-versions.outputs.matrix }}
1719
steps:
1820
- uses: actions/checkout@v6
1921
- name: Setup Node.js environment
@@ -22,6 +24,12 @@ jobs:
2224
node-version: '22'
2325
cache: 'npm'
2426

27+
- name: Cache node_modules for future jobs
28+
uses: actions/cache@v4
29+
with:
30+
path: node_modules
31+
key: node-modules-${{ hashFiles('package-lock.json') }}
32+
2533
- name: Install dependencies
2634
run: npm ci
2735

@@ -34,15 +42,6 @@ jobs:
3442
- name: Build frontend
3543
run: npm run build
3644

37-
- name: Start grafana docker
38-
run: docker compose up -d
39-
40-
- name: Run e2e tests
41-
run: npm run e2e
42-
43-
- name: Stop grafana docker
44-
run: docker compose down
45-
4645
- name: Check for backend
4746
id: check-for-backend
4847
run: |
@@ -70,3 +69,69 @@ jobs:
7069
with:
7170
version: latest
7271
args: buildAll
72+
73+
- name: Upload build artifact
74+
uses: actions/upload-artifact@v4
75+
with:
76+
name: dist
77+
path: dist/
78+
79+
- name: Resolve Grafana E2E versions
80+
id: resolve-versions
81+
uses: grafana/plugin-actions/e2e-version@e2e-version/v1.2.1
82+
with:
83+
skip-grafana-react-19-preview-image: false
84+
85+
e2e:
86+
runs-on: ubuntu-latest
87+
timeout-minutes: 15
88+
needs: build
89+
strategy:
90+
fail-fast: false
91+
matrix:
92+
GRAFANA_IMAGE: ${{ fromJson(needs.build.outputs.e2e-matrix) }}
93+
QUICKWIT_VERSION: [edge]
94+
steps:
95+
- uses: actions/checkout@v6
96+
97+
- name: Download build artifact
98+
uses: actions/download-artifact@v4
99+
with:
100+
name: dist
101+
path: dist/
102+
103+
- name: Restore executable permissions
104+
run: chmod +x dist/gpx_quickwit_*
105+
106+
- name: Setup Node.js environment
107+
uses: actions/setup-node@v6
108+
with:
109+
node-version: '22'
110+
111+
- name: Restore node_modules
112+
uses: actions/cache/restore@v4
113+
with:
114+
path: node_modules
115+
key: node-modules-${{ hashFiles('package-lock.json') }}
116+
117+
- name: Install Playwright
118+
run: npx playwright install --with-deps chromium
119+
120+
- name: Start Grafana (${{ matrix.GRAFANA_IMAGE.name }}:${{ matrix.GRAFANA_IMAGE.version }}) + Quickwit (${{ matrix.QUICKWIT_VERSION }})
121+
run: docker compose up -d --build
122+
env:
123+
GRAFANA_VERSION: ${{ matrix.GRAFANA_IMAGE.version }}
124+
GRAFANA_IMAGE: ${{ matrix.GRAFANA_IMAGE.name }}
125+
QUICKWIT_VERSION: ${{ matrix.QUICKWIT_VERSION }}
126+
127+
- name: Wait for Grafana and Quickwit to start
128+
run: |
129+
timeout 60 bash -c 'until curl -sf http://localhost:3000/api/health; do sleep 2; done' || { docker compose logs grafana; exit 1; }
130+
timeout 60 bash -c 'until curl -sf http://localhost:7280/health/readyz; do sleep 2; done' || { docker compose logs quickwit; exit 1; }
131+
132+
- name: Run e2e tests
133+
run: npm run e2e
134+
135+
- name: Stop Grafana
136+
if: always()
137+
run: docker compose down

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ artifacts/
3131
work/
3232
ci/
3333
e2e-results/
34-
**/cypress/videos
35-
**/cypress/report.json
34+
playwright-report/
35+
test-results/
36+
playwright/.auth/
3637

3738
# Editor
3839
.idea

README.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,25 @@ Quickwit 0.8 is compatible with 0.4.x and 0.5.x versions.
3131

3232
You can either download the plugin manually and unzip it into the plugin directory or use the env variable `GF_INSTALL_PLUGINS` to install it.
3333

34+
### 0.5.0 (Latest) for Quickwit 0.8 + Grafana 12.1
35+
36+
`GF_INSTALL_PLUGINS` has been deprecated since 12.1. `GF_PLUGINS_PREINSTALL_SYNC` must be used instead
37+
38+
Run `grafana` container with the env variable:
39+
40+
```bash
41+
docker run -p 3000:3000 -e GF_PLUGINS_PREINSTALL_SYNC="quickwit-quickwit-datasource@0.5.0@https://github.com/quickwit-oss/quickwit-datasource/releases/download/v0.5.0/quickwit-quickwit-datasource-0.5.0.zip" grafana/grafana run
42+
```
43+
44+
Or download the plugin manually and start Grafana
45+
46+
```bash
47+
wget https://github.com/quickwit-oss/quickwit-datasource/releases/download/v0.5.0/quickwit-quickwit-datasource-0.5.0.zip
48+
mkdir -p plugins
49+
unzip quickwit-quickwit-datasource-0.5.0.zip -d plugins/quickwit-quickwit-datasource-0.5.0
50+
docker run -p 3000:3000 -e GF_PATHS_PLUGINS=/data/plugins -v ${PWD}/plugins:/data/plugins grafana/grafana run
51+
```
52+
3453
### 0.5.0 (Latest) for Quickwit 0.8 + Grafana 11
3554

3655
Run `grafana` container with the env variable:
@@ -102,6 +121,7 @@ To configure the Quickwit datasource, you need to provide the following informat
102121
- The index name.
103122
- The log message field name (optional). This is the field displayed in the explorer view.
104123
- The log level field name (optional). It must be a fast field.
124+
- The related logs or traces datasource (optional). This enables trace-to-logs and log-to-trace links when logs and traces are stored in separate Quickwit indexes.
105125

106126
### With Grafana UI
107127

@@ -122,6 +142,112 @@ datasources:
122142
logLevelField: severity_text
123143
```
124144
145+
### Logs and traces in separate indexes
146+
147+
When logs and traces are stored in different Quickwit indexes, configure one datasource per index and link them with `logsDatasourceUid` and `tracesDatasourceUid`.
148+
149+
```yaml
150+
apiVersion: 1
151+
152+
datasources:
153+
- name: Quickwit Logs
154+
uid: quickwit-logs
155+
type: quickwit-quickwit-datasource
156+
url: http://localhost:7280/api/v1
157+
jsonData:
158+
index: 'otel-logs-v0_9'
159+
logMessageField: body.message
160+
logLevelField: severity_text
161+
tracesDatasourceUid: quickwit-traces
162+
tracesDatasourceName: Quickwit Traces
163+
164+
- name: Quickwit Traces
165+
uid: quickwit-traces
166+
type: quickwit-quickwit-datasource
167+
url: http://localhost:7280/api/v1
168+
jsonData:
169+
index: 'otel-traces-v0_9'
170+
logsDatasourceUid: quickwit-logs
171+
logsDatasourceName: Quickwit Logs
172+
```
173+
174+
## Traces
175+
176+
The query editor has two trace query types:
177+
178+
- **Trace search** scans matching spans and returns one row per trace. Use this to find trace IDs by Lucene query, service, operation, status, or attributes.
179+
- **Traces** returns a full trace frame for Grafana's trace viewer. Use this with a trace ID query such as `trace_id:abc123`.
180+
181+
The trace parser expects Quickwit OpenTelemetry trace fields such as:
182+
183+
- `trace_id`
184+
- `span_id`
185+
- `parent_span_id`
186+
- `service_name`
187+
- `span_name`
188+
- `span_start_timestamp_nanos`
189+
- `span_duration_millis` or `span_end_timestamp_nanos`
190+
191+
It also reads optional fields for richer trace rendering:
192+
193+
- `resource_attributes` for service tags
194+
- `span_attributes` for span tags, including `service.peer.name` and `peer.service`
195+
- `span_status` for error status and warnings
196+
- `events` for span events and exception stack traces
197+
- `links` for span references
198+
- `scope_name` and `scope_version` for instrumentation library details
199+
200+
Trace responses include:
201+
202+
- Grafana trace frames for the trace viewer.
203+
- Node graph frames that summarize service-to-service calls.
204+
- Span warnings for error status and dropped attributes/events/links.
205+
- Span event details and exception stack traces.
206+
- Stable per-service node colors in the node graph.
207+
208+
### Trace/log correlations
209+
210+
Trace-to-logs links are attached to each trace span. They query the configured logs datasource with:
211+
212+
```text
213+
trace_id:${__span.traceId} AND span_id:${__span.spanId}
214+
```
215+
216+
Log-to-trace links are attached to log fields named:
217+
218+
- `trace_id`
219+
- `traceID`
220+
- `traceId`
221+
- `attributes.trace_id`
222+
223+
They open the configured traces datasource with:
224+
225+
```text
226+
trace_id:${__value.raw}
227+
```
228+
229+
### Local trace fixtures
230+
231+
For local testing, use the fixture script:
232+
233+
```bash
234+
QUICKWIT_URL=http://127.0.0.1:7280/api/v1 ./scripts/ingest-multi-service-traces.sh
235+
```
236+
237+
It writes two multi-service traces into `otel-traces-v0_9` and matching correlated logs into `otel-logs-v0_9`.
238+
239+
In **Trace search**, filter the fixture data with:
240+
241+
```text
242+
span_attributes.fixture:multi-service-trace
243+
```
244+
245+
In **Traces**, open a returned trace ID with:
246+
247+
```text
248+
trace_id:<trace id>
249+
```
250+
125251
## Features
126252

127253
- Explore view.
@@ -130,6 +256,9 @@ datasources:
130256
- Adhoc filters.
131257
- Annotations
132258
- Explore Log Context.
259+
- Trace search and trace view.
260+
- Trace-to-logs and log-to-trace links.
261+
- Service node graph for trace results.
133262
- [Alerting](https://grafana.com/docs/grafana/latest/alerting/).
134263

135264
## FAQ and Limitations

cypress.json

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)