-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.xml
545 lines (476 loc) · 62 KB
/
index.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Butler – About</title>
<link>https://butler.ptarmiganlabs.com/docs/about/</link>
<description>Recent content in About on Butler</description>
<generator>Hugo -- gohugo.io</generator>
<language>en</language>
<atom:link href="https://butler.ptarmiganlabs.com/docs/about/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Docs: Butler</title>
<link>https://butler.ptarmiganlabs.com/docs/about/butler/</link>
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
<guid>https://butler.ptarmiganlabs.com/docs/about/butler/</guid>
<description>
<p>The Butler project is all about adding useful features to the client-managed version of Qlik Sense, also known as Qlik Sense Enterprise on Windows, QSEoW.<br>
Some of the features can be used from Sense load scripts, other features provide integration with 3rd party systems.<br>
Most of Butler&rsquo;s features try to make daily life for a Qlik Sense administrator a bit easier.</p>
<p>The goal is to integrate battle-proven concepts and best-of-breed open-source tools into Butler and thus make them available to developers of Sense apps or those responsible for running Sense clusters.<br>
In some cases it might be possible to use these tools from within Sense also without Butler - in those cases Butler simply tries to make things easier, lowering the barriers to get started and get things done.</p>
<p>There is also a clear goal that Butler should be very configurable. In practice this means that individual features can be turned on/off as needed, improving security and lowering memory usage.</p>
<p>Butler is written in <a href="https://nodejs.org/en/">Node.js</a> and runs on most modern operating systems.<br>
As of version 7.2 Butler offers pre-built binaries for Windows, macOS and Linux§, meaning that Node.js no longer has to be separately installed to use Butler.<br>
This simplifies things - just download, configure and run.</p>
<p>You can run Butler on the same server as Qlik Sense, in a Docker container on a Linux server, in Kubernetes, on Mac OS, on Raspberry Pi (not a good idea.. but possible and proven to work).</p>
<p>Butler is a member of a group of tools collectively referred to as the &ldquo;Butler family&rdquo;, more info is available <a href="https://butler.ptarmiganlabs.com/docs/about/butler-family">here</a>.</p>
<p>This picture might be useful to understand what Butler does and how it fits into the larger system map around Qlik Sense:</p>
<p><img src="https://butler.ptarmiganlabs.com/img/butler-system-overview-1.png" alt="alt text" title="Butler high level system overview"></p>
</description>
</item>
<item>
<title>Docs: Use cases</title>
<link>https://butler.ptarmiganlabs.com/docs/about/use-cases/</link>
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
<guid>https://butler.ptarmiganlabs.com/docs/about/use-cases/</guid>
<description>
<ul>
<li><a href="#instant-notifications-when-reload-tasks-fail-or-are-stopped">Instant notifications when reload tasks fail or are stopped</a></li>
<li><a href="#forward-failed-reload-events-to-incident-management-systems-new-relic-signl4">Forward failed reload events to incident management systems (New Relic, Signl4)</a></li>
<li><a href="#use-influxdbgrafana-or-new-relic-to-track-butler-memory-usage">Use InfluxDB/Grafana or New Relic to track Butler memory usage</a></li>
<li><a href="#save-a-copy-of-the-complete-reload-log-for-all-failed-reload-tasks">Save a copy of the complete reload log for all failed reload tasks</a></li>
<li><a href="#start-reload-tasks-from-load-script-or-from-upstream-systems">Start reload tasks from load script or from upstream systems</a></li>
<li><a href="#start-any-reload-task-from-within-any-qlik-sense-or-web-app">Start any reload task from within any Qlik Sense or web app</a></li>
<li><a href="#start-reload-tasks-via-rest-api-based-on-task-tags-or-custom-properties">Start reload tasks via REST API based on task tags or custom properties</a></li>
<li><a href="#trigger-fullpartial-app-reloads-from-load-script-or-upstream-systems">Trigger full/partial app reloads from load script or upstream systems</a></li>
<li><a href="#flexible-scheduling-of-app-reloads-in-qlik-sense-enterprise-on-windows">Flexible scheduling of app reloads in Qlik Sense Enterprise on Windows</a></li>
<li><a href="#passing-parameters-between-reload-tasks">Passing parameters between reload tasks</a></li>
<li><a href="#storing-state-across-several-apps">Storing state across several apps</a>
<ul>
<li><a href="#time-to-live-ttl-for-key-value-pairs">Time-to-live (TTL) for key-value pairs</a></li>
</ul>
</li>
<li><a href="#make-new-data-reach-end-users-as-quickly-as-possible">Make new data reach end users as quickly as possible</a></li>
<li><a href="#using-mqtt-to-notify-downstream-systems-that-sense-is-done-processing-data">Using MQTT to notify downstream systems that Sense is done processing data</a></li>
<li><a href="#create-directories-copymovedelete-files">Create directories, copy/move/delete files</a></li>
<li><a href="#extract-metadata-for-apps">Extract metadata for apps</a></li>
<li><a href="#easily-post-messages-to-slack">Easily post messages to Slack</a></li>
<li><a href="#monitor-windows-services">Monitor Windows services</a></li>
<li><a href="#monitor-and-release-qlik-sense-user-licenses">Monitor and release Qlik Sense user licenses</a></li>
</ul>
<h2 id="instant-notifications-when-reload-tasks-fail-or-are-stopped">Instant notifications when reload tasks fail or are stopped</h2>
<p><strong>Information about failing tasks</strong> can be sent as emails, to Microsoft Teams, Slack, as MQTT messages or outgoing webhooks.</p>
<p>Email, Slack and MS Teams notifications all use a templating concept where HTML/Markdown template files describe what the alert message should look like. Before the alert is sent the template is populated with actual data from the failed reload task.</p>
<p>Both subject and body of email can use the template fields.</p>
<p>For both Slack and Teams there are options to use more flexible/configurable alert formats and more basic pre-configured alerts.</p>
<p>The result is a very poweful tool for QSEoW sysadmins, who get real-time insight into what&rsquo;s happening with respect to task execution.</p>
<p>More info <a href="https://butler.ptarmiganlabs.com/docs/getting-started/setup/reload-alerts/">here</a>.</p>
<h2 id="forward-failed-reload-events-to-incident-management-systems-new-relic-signl4">Forward failed reload events to incident management systems (New Relic, Signl4)</h2>
<p>Butler offers advanced failed reload alerts via Slack, Teams, email and outgoing webhooks.<br>
Configurable templates means you can customize emails/Teams/Slack messages.</p>
<p>Sometimes you want a bit more structure though.<br>
This is especially true when Sense is used in the enterprise.</p>
<p>Butler integrates with both <a href="https://www.signl4.com">Signl4</a> and <a href="https://newrelic.com">New Relic</a>.<br>
Both offer incident management features on both the web and via mobile clients.</p>
<p>Information about failed/aborted reloads can be sent to one or more New Relic accounts.<br>
Tags for the reload task and associated app is sent to New Relic as metadata for the event/log entry that&rsquo;s created there.</p>
<h2 id="use-influxdbgrafana-or-new-relic-to-track-butler-memory-usage">Use InfluxDB/Grafana or New Relic to track Butler memory usage</h2>
<p>Butler can be configured to log its own memory usage to <a href="https://www.influxdata.com/products/">InfluxDB</a>, from where it can be visualised using <a href="https://grafana.com">Grafana</a>.</p>
<p>If you prefer using <a href="https://newrelic.com">New Relic One</a> that&rsquo;s possible too - sending Butler memory metrics to New Relic is super simple: Just add your New Relic credentials in the YAML config file or as command line options when starting Butler and you&rsquo;re set.</p>
<h2 id="save-a-copy-of-the-complete-reload-log-for-all-failed-reload-tasks">Save a copy of the complete reload log for all failed reload tasks</h2>
<p>Let&rsquo;s say a scheduled reload task fails.</p>
<p>This can happen due to lots of reasons, from uncontrollable events that are impossible to predict to bugs in the script of a Sense app.</p>
<p>No matter what the cause is, as a Sense administrator you probably want to investigate the script reload logs.</p>
<p>Butler can send notifications (Slack, Teams, email, webhooks, &hellip;) when reloads fail.<br>
These notifications can include the last 20-30-40 lines of the script log and this usually gives a good idea of what caused the reload to fail.</p>
<p>But what if you want to look at the <em>complete</em> reload log of that failed app reload?</p>
<p>So far you would have to dig into the log directory on the Sense server, find that specific reload log among potentially thousands of other log files. Not very effective.</p>
<p>As of version 7.2 Butler can store a copy of the complete reload log in a directory that you specify.<br>
The log files are stored in separate directories, one for each date.<br>
This makes it easy to find the log file you are interested in.</p>
<h2 id="start-reload-tasks-from-load-script-or-from-upstream-systems">Start reload tasks from load script or from upstream systems</h2>
<p>Trigger Sense reload tasks from a reload script: This makes it possible to start different Sense tasks based on what data has been read from a database, what time of day it is etc.<br>
Starting a task from the reload script is as easy as <code>Call StartTask('fbf645f0-0c92-40a4-af9a-6e3eb1d3c35c')</code>.</p>
<p>Trigger Sense reloads from external systems: When new data is available in a source database, that database can trigger a reload in Sense, and the data is loaded from the database into Sense. This way delays caused by Sense polling for data are minimized and data arrives at end users as quickly as possible.</p>
<p>Starting reload tasks using REST API is described <a href="https://butler.ptarmiganlabs.com/docs/examples/start-task/start-task-from-rest/">here</a>.<br>
Using MQTT messages to achieve this is described <a href="https://butler.ptarmiganlabs.com/docs/examples/start-task/start-task-from-mqtt/">here</a>.</p>
<h2 id="start-any-reload-task-from-within-any-qlik-sense-or-web-app">Start any reload task from within any Qlik Sense or web app</h2>
<p>Some HTML and Javascript magic is also needed, but given Butler&rsquo;s start-task API it&rsquo;s pretty easy to set up a button in a Sense app (or any web app!) to start any Sense reload task.</p>
<p>This can for example be used to allow end users to start an Extract-Transform when they (the user) need refreshed data.</p>
<p>More info <a href="https://butler.ptarmiganlabs.com/docs/examples/start-task/start-task-from-rest/">here</a>.</p>
<h2 id="start-reload-tasks-via-rest-api-based-on-task-tags-or-custom-properties">Start reload tasks via REST API based on task tags or custom properties</h2>
<p>Using tags and/or custom properties to identify what tasks should be started can be easier than having to know the tasks IDs.
This both makes it easier for 3rd party systems to start Qlik Sense tasks and easier for Sense admins to manage which tasks should be startable by 3rd party systems.</p>
<p>More info in <a href="https://butler.ptarmiganlabs.com/docs/concepts/start-sense-tasks/">Concepts</a> and <a href="https://butler.ptarmiganlabs.com/docs/examples/start-task/">Examples</a> sections.</p>
<h2 id="trigger-fullpartial-app-reloads-from-load-script-or-upstream-systems">Trigger full/partial app reloads from load script or upstream systems</h2>
<p>Sometimes you just want to reload an app without also having to create a reload task.<br>
When it comes to partial app reloads it&rsquo;s not even possible to do these from a Sense reload task.</p>
<p>Butler&rsquo;s API makes prvovides a solution: Just pass in an app ID to reload together with task IDs of the tasks that should be started when the app is done reloading (different tasks can be started depending on app reload success or failure).</p>
<p>The partial reload feature is of special interest as it can be used to trigger faster incremental execution of of Extract-Transform reload chains. Great for keeping data in Sense apps updated during the course of a day!</p>
<p>More info <a href="https://butler.ptarmiganlabs.com/docs/examples/sense-demo-apps/partial-loads/">here</a>.</p>
<h2 id="flexible-scheduling-of-app-reloads-in-qlik-sense-enterprise-on-windows">Flexible scheduling of app reloads in Qlik Sense Enterprise on Windows</h2>
<p>Using the scheduler built into Qlik Sense you can&rsquo;t for example create schedules that are limited to a parts of a day.<br>
This is a pretty common scenario though - you want to reload an app hourly from say 3 am to 3 pm.</p>
<p>You <em>can</em> set this up in Sense, but it involves creating <em>a lot</em> of triggers for the reload task, which becomes a nightmare to maintain.</p>
<p><a href="https://butler.ptarmiganlabs.com/docs/concepts/scheduler">Butler&rsquo;s task scheduler</a> is built on Cron, which has been used in Linux for decades. Battle proven and very flexible.</p>
<h2 id="passing-parameters-between-reload-tasks">Passing parameters between reload tasks</h2>
<p>This has always been hard both in QlikView and Sense.</p>
<p><a href="https://butler.ptarmiganlabs.com/docs/concepts/key-value/">Butler&rsquo;s key-value store</a> makes it much easier to pass values from one app to the next in a reload chain.</p>
<h2 id="storing-state-across-several-apps">Storing state across several apps</h2>
<p>The <a href="https://butler.ptarmiganlabs.com/docs/concepts/key-value/">key-value store</a> can also be used to keep state in general across several apps or parts of a Qlik Sense environment.</p>
<p>Maybe a Development cluster needs to share information in real time with the Test and Production clusters?<br>
Easily solved using Butler&rsquo;s key-value store.</p>
<p>A demo showing parameter passing between apps is found <a href="https://butler.ptarmiganlabs.com/docs/examples/reload-chaining/">here</a>.</p>
<h3 id="time-to-live-ttl-for-key-value-pairs">Time-to-live (TTL) for key-value pairs</h3>
<p>Key-value pairs can optionally be set up with a time-to-live (ttl) parameter. If ttl is set, the KV pair will auto-delete when the ttl expires.</p>
<p>The key-value store is described <a href="https://butler.ptarmiganlabs.com/docs/concepts/key-value/">here</a>.</p>
<h2 id="make-new-data-reach-end-users-as-quickly-as-possible">Make new data reach end users as quickly as possible</h2>
<p>See above. Have the upstream data source initiate Sense app reloads, either via Butler&rsquo;s REST API or via MQTT messages sent to Butler.</p>
<h2 id="using-mqtt-to-notify-downstream-systems-that-sense-is-done-processing-data">Using MQTT to notify downstream systems that Sense is done processing data</h2>
<p>Use Butler&rsquo;s API endpoints for MQTT handling to send and receive MQTT publish-subscribe messages.<br>
MQTT (and the pubsub concept in general) is a great way for systems to communicate reliably with each other.</p>
<p>A demo app is available, showing how MQTT messages can be sent from Sense load scripts. More info <a href="https://butler.ptarmiganlabs.com/docs/examples/sense-demo-apps/publish-to-mqtt/">here</a>.</p>
<h2 id="create-directories-copymovedelete-files">Create directories, copy/move/delete files</h2>
<p>In &ldquo;standard mode&rdquo; apps reloading in Qlik Sense Enterprise on Windows can&rsquo;t access the file system of the Sense servers. This is a good thing because it adds a lot of security.</p>
<p>From time to time you need to delete temp QVDs though, or copy or move data files from one directory to another.</p>
<p>Butler has REST API endpoints for these use cases, but as those endpoints are locked down to only work on specific, configurable directiories they don&rsquo;t result in the same security issues as seen in for example QlikView or Sense running in legacy mode.</p>
<p>More info <a href="https://butler.ptarmiganlabs.com/docs/examples/file-copy-move-delete/">here</a>.</p>
<h2 id="extract-metadata-for-apps">Extract metadata for apps</h2>
<p>Exporting apps as JSON can be very useful for backup purposes. Doing regular snapshots of all apps in a Sense cluster is a fast and space-effective way of keeping point-in-time backups.</p>
<p>The <a href="https://butler.ptarmiganlabs.com/docs/reference/rest-api-1/?operationsSorter=alpha">REST API documentation</a> has full docs for the <code>/v4/app/{appId}/dump</code> endpoint.</p>
<h2 id="easily-post-messages-to-slack">Easily post messages to Slack</h2>
<p>Slack messages can include full formatting (web links, text formatting etc), as well as &ldquo;poking&rdquo; users.<br>
I.e. notifying specific Slack users that they have a new message.</p>
<p>Can for example be used to notify user(s) that an app has reloaded with new data, or that some error condition has occured.</p>
<p>More info <a href="https://butler.ptarmiganlabs.com/docs/examples/sense-demo-apps/post-to-slack/">here</a>.</p>
<h2 id="monitor-windows-services">Monitor Windows services</h2>
<p>If Butler is running on Windows (server or even desktop) it can monitor one or more Windows services.<br>
This feature is <strong>not</strong> available when running Butler on Linux, macOS or in Docker.</p>
<p>Monitoring here means tracking the services&rsquo; state and sending messages to email, InfluxDB, New Relic, MQTT, Webhooks, Slack or Teams when services stop or start.</p>
<p>It can for example be used to get alerts if a Qlik Sense service for some reason stops.<br>
The concept is not limited to Qlik Sense services though - any Windows service can be monitored.</p>
<h2 id="monitor-and-release-qlik-sense-user-licenses">Monitor and release Qlik Sense user licenses</h2>
<p>Butler can monitor the usage of Qlik Sense user licenses and store the data in InfluxDB, from where the license data can be visualized in Grafana.
This makes it easy to track (and alert if needed) on the number of used licenses, how many are available and when it&rsquo;s time to get more licenses.</p>
<p>Butler can also automatically release Professional and Analyzer user licenses that have been inactive for a certain period of time.
This is useful in environments where some users use Sense sporadically, for example only during certain times of the year.
In such cases it&rsquo;s a waste of resources to keep the license assigned to the user when it&rsquo;s not being used.</p>
<p>More info <a href="https://butler.ptarmiganlabs.com/docs/concepts/qlik-sense-licenses/">here</a>.</p>
</description>
</item>
<item>
<title>Docs: The Butler family</title>
<link>https://butler.ptarmiganlabs.com/docs/about/butler-family/</link>
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
<guid>https://butler.ptarmiganlabs.com/docs/about/butler-family/</guid>
<description>
<p>Butler started out with a very specific need to start Sense reloads from outside systems.<br>
Over the years a few projects (for example Butler SOS, which simplifies day 2 operations ([<a href="https://www.infoworld.com/article/3442754/why-de-risking-day-2-operations-is-a-smart-business-strategy.html">1</a>], [<a href="https://dzone.com/articles/defining-day-2-operations">2</a>]) have spun off from the original Butler project, and still other projects have been created from scratch to solve specific challenges around developing Sense apps and running Qlik Sense server environments.</p>
<p>All members of the Butler family are available on <a href="https://github.com/ptarmiganlabs">Ptarmigan Labs&rsquo; GitHub page</a>.</p>
<p>Projects with production grade release status are (as of this writing):</p>
<h3 id="butler">Butler</h3>
<p>The original Butler. Offers various utilities that make it easier to develop Sense apps, as well as simplifying day 2 operations.</p>
<p><a href="https:/butler.ptarmiganlabs.com">butler.ptarmiganlabs.com</a>. (This site!)</p>
<h3 id="butler-sos">Butler SOS</h3>
<p>Real-time operational metrics for Qlik Sense. A must-have if you are responsible for a Sense environment with more than a dozen or so users.</p>
<p>Butler SOS makes it possible to detect and alert on issues as they happen, rather than in retrospect much later.</p>
<p>Several storage and visualisation options available, including <a href="https://www.influxdata.com">InfluxDB</a> + <a href="https://grafana.com">Grafana</a>, and <a href="https://newrelic.com">New Relic</a>.</p>
<p><a href="https://butler-sos.ptarmiganlabs.com">butler-sos.ptarmiganlabs.com</a></p>
<h3 id="butler-sheet-icons">Butler Sheet Icons</h3>
<p>Automates the creation of sheet icons for both Qlik Sense Cloud and client-managed Qlik Sense Enterprise on Windows (QSEoW) applications.</p>
<p>It&rsquo;s a cross platform command line tool which given the correct Sense credentials will take screen shots of all sheets in a Sense app (or all apps on a Sense server!), then create thumbnail versions of those screenshots.<br>
Finally those thumbnails will be set as sheet icons.</p>
<p>No more manual screenshot taking, resizing images, navigating hundreds of sheets in dozens of apps.<br>
Start Butler Sheet Icons instead and go get a nice <a href="https://www.swedishfood.com/fika">fika</a>.</p>
<p>The tool can be used stand-along or as part of an automated release process.</p>
<p><a href="https://github.com/ptarmiganlabs/butler-sheet-icons">https://github.com/ptarmiganlabs/butler-sheet-icons</a></p>
<h3 id="ctrl-q">Ctrl-Q</h3>
<p>Given the name of this tool it doesn&rsquo;t sound like a member of the Butler family.<br>
Let&rsquo;s say Ctrl-Q is a sibling of the Butler bunch.</p>
<p>While the Butler tools are (usually) intended to solve and simplify rather specific use cases, Ctrl-Q is aimed at being the lazy Qlik developer&rsquo;s best friend.</p>
<p>Let&rsquo;s say there is some manual, tedious, time consuming and error prone activity that a Qlik Sense developer is faced with.<br>
For example importing dozens of apps from QVF files and creating a hundred associated reload tasks.<br>
Ctrl-Q lets you do this with a single command, using definitions in an Excel file. Instead of spending a day on this the actual execution takes a minute or so.</p>
<p>In other words: Ctrl-Q focus on high-value use cases that are difficult or impossible to solve using other tools.</p>
<p><a href="https://github.com/ptarmiganlabs/ctrl-q">github.com/ptarmiganlabs/ctrl-q</a></p>
<h3 id="butler-cw">Butler CW</h3>
<p>Butler Cache Warmer. Cache warming is the process of proactively forcing Sense apps to be loaded into RAM, so they are readily available when users open them.<br>
Using Butler CW is an easy way to make your end users&rsquo; experience of Sense a little better.</p>
<p><a href="https://github.com/ptarmiganlabs/butler-cw">github.com/ptarmiganlabs/butler-cw</a></p>
<h3 id="butler-app-duplicator">Butler App Duplicator</h3>
<p>No matter if you are a single developer creating Sense apps, or have lots of developers doing this, having app templates is a good idea:</p>
<ul>
<li>Lowered barrier of entry for new Sense developers.</li>
<li>Productivity boost when developing Sense apps.</li>
<li>Encouraging a common coding standard across all apps.</li>
</ul>
<p><a href="https://github.com/ptarmiganlabs/butler-app-duplicator">github.com/ptarmiganlabs/butler-app-duplicator</a></p>
<h3 id="butler-spyglass">Butler Spyglass</h3>
<p>This tool is mainly of interest if you have lots of QVDs and apps, but when that&rsquo;s the case it&rsquo;s of paramount importance to understand what apps use which QVDs. In other words what data lineage looks like.</p>
<p>Butler Spyglass also extracts full load scripts for all Sense apps, creating a historical record of all load scripts for all Sense apps.</p>
<p><a href="https://github.com/ptarmiganlabs/butler-spyglass">github.com/ptarmiganlabs/butler-spyglass</a></p>
<h3 id="butler-notifier">Butler Notifier</h3>
<p>This tool makes it easy to tap into the Qlik Sense notification API. From there you can get all kinds of notifications, including task reload failures and changes in session state (user login/logout etc).</p>
<p><a href="https://github.com/ptarmiganlabs/butler-notifier">github.com/ptarmiganlabs/butler-notifier</a></p>
<h3 id="butler-icon-uploader">Butler Icon Uploader</h3>
<p>Visual looks is important when it comes to analytics, and this holds true also for Sense apps.</p>
<p>The Butler Icon Uploader makes it easy to upload icon libraries (for example Font Awesome) to Qlik Sense Enterprise. With such icons available it is then easy for app developers to use professional quality sheet and app icons in their Sense apps.</p>
<p><a href="https://github.com/ptarmiganlabs/butler-icon-upload">github.com/ptarmiganlabs/butler-icon-upload</a></p>
</description>
</item>
<item>
<title>Docs: Versions</title>
<link>https://butler.ptarmiganlabs.com/docs/about/versioning/</link>
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
<guid>https://butler.ptarmiganlabs.com/docs/about/versioning/</guid>
<description>
<div class="pageinfo pageinfo-primary">
<p>In the spirit of not copying information to several places, the version history is kept as annotations of each release on the <a href="https://github.com/ptarmiganlabs/butler/releases">GitHub release page</a>.</p>
<p>Version numbers include up to 3 levels, for example version 4.6.2 (which is a fictitious version):</p>
<p>4 is the <strong>major</strong> version. It is increased when Butler has added major new features, or in other ways changed in major ways. If following this principle, breaking changes should always result in a bumped major version.</p>
<p>6 is the <strong>minor</strong> version. This indicates a smaller update, when one or a few minor features have been added.</p>
<p>2 is the <strong>patch</strong> level. When individual bugs are fixed, these are released with an increased patch level.</p>
<p>Note 1: Major and minor updates usually include bug fixes too.<br>
Note 2: If a version of 5.2 is mentioned, this implicitly means 5.2.0.</p>
</div>
<h2 id="documentation-updates">Documentation updates</h2>
<p>Starting with Butler version 4.0, this documentation site will offer both latest and earlier site versions.</p>
<p>Select which doc site to view in drop-down list in the upper right corner of the page.</p>
</description>
</item>
<item>
<title>Docs: Contribution guidelines</title>
<link>https://butler.ptarmiganlabs.com/docs/about/contributing/</link>
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
<guid>https://butler.ptarmiganlabs.com/docs/about/contributing/</guid>
<description>
<div class="pageinfo pageinfo-primary">
<p>Butler is an open source project, using the <a href="https://choosealicense.com/licenses/mit/">MIT license</a>.</p>
<p>This means that all source code, documentation etc is available as-is, at no cost.</p>
<p><strong>It however also means that anyone interested can - and is encouraged to - contribute to the project!</strong></p>
</div>
<p>Butler is developed in <a href="https://nodejs.org">Node.js</a>, with support from various <a href="https://www.npmjs.com/">NPM</a> modules.</p>
<p>We use <a href="https://gohugo.io/">Hugo</a> to format and generate this documentation site, the <a href="https://github.com/google/docsy">Docsy</a> theme for styling and site structure.<br>
Hugo is an open-source static site generator that provides us with templates, content organisation in a standard directory structure, and a website generation engine. You write the pages in Markdown (or HTML if you want), and Hugo wraps them up into a website.</p>
<p>All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult <a href="https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/about-pull-requests">GitHub Help</a> for more information on using pull requests.</p>
<h2 id="creating-an-issue">Creating an issue</h2>
<p>If you&rsquo;ve found a problem - or have a feature suggestion - with Butler itself or the documentation, but you&rsquo;re not sure how to fix it yourself, please create an issue in the <a href="https://github.com/ptarmiganlabs/butler/issues/new">Butler repo</a>. You can also create an issue about a specific doc page by clicking the <strong>Create Issue</strong> button in the top right hand corner of the page.</p>
<div class="alert alert-warning" role="alert">
<h4 class="alert-heading">Security/Disclosure</h4>
If you discover a serious bug with Butler that may pose a security problem, please disclose it confidentially to <a href="mailto:security@ptarmiganlabs.com">security@ptarmiganlabs.com</a> first, so that it can be assessed and hopefully fixed prior to being exploited. Please do not raise GitHub issues for security-related doubts or problems.
</div>
</description>
</item>
<item>
<title>Docs: Telemetry</title>
<link>https://butler.ptarmiganlabs.com/docs/about/telemetry/</link>
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
<guid>https://butler.ptarmiganlabs.com/docs/about/telemetry/</guid>
<description>
<div class="pageinfo pageinfo-primary">
<p>Sharing telemetry data from Butler is optional.<br>
You can use all Butler features without sharing telemetry data.</p>
<p>That said, if you find the Butler tool useful you are <strong>strongly encouraged</strong> to leave Butler&rsquo;s telemetry feature turned on.<br>
Having access to this data greatly helps the Butler developers when they design new features, fix bugs etc.</p>
<p>The Butler developers care about you - sharing telemetry data is your way of showing you care about them.</p>
<p>Sharing is caring!</p>
</div>
<h2 id="whats-telemetry">What&rsquo;s telemetry</h2>
<p>From <a href="https://en.wikipedia.org/wiki/Telemetry">Wikipedia</a>:</p>
<p><em>Telemetry is the in situ collection of measurements or other data at remote points and their automatic transmission to receiving equipment (telecommunication) for monitoring.</em></p>
<p>In the context of software tools (including Butler) telemetry is often used to describe the process of sending information about the tool itself to some monitoring system.</p>
<h2 id="why-telemetry-in-butler">Why telemetry in Butler</h2>
<p>This is a very, very good question.</p>
<p>For many years there was no telemetry at all in Butler.</p>
<p>Development of new features were driven mainly by what features were needed at the time.<br>
Or the fact that Qlik released some new feature in Sense and Butler was a way to test that new feature from the perspective of the Sense APIs.</p>
<p>That&rsquo;s all good but today Butler is a rather significant tool with features spanning quite different areas (alerting, task scheduling, key-value store and more).</p>
<p>This multitude of features is also one of the core reasons for adding telemetry to Butler:</p>
<div class="pageinfo pageinfo-info">
<ul>
<li>Which Butler APIs and features are actually used out there?</li>
<li>Which operating systems, Node.js versions and hardware platforms is Butler running on?</li>
</ul>
</div>
<p>Without this information the Butler developers will keep working in the dark, not really knowing where to focus their efforts.</p>
<p>On the other hand - <strong>with</strong> access to telemetry data a lot of possibilities open up for the Butler developers:</p>
<ul>
<li>If telemetry shows that no one uses a particular feature, maybe that feature should be scheduled for deprecation?</li>
<li>The opposite of the previous: If lots of users use a specific Butler feature, then that feature is a candidate for future focus and development.</li>
<li>Telemetry will show if lots of users run Butler on old Node.js versions. Knowing this its possible to set a migration schedule for what Node.js versions are supported - avoiding hard errors when some old Node.js version is no longer supported by Butler.</li>
<li>Same thing for understanding what operating systems Butler runs (and should be supported) on.</li>
</ul>
<h3 id="configuring-butlers-telemetry">Configuring Butler&rsquo;s telemetry</h3>
<p>Instructions <a href="https://butler.ptarmiganlabs.com/docs/getting-started/setup/telemetry/">here</a>.</p>
<h2 id="the-details">The details</h2>
<div class="alert alert-primary" role="alert">
<h4 class="alert-heading">What's shared</h4>
<p>The telemetry data includes the following:</p>
<ol>
<li><strong>Information about what API endpoints are enabled in the Butler config file.</strong><br>
<em>Why: This tells the Butler developers which features are used and which aren&rsquo;t. This is critical information when it comes to planning where to focus future development efforts.</em></li>
<li><strong>Information about what features are enabled and which are disabled.</strong><br>
<em>Why: Same as above. Knowing which features are used (and are thus important) allows the Butler developers to better plan future work.</em></li>
<li><strong>Information about Butler&rsquo;s execution environment</strong> (operating system, hardware architecture, Node.js version etc).<br>
<em>Why: Ideally the Butler developers want to use as modern versions of Node.js as possible. But if telemetry shows that lots os Butler instances use old Node.js versions or run on some (yet) untested/unverified Linux version - then maybe those older Node.js/Linux versions must be supported for yet some time.</em></li>
</ol>
</div>
<div class="alert alert-warning" role="alert">
<h4 class="alert-heading">What's not shared</h4>
<p>The telemetry data will never include:</p>
<ol>
<li>Data that can identify your Sense environment or the server on which Butler runs. This includes IP/MAC addresses or other network information, server names, Docker container metadata or similar.</li>
<li>Any actual data sent via Butler APIs.</li>
<li>Qlik Sense or other certificates or credentials in any shape or form.</li>
</ol>
</div>
<h3 id="where-is-telemetry-data-sent">Where is telemetry data sent</h3>
<p>The telemetry data is sent to the <a href="https://posthog.com">PostHog</a> service, using their database in the European Union.</p>
<h3 id="deleting-telemetry-data">Deleting telemetry data</h3>
<p>Even though no-one (not even the Butler developers or Ptarmigan Labs who manage the telemetry database!) has any way of ever connecting the data sent by <em>your</em> Butler instance to <em>you</em> (it&rsquo;s all anonymized, remember?), there can be cases where telemetry data must be deleted.</p>
<p>The <a href="https://butler.ptarmiganlabs.com/docs/legal-stuff/#telemetry-data">legal page</a> has more information about this.</p>
<h3 id="field-level-description-of-telemetry-data">Field level description of telemetry data</h3>
<p>A telemetry message from Butler contains the information below.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">&#34;ts&#34;</span><span style="color:#000;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;2021-04-23T23:11:51.431Z&#34;</span><span style="color:#000;font-weight:bold">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">&#34;data&#34;</span><span style="color:#000;font-weight:bold">:</span> <span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">service:</span> <span style="color:#204a87;font-weight:bold">&#34;butler&#34;</span><span style="color:#000;font-weight:bold">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">serviceVersion:</span> <span style="color:#204a87;font-weight:bold">&#34;7.2.1&#34;</span><span style="color:#000;font-weight:bold">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">system:</span> <span style="color:#a40000">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">id:</span> <span style="color:#204a87;font-weight:bold">&#34;3de76798c85894844ac20100cf2142c9a58cc90d7e9dd31a22c94b68048c3ee5&#34;</span><span style="color:#000;font-weight:bold">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">arch:</span> <span style="color:#204a87;font-weight:bold">&#34;x64&#34;</span><span style="color:#000;font-weight:bold">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">platform:</span> <span style="color:#204a87;font-weight:bold">&#34;darwin&#34;</span><span style="color:#000;font-weight:bold">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">release:</span> <span style="color:#204a87;font-weight:bold">&#34;12.3.1&#34;</span><span style="color:#000;font-weight:bold">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">distro:</span> <span style="color:#204a87;font-weight:bold">&#34;macOS&#34;</span><span style="color:#000;font-weight:bold">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">codename:</span> <span style="color:#204a87;font-weight:bold">&#34;macOS Monterey&#34;</span><span style="color:#000;font-weight:bold">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">virtual:</span> <span style="color:#a40000">false,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">hypervisor:</span> <span style="color:#a40000">undefined,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">nodeVersion:</span> <span style="color:#204a87;font-weight:bold">&#34;v16.4.0&#34;</span><span style="color:#000;font-weight:bold">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">},</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">enabledFeatures:</span> <span style="color:#a40000">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">api:</span> <span style="color:#a40000">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">apiListEnbledEndpoints:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">base62ToBase16:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">base16ToBase62:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">butlerping:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">createDir:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">createDirQVD:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">fileDelete:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">fileMove:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">fileCopy:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">keyValueStore:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">mqttPublishMessage:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">scheduler:</span> <span style="color:#a40000">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">createNewSchedule:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">getSchedule:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">getScheduleStatusAll:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">updateSchedule:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">deleteSchedule:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">startSchedule:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">stopSchedule:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span><span style="color:#a40000">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">senseAppReload:</span> <span style="color:#204a87;font-weight:bold">true</span><span style="color:#a40000">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">senseAppDump:</span> <span style="color:#204a87;font-weight:bold">true</span><span style="color:#a40000">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">senseListApps:</span> <span style="color:#204a87;font-weight:bold">true</span><span style="color:#a40000">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">senseStartTask:</span> <span style="color:#204a87;font-weight:bold">true</span><span style="color:#a40000">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">slackPostMessage:</span> <span style="color:#204a87;font-weight:bold">true</span><span style="color:#a40000">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">},</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">feature:</span> <span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">heartbeat:</span> <span style="color:#a40000">false,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">dockerHealthCheck:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">uptimeMonitor:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">uptimeMonitor_storeInInfluxdb:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">uptimeMonitor_storeInNewRelic:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">teamsNotification:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">teamsNotification_reloadTaskFailure:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">teamsNotification_reloadTaskAborted:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">slackNotification:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">slackNotification_reloadTaskFailure:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">slackNotification_reloadTaskAborted:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">emailNotification:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">emailNotification_reloadTaskFailure:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">emailNotification_reloadTaskAborted:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">webhookNotification:</span> <span style="color:#a40000">false,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">webhookNotification_reloadTaskFailure:</span> <span style="color:#a40000">false,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">webhookNotification_reloadTaskAborted:</span> <span style="color:#a40000">false,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">signl4Notification_reloadTaskFailure:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">signl4Notification_reloadTaskAborted:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">newRelicNotification_reloadTaskFailure:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">newRelicNotification_reloadTaskAborted:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">scheduler:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">mqtt:</span> <span style="color:#a40000">true,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">userActivityLogging:</span> <span style="color:#a40000">false,</span>
</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span><span style="color:#a40000">,</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">},</span>
</span></span><span style="display:flex;"><span> <span style="color:#a40000">}</span>
</span></span><span style="display:flex;"><span><span style="color:#a40000">}</span>
</span></span></code></pre></div><h4 id="creating-an-anonymous-id-field">Creating an anonymous ID field</h4>
<p>The <code>id</code> field deserves a bit more explanation.</p>
<p>It&rsquo;s purpose is to uniquely identify the Butler instance - nothing else.<br>
If Butler is stopped and started agagin the same ID should be generated.</p>
<p>Some sensitive information is used to create the ID, but as the ID is anonymized before sent as part of the telemetry data, <em>no sensitive information leaves your servers</em>.</p>
<p>The ID field is created as follows:</p>
<ol>
<li>
<p>Combine the following information to a single string</p>
<ol>
<li>MAC address of default network interface</li>
<li>IPv4 address of default network interface</li>
<li>IP or FQDN of Sense server where repository service is running</li>
<li>System unique ID as reported by the OS. Not all OSs support this though, which is why field 1-3 above are also needed to get a unique ID.</li>
</ol>
</li>
<li>
<p>Run the created string through a <a href="https://en.wikipedia.org/wiki/Cryptographic_hash_function">one-way hashing/message digest function</a>.
Butler uses Node.js&rsquo; own <a href="https://nodejs.org/docs/latest-v15.x/api/crypto.html">Crypto</a> library to create a <a href="https://en.wikipedia.org/wiki/SHA-2">SHA-256</a> hash, using the default network interface&rsquo;s MAC address as salt.<br>
Security is increased due to the fact that the salt never leaves the server where Butler is running.</p>
<p>The bottom line is that it&rsquo;s impossible to reverse the process and get your the IP, host name etc used in step 1 above.<br>
Then again - this is cryptography and things change.<br>
But if you trust the certificates securing Sense itself, then the ID anonymization used by Butler should be ok too.</p>
</li>
<li>
<p>The result is a string that uniquely identifies the Butler instance at hand, without giving away any sensitive data about the system where Butler is running.</p>
</li>
</ol>
<p>See below for an example of what the <code>id</code> field looks like.<br>
The <code>id</code> field is shown during Butler startup as &ldquo;Instance ID&rdquo;.</p>
<pre tabindex="0"><code>2023-12-08T13:15:21.936Z info: --------------------------------------
2023-12-08T13:15:21.937Z info: Starting Butler
2023-12-08T13:15:21.937Z info: Log level : info
2023-12-08T13:15:21.937Z info: App version : 9.1.1
2023-12-08T13:15:21.937Z info: Instance ID : 3de76798c85894844ac20100cf2142c9a58cc90d7e9dd31a22c94b68048c3ee5
2023-12-08T13:15:21.937Z info:
2023-12-08T13:15:21.937Z info: Node version : v18.5.0
2023-12-08T13:15:21.937Z info: Architecture : x64
2023-12-08T13:15:21.937Z info: Platform : darwin
2023-12-08T13:15:21.937Z info: Release : 14.1
2023-12-08T13:15:21.938Z info: Distro : macOS
2023-12-08T13:15:21.938Z info: Codename : macOS Sonoma
2023-12-08T13:15:21.938Z info: Virtual : false
2023-12-08T13:15:21.938Z info: Processors : 1
2023-12-08T13:15:21.938Z info: Physical cores : 8
2023-12-08T13:15:21.938Z info: Cores : 16
2023-12-08T13:15:21.938Z info: Docker arch. : undefined
2023-12-08T13:15:21.938Z info: Total memory : 68719476736
2023-12-08T13:15:21.938Z info:
2023-12-08T13:15:21.938Z info: Config file : /Users/goran/tools/butler/production.yaml
2023-12-08T13:15:21.938Z info: API rate limit : 100
2023-12-08T13:15:21.938Z info: --------------------------------------
</code></pre><h2 id="telemetry-faq">Telemetry FAQ</h2>
<ol>
<li>
<p><strong><em>What data is included in the telemetry messages?</em></strong><br>
See above for details.<br>
In general the telemetry includes information about which Butler API endpoints and features are enabled vs disabled.<br>
A unique, anonymized ID is included too, it&rsquo;s unique to each Butler instance and is used soley to distinguish between different Butler instances.<br>
Finally some information about Butler&rsquo;s execution environment is included. Things like operating system, Node.js version used etc.</p>
</li>
<li>
<p><strong><em>Can my Sense environment be identified via telemetry data?</em></strong><br>
Short answer: No.<br>
Longer answer: No information about your Sense environment is sent as part of telemetry. No IP addresses or server names, no IDs of Sense apps/tasks/etc, no information about what actual data passed through Butler&rsquo;s APIs, or any other data that can be linked to your Sense environment is included in the telemetry data.</p>
</li>
</ol>
</description>
</item>
</channel>
</rss>