@@ -5,7 +5,7 @@ for [Grafana](https://grafana.com/) allows the plotting of time-series data
5
5
that's stored in [ Zed lakes] ( https://zed.brimdata.io/docs/commands/zed/ ) .
6
6
7
7
---
8
- * [ Configuration] ( #configuration )
8
+ * [ Install & Configuration] ( #install-- configuration )
9
9
* [ Best Practices] ( #best-practices )
10
10
* [ Example Usage in Dashboards] ( #example-usage-in-dashboards )
11
11
+ [ One row per metric] ( #one-row-per-metric )
@@ -16,20 +16,77 @@ that's stored in [Zed lakes](https://zed.brimdata.io/docs/commands/zed/).
16
16
+ [ Annotations] ( #annotations )
17
17
+ [ Logs] ( #logs )
18
18
* [ Debugging] ( #debugging )
19
+ * [ Why Unsigned?] ( #why-unsigned )
19
20
* [ Contributing] ( #contributing )
20
21
* [ Join the Community] ( #join-the-community )
21
22
---
22
23
23
- ## Configuration
24
+ ## Quick Start
24
25
25
- The Zed data source can be added in Grafana via the
26
- ** Configuration > Data Sources** menu. If a lake service is listening locally
27
- on the default TCP port ` 9867 ` (as is typical for the lake launched by the
28
- [ Zui app] ( https://zui.brimdata.io/ ) or when
29
- [ ` zed serve ` ] ( https://zed.brimdata.io/docs/commands/zed#213-serve ) is run by hand) the default URL setting can
30
- be used. If your lake is listening elsewhere (e.g., with [ Zui Insiders] ( https://github.com/brimdata/zui-insiders )
31
- it's at http://localhost:9988 ) change the URL setting appropriately. When
32
- ** Save & test** is clicked, the plugin will attempt to return the value from
26
+ Want to see if this plugin is what you're looking for? Watch
27
+ [ this quick video] ( https://www.youtube.com/watch?v=xxxxxxxx )
28
+ to see how easy it is to install the plugin and make your first chart from Zed
29
+ data in Grafana. Then keep reading for best practices to plot your
30
+ sophisticated, real-world data.
31
+
32
+ For easy cut & paste, here's the command line used in the video to generate
33
+ your own simple test data.
34
+
35
+ ```
36
+ NUM=1; while [ $NUM -le 10 ]; do echo $NUM | /opt/Zui/resources/app.asar.unpacked/zdeps/zq -z 'yield {ts: now(), num:this}' -; sleep 1; NUM=`expr $NUM + 1`; done | tee data.zson
37
+ ```
38
+
39
+ ## Install & Configuration
40
+
41
+ As an example environment, here the plugin is shown being installed on a fresh
42
+ [ Grafana installation on Linux] ( https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/ ) .
43
+ For specifics regarding other platforms or adding a plugin into an existing
44
+ environment, refer to the [ Grafana documentation] ( https://grafana.com/docs/grafana/latest/setup-grafana/installation/ ) .
45
+
46
+
47
+ To download and install the latest plugin release, run the following command:
48
+
49
+ ```
50
+ sudo grafana-cli \
51
+ --pluginUrl https://github.com/brimdata/grafana-zed-datasource/releases/latest/download/brimdata-zed-datasource.zip \
52
+ plugins install brimdata-zed-datasource
53
+ ```
54
+
55
+ As the plugin is not currently signed ([ learn why] ( #why-unsigned ) ) an
56
+ additional [ configuration change] ( https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#allow_loading_unsigned_plugins )
57
+ is required to allow the Zed plugin to run. Modify the config file
58
+ ` /etc/grafana/grafana.ini ` , removing the leading semicolon to
59
+ uncomment this line and then edit it to read:
60
+
61
+ ```
62
+ allow_loading_unsigned_plugins = brimdata-zed-datasource
63
+ ```
64
+
65
+ Restart the Grafana service for the modified config to take effect.
66
+
67
+ ```
68
+ sudo systemctl restart grafana-server
69
+ ```
70
+
71
+ To confirm the plugin has loaded successfully, look for a line like the
72
+ following in ` /var/log/syslog ` .
73
+
74
+ ```
75
+ Jun 7 09:37:16 ubuntu-22 grafana[22412]: logger=plugin.loader t=2023-06-07T09:37:16.885366925-07:00 level=info msg="Plugin registered" pluginID=brimdata-zed-datasource
76
+ ```
77
+
78
+ Once inside Grafana (default: http://localhost:3000 ), the Zed data source
79
+ can be added by navigating to ** Administration > Data Sources > Add data source** ,
80
+ then click the entry for Zed (typically at the bottom of the list).
81
+
82
+ If a Zed lake service is listening locally on the default TCP port ` 9867 `
83
+ (as is typical for the lake launched by the [ Zui app] ( https://zui.brimdata.io/ )
84
+ or when [ ` zed serve ` ] ( https://zed.brimdata.io/docs/commands/zed#213-serve ) is
85
+ run with default settings) the default URL setting can be used. If your lake
86
+ is listening elsewhere (e.g., with [ Zui Insiders] ( https://github.com/brimdata/zui-insiders )
87
+ it's at http://localhost:9988 ) change the URL setting as necessary.
88
+
89
+ When ** Save & test** is clicked, the plugin will query the value from
33
90
the lake service's ` /version ` endpoint. If successful, the version will be shown
34
91
and the plugin is ready for use in dashboard panel queries.
35
92
@@ -44,23 +101,26 @@ data at moderate scale.
44
101
In its current state, the plugin relies on the use of Zed queries that
45
102
prepare data for easy transformation to the
46
103
[ data frames] ( https://grafana.com/docs/grafana/latest/developers/plugins/data-frames/ )
47
- that Grafana ultimately uses for rendering plots. Some best practices that
48
- help achieve this:
104
+ that Grafana uses for rendering plots. Some best practices that help achieve this:
49
105
50
- 1 . ** The field used as the timestamp for your time-series data should ideally be
51
- your [ pool key] ( https://zed.brimdata.io/docs/commands/zed#143-pool-key ) .**
106
+ 1 . ** The Time Field that contains timestamps for your data must be of Zed's
107
+ ` time ` type.**
108
+
109
+ 2 . ** The Time Field should ideally be your
110
+ [ pool key] ( https://zed.brimdata.io/docs/commands/zed#143-pool-key ) .**
52
111
53
112
With this pool configuration, the time range portion of queries initiated
54
- via the Grafana dashboard will scan only the minimal number of data
55
- objects in the Zed lake relevant to the query.
113
+ via the Grafana dashboard will scan the minimal number of data objects in
114
+ the Zed lake relevant to the query.
56
115
57
- 2 . ** If possible, use ` ts ` as the name for your timestamp field .**
116
+ 3 . ** If possible, use ` ts ` as the name for your Time Field .**
58
117
59
118
This field name matches the "out of the box" default settings for the plugin.
60
119
However, the plugin can easily be configured to adapt to a different field
61
120
name.
62
121
63
- 3 . ** Your time-series data should be of a single [ shape] ( https://zed.brimdata.io/docs/language/overview#10-shaping ) .**
122
+ 4 . ** Your time-series data should be of a single
123
+ [ shape] ( https://zed.brimdata.io/docs/language/overview#10-shaping ) .**
64
124
65
125
Grafana's columnar data frames need to be constructed with a specific list
66
126
of expected fields. Therefore the count of shapes returned by a query is
@@ -71,13 +131,15 @@ your [pool key](https://zed.brimdata.io/docs/commands/zed#143-pool-key).**
71
131
[ ` fuse ` operator] ( https://zed.brimdata.io/docs/language/operators/fuse ) to
72
132
combine the entire query result into a single, wider shape.
73
133
74
- 4 . ** Store data in top-level fields of primitive types.**
134
+ 5 . ** Store data in top-level fields of primitive types.**
75
135
76
136
Of the fields in a response to a Zed query, the values passed on to Grafana
77
137
by the plugin will be top-level fields of Zed's
78
138
[ primitive types] ( https://zed.brimdata.io/docs/formats/zed#1-primitive-types ) .
79
- If you need to use values from complex types in Grafana, modify your Zed
80
- query to make them available as top-level fields, e.g., by using the
139
+ If you need to use values from
140
+ [ complex Zed types] ( https://zed.brimdata.io/docs/formats/zed#2-complex-types )
141
+ in Grafana, modify your Zed query to make them available as top-level fields,
142
+ e.g., by using the
81
143
[ ` put ` operator] ( https://zed.brimdata.io/docs/language/operators/put ) .
82
144
83
145
Next we'll walk through some real world examples that leverage these best
@@ -93,9 +155,9 @@ time-series data to illustrate the concepts.
93
155
94
156
### One row per metric
95
157
96
- An example that uses this approach is the
158
+ Some example data that uses this approach is the
97
159
[ weekly fuel prices (all data)] ( https://dgsaie.mise.gov.it/open_data_export.php?export-id=4&export-type=csv )
98
- link in the [ Italian fuel price data] ( https://dgsaie.mise.gov.it/open-data ) that's freely
160
+ link in the [ Italian fuel price data] ( https://dgsaie.mise.gov.it/open-data ) , which is freely
99
161
available under the [ IODL 2.0 license] ( https://it.wikipedia.org/wiki/Italian_Open_Data_License ) .
100
162
We'll start by downloading a copy with the English language column headers and
101
163
peek at the data in its original form.
@@ -120,16 +182,14 @@ SURVEY_DATE,PRODUCT_ID,PRODUCT_NAME,PRICE,VAT,EXCISE,NET,CHANGE
120
182
121
183
Per the approach, we see that the date stamp is repeated for the measurement of
122
184
each of the six different fuel types. Also, being CSV data, this date field
123
- begins life as a mere string and therefore should be transformed to the Zed
124
- ` time ` type as we store it in the lake. This will allow the values
125
- to be used in time range selections in Grafana that will then be used in the
126
- generated Zed queries that gather points for plotting.
185
+ begins life as a mere string and therefore must be transformed to the Zed
186
+ ` time ` type as we store it in the lake.
127
187
128
- Taking this into account, we'll perform some preprocessing with [ ` zq ` ] ( https://zed.brimdata.io/docs/commands/zq ) to
129
- prepare the timestamp field and also isolate a subset of the fields, then
130
- ultimately load the data into a pool in our Zed lake. For convenience, we'll
131
- use ` ts ` as the name of the transformed time field since this is the plugin's
132
- default.
188
+ Taking this into account, we'll perform some preprocessing with
189
+ [ ` zq ` ] ( https://zed.brimdata.io/docs/commands/zq ) to prepare the Time
190
+ Field and also isolate a subset of other fields, then ultimately load the data
191
+ into a pool in our Zed lake. For convenience, we'll use ` ts ` as the name of
192
+ the transformed time field since this is the plugin's default.
133
193
134
194
```
135
195
$ zed create prices1
@@ -191,8 +251,8 @@ SURVEY_DATE,EURO-SUPER_95,AUTOMOTIVE_GAS_OIL,LPG,HEATING_GAS_OIL,RESIDUAL_FUEL_O
191
251
192
252
As we see, there's now a separate column in the CSV file for each category of fuel
193
253
and each row of measurements appears with a single, shared date stamp. We'll
194
- create a separate pool and once again transform the date stamp to a Zed ` time `
195
- field as we load it into our lake.
254
+ create another pool and once again transform the date stamp to a field of Zed's
255
+ ` time ` type as we load it into our lake.
196
256
197
257
```
198
258
$ zed create prices2
@@ -217,8 +277,9 @@ $ zed query -Z 'from prices2 | head 1'
217
277
218
278
Because Grafana defaults to plotting all numeric fields, all six appear on our
219
279
chart if we let the plugin use its default Zed query (` * ` ) that pulls all points
220
- from the pool. The only setting we had to change in our panel configuration was
221
- to specify the pool name "prices2".
280
+ from the pool that are in the dashboard's current selected time range. The only
281
+ change from defaults we had to make when configuring our new panel was specifying
282
+ the pool name "prices2".
222
283
223
284
![ Example with many metrics per row] ( https://github.com/brimdata/grafana-zed-datasource/raw/main/src/img/prices2.png )
224
285
@@ -237,9 +298,9 @@ rename this["Euro-Super 95"] := this["EURO-SUPER_95"],
237
298
238
299
Now that we've seen the second approach makes it easier to plot, if you find
239
300
yourself with data that's already stored using the first approach, you could use
240
- Zed like what's shown below to transform to the second approach. This idiom could
241
- be used to preprocess the data before loading it into yet another pool or you
242
- could use it as part of a Zed query in your Grafana panel config.
301
+ a Zed query like what's shown below to transform to the second approach. This
302
+ idiom could be used to preprocess the data before loading it into yet another
303
+ pool, or you could use it as part of a Zed query in your Grafana panel config.
243
304
244
305
```
245
306
$ zed query -Z 'from prices1
@@ -281,13 +342,13 @@ Building on our prior example, here we've defined a multi-value variable called
281
342
282
343
![ Custom variable config] ( https://github.com/brimdata/grafana-zed-datasource/raw/main/src/img/custom-variable-config.png )
283
344
284
- Returning to our dashboard, we now can enter a Zed query that uses
345
+ Returning to our dashboard, we now can enter a Zed query that uses the
285
346
[ ` cut ` operator] ( https://zed.brimdata.io/docs/language/operators/cut ) to
286
- isolate only the timestamp field and variable reference that expands into a
347
+ isolate only the Time Field and a variable reference that expands to a
287
348
comma-separated field list required by ` cut ` . Notice that we once again made
288
349
use of [ field dereferencing with indexing] ( https://zed.brimdata.io/docs/language/overview#75-field-dereference )
289
350
for the field ` EURO-SUPER_95 ` since it can't be referenced as an identifier due
290
- to its use of the character ` - ` .
351
+ to its name containing the character ` - ` .
291
352
292
353
![ Custom variable in panel] ( https://github.com/brimdata/grafana-zed-datasource/raw/main/src/img/custom-variable-in-panel.png )
293
354
@@ -320,7 +381,7 @@ Grafana based on the current plot width and slides easily into the `span`
320
381
parameter of Zed's [ ` bucket() ` function] ( https://zed.brimdata.io/docs/language/functions/bucket ) .
321
382
322
383
We'll once again start by creating a pool and loading our raw test data. Since
323
- this data already has a ` time ` -typed field called ` ts ` , we don't need to
384
+ this data already has a ` time ` -typed Time Field called ` ts ` , we don't need to
324
385
perform the same preprocessing of the timestamp we did previously.
325
386
326
387
```
@@ -350,31 +411,33 @@ count() by ts:=bucket(ts,$__interval),method
350
411
351
412
![ HTTP method count panel] ( https://github.com/brimdata/grafana-zed-datasource/raw/main/src/img/http-method-count.png )
352
413
353
- To see the effect of the ` $__interval ` variable, click the ** Query Inspector **
354
- button and click ** Refresh ** on the ** Query ** tab. Here we can see the full
355
- query assembled by the plugin that was sent to the Zed lake API based on the
356
- current panel settings. We can see that the ` $__interval ` variable was
357
- replaced with a duration string ` 1s ` that reflects 1 -second time buckets.
358
- If you zoom in/out to change the current time range for the plot and recheck
359
- the Query Inspector , you'll see this value change.
414
+ To see the effect of the ` $__interval ` variable, open the Network tab of your
415
+ browser's Developer Tools and click the most recent request issued against the Zed
416
+ lake API's ` query ` endpoint. Here we can see the final query assembled by the
417
+ plugin based on the current panel settings. We can see that the ` $__interval `
418
+ variable was replaced with a duration string ` 2s ` that reflects 2 -second time
419
+ buckets. If you zoom in/out to change the current time range for the plot and
420
+ check again , you'll see this value change.
360
421
361
- ![ Query inspector ] ( https://github.com/brimdata/grafana-zed-datasource/raw/main/src/img/query-inspector .png )
422
+ ![ DevTools Network Tab ] ( https://github.com/brimdata/grafana-zed-datasource/raw/main/src/img/devtools-network-tab .png )
362
423
363
424
To understand what the rest of the Zed is doing, let's look at a sample of
364
425
data from outside Grafana starting with just the aggregation.
365
426
366
427
```
367
428
$ zed query -z 'from http
368
- | count() by ts:=bucket(ts,1s ),method
429
+ | count() by ts:=bucket(ts,2s ),method
369
430
| sort ts'
370
431
371
- {ts:2018-03-24T17:15:20Z,method:"GET",count:63(uint64)}
372
432
{ts:2018-03-24T17:15:20Z,method:"POST",count:1(uint64)}
373
- {ts:2018-03-24T17:15:20Z,method:"PUT",count:1(uint64)}
374
433
{ts:2018-03-24T17:15:20Z,method:"OPTIONS",count:1(uint64)}
375
- {ts:2018-03-24T17:15:21Z,method:"HEAD",count:1(uint64)}
376
- {ts:2018-03-24T17:15:21Z,method:"GET",count:35(uint64)}
377
- {ts:2018-03-24T17:15:21Z,method:"PRI",count:1(uint64)}
434
+ {ts:2018-03-24T17:15:20Z,method:"HEAD",count:1(uint64)}
435
+ {ts:2018-03-24T17:15:20Z,method:"PRI",count:1(uint64)}
436
+ {ts:2018-03-24T17:15:20Z,method:"PUT",count:1(uint64)}
437
+ {ts:2018-03-24T17:15:20Z,method:"GET",count:98(uint64)}
438
+ {ts:2018-03-24T17:15:22Z,method:null(string),count:1(uint64)}
439
+ {ts:2018-03-24T17:15:22Z,method:"POST",count:3(uint64)}
440
+ {ts:2018-03-24T17:15:22Z,method:"GET",count:84(uint64)}
378
441
...
379
442
```
380
443
@@ -466,32 +529,67 @@ our annotations query.
466
529
467
530
## Debugging
468
531
469
- When things are going wrong , the first thing to check is for an alert shown
532
+ When you hit problems , the first thing to check is for an alert shown
470
533
when you hover the mouse pointer over a red triangle in the upper-left corner
471
534
of a panel. The errors you may see here are described in this README and
472
535
should be self-explanatory.
473
536
474
537
![ Hovering over an error message.] ( https://github.com/brimdata/grafana-zed-datasource/raw/main/src/img/error-hover.png )
475
538
476
539
If you can't make sense of the error message, you may find it helpful to look
477
- in Grafana's ** Query Inspector** as shown [ above] ( #aggregations-and-the-__interval-variable ) .
478
- The assembled query shown can then be executed outside of Grafana using
479
- ` zed query ` or in the Zui app to narrow down if it's a problem with how
480
- the query is constructed or if it's a bug/limitation in the plugin or Grafana.
540
+ in the Network tab of your browser's Developer Tools as shown
541
+ [ above] ( #aggregations-and-the-__interval-variable ) . The assembled query shown
542
+ can then be executed outside of Grafana using ` zed query ` or in the Zui app to
543
+ narrow down if it's a problem with how the query is constructed or if it's a
544
+ bug/limitation in the plugin or Grafana.
481
545
482
546
If you're still stuck, come talk to us on the ` #grafana ` channel on the
483
547
[ Brim Data community Slack] ( https://www.brimdata.io/join-slack/ ) or
484
548
[ open an issue] ( https://github.com/brimdata/grafana-zed-datasource/issues ) .
485
549
550
+ ## Why Unsigned?
551
+
552
+ Ideally we'd prefer to have the Zed plugin available in the
553
+ [ public data source plugin directory] ( https://grafana.com/grafana/plugins/?type=datasource )
554
+ to make it easier to find and install. This is predicated on the plugin being
555
+ [ signed] ( https://grafana.com/docs/grafana/latest/developers/plugins/sign-a-plugin/ ) .
556
+ An initial release of the plugin was indeed submitted to the Grafana maintainers
557
+ with the belief it met the criteria for the "community"
558
+ [ plugin signature level] ( https://grafana.com/docs/grafana/latest/developers/plugins/sign-a-plugin/#plugin-signature-levels )
559
+ since, per that page, the dependent [ Zed] ( https://zed.brimdata.io/ ) technology
560
+ is offered to the community free of charge as open source and will continue to be
561
+ indefinitely. However, after initial review of our submission we were pointed
562
+ at [ more extensive legal terms] ( https://grafana.com/legal/plugins/ )
563
+ which explain that to qualify for the community signature level the plugin must
564
+ be "not affiliated with any commercial endeavor". As the corporate sponsor of
565
+ the Zed project, [ Brim Data] ( https://www.brimdata.io/ ) is currently a seed stage startup, and the company
566
+ does hope to one day operate a viable business such as by offering paid services and
567
+ support to users that may want it. Apparently this fact alone is enough to
568
+ disqualify the plugin from eligibility at the "community" level. Furthermore, the
569
+ constraints of being a seed stage startup mean Brim Data cannot currently
570
+ justify the expense of paying the quoted price to be signed at Grafana's
571
+ "commercial" signature level. While this is disappointing, we respect Grafana's
572
+ decision to run their programs as they wish. We are hopeful that they will
573
+ one day change their policies to benefit our combined user base. In the
574
+ meantime, we hope that users may benefit from using the Zed plugin even in
575
+ its atypical "unsigned" state.
576
+
577
+ If you have additional questions or concerns about running "unsigned", or if
578
+ you feel strongly about the plugin being "signed" and have thoughts on how
579
+ to move past the known barriers, please come talk to us in the ` #grafana `
580
+ channel on the [ Brim Data community Slack] ( https://www.brimdata.io/join-slack/ ) .
581
+
486
582
## Contributing
487
583
488
584
Contributions are welcomed! Per common practice, please
489
585
[ open an issue] ( https://github.com/brimdata/grafana-zed-datasource/issues )
490
586
before sending a pull request. If you think your ideas might benefit from
491
- some refinement via Q&A, come talk to us on the
587
+ some refinement via Q&A, come talk to us on the ` #grafana ` channel on the
492
588
[ Brim Data community Slack] ( https://www.brimdata.io/join-slack/ ) .
493
589
494
590
## Join the Community
495
591
496
592
Join the [ Brim Data community Slack] ( https://www.brimdata.io/join-slack/ ) workspace for
497
- announcements, Q&A, and to trade tips!
593
+ announcements, Q&A, and to trade tips. There's a ` #grafana ` channel where you
594
+ can ask questions and get help with this plugin, a ` #zed ` channel for Q&A about the
595
+ Zed language & lake, and more!
0 commit comments