370 lines
17 KiB
Markdown
370 lines
17 KiB
Markdown
---
|
||
title: "Audacity and the telemetry pull request"
|
||
author: ["Amolith"]
|
||
lastmod: 2023-01-27T13:00:37-05:00
|
||
tags: ["Open source culture", "Audio editing", "Music", "Drama"]
|
||
categories: ["Technology"]
|
||
draft: true
|
||
---
|
||
|
||
Five days ago at the time of writing, [Dmitry Vedenko](https://github.com/crsib)
|
||
opened a Pull Request (PR) in [Audacity's GitHub
|
||
repository](https://github.com/audacity/audacity/pull/835) entitled [_Basic
|
||
telemetry for the Audacity_.](https://github.com/audacity/audacity/pull/835)
|
||
About two days later, all hell broke loose. That PR now has over 3.3 thousand
|
||
downvotes and more than one thousand comments from nearly 400 individuals. I
|
||
started reading the posts shortly after they began and kept up with them over
|
||
the following days, reading every single new post. I recognise that few people
|
||
are going to feel like wading through over 1k comments so this is my attempt to
|
||
provide a summary of the PR itself using the community's code reviews along with
|
||
a summary of the various opinions conveyed in the comments.
|
||
|
||
When I reference comments, I'll provide a footnote that includes a link to the
|
||
comment and a link to a screenshot just in case it's removed or edited in the
|
||
future.
|
||
|
||
## Audacity's acquisition
|
||
|
||
I haven't been able to find _much_ information in this area so forgive me if I'm
|
||
scant on details.
|
||
|
||
On 30 April, a company called [Muse Group](https://mu.se/) acquired
|
||
[Audacity.](https://www.audacityteam.org/) According to [their
|
||
website](https://mu.se), Muse is the parent company behind many musical
|
||
applications and tools. It was founded by Eugeny Naidenov just days before it
|
||
acquired Audacity. Before all of this, Eugeny Naidenov founded [Ultimate
|
||
Guitar](https://www.ultimate-guitar.com/) (UG) in 1998. The service grew rather
|
||
quickly and now has over 300 million users. UG acquired [Dean Zelinsky
|
||
Guitars](https://deanzelinsky.com/) in 2012, [Agile
|
||
Partners](http://agilepartners.com/) in 2013,
|
||
[MuseScore](https://musescore.org/) in 2017, and
|
||
[Crescendo](http://trycrescendo.com/) in 2018. Muse Group was established in
|
||
2021 and it seems as if all of the services UG acquired were (or will be)
|
||
transferred to Muse Group, as well as UG itself. Immediately following its
|
||
establishment, Muse not only acquired Audacity but also
|
||
[StaffPad.](https://www.staffpad.net/)
|
||
|
||
I say 30 April because that's when Muse published their [press
|
||
release](https://mu.se/newsroom/tpost/6dhedma301-muse-group-acquires-audacity-expanding-c)
|
||
and when Martin Keary (Tantacrul) published a video entitled [_I’m now in charge
|
||
of Audacity. Seriously._](https://www.youtube.com/watch?v=RMWNvwLiXIQ) According
|
||
to his comment,[^fn:1] Martin will help with proposing Audacity's roadmap and
|
||
many of its future features as well as working with the community. This has been
|
||
his role with MuseScore since he joined that project and he will be continuing
|
||
it here.
|
||
|
||
`-----BEGIN PERSONAL OPINION-----`
|
||
|
||
Looking at [his website,](https://www.martinkeary.com/) I also suspect he will
|
||
play a large role in redesigning Audacity's interface. Considering that he was
|
||
instrumental in designing [the best mobile interface I've ever had the absolute
|
||
pleasure of experiencing,](https://www.martinkeary.com/#/ubuntu-touch-os/) I
|
||
have high hopes that this is the case.
|
||
|
||
`------END PERSONAL OPINION------`
|
||
|
||
## Telemetry implementation
|
||
|
||
### Implementation Basics
|
||
|
||
A few days after the acquisition, a PR was opened that adds _Basic telemetry for
|
||
the Audacity_. This implementation collects "application opened" events and
|
||
sends those to Yandex to estimate the number of Audacity users. It also collects
|
||
session start and end events, errors for debugging, file used for import and
|
||
export, OS and Audacity versions, and the use of effects, generators, and
|
||
analysis tools so they can prioritise future improvements. Sending this data
|
||
would be optional and the user would be presented with a dialogue the first time
|
||
they launch the application after installation or after they update to the
|
||
including release. This description was mostly copied directly from [the PR
|
||
description
|
||
itself.](https://github.com/audacity/audacity/pull/835#issue-629891447)
|
||
|
||
### Frontend Implementation
|
||
|
||
This is fairly straightforward and a pretty standard UI for prompting users to
|
||
consent to analytics and crash logging. This section is included because the
|
||
community has strong opinions regarding the language used and its design, but
|
||
that will be discussed later. The screenshot below is copied directly from the
|
||
PR.
|
||
|
||
{{< figure src="~/repos/sites/secluded/static/assets/pngs/audacity-pr/consentdialogue.png" link="~/repos/sites/secluded/static/assets/pngs/audacity-pr/consentdialogue.png" >}}
|
||
|
||
### Backend Implementation
|
||
|
||
Many of the code reviews include the reviewer's personal opinion so I will
|
||
summarise the comment, provide the code block in question, and link directly to
|
||
the comment in a footnote.[^fn:2]
|
||
|
||
```c
|
||
if (!inputFile.Write (wxString::FromUTF8 (ClientID + "\n")))
|
||
return false;
|
||
```
|
||
|
||
[Lines 199-200 of
|
||
TelemetryManager.cpp](https://github.com/crsib/audacity/blob/c9264d2478fe2af82aeb6e2a0295b00b3a27ce53/libraries/lib-telemetry/TelemetryManager.cpp#L199-L200)
|
||
save the user's unique client ID to a file.[^fn:3] This allows the analytics
|
||
tool (in this case, Google Analytics) to aggregate data produced by a single
|
||
user.
|
||
|
||
```c
|
||
def_vars()
|
||
|
||
set( CURL_DIR "${_INTDIR}/libcurl" )
|
||
set( CURL_TAG "curl-7_76_0")
|
||
```
|
||
|
||
[Lines 3-6 of
|
||
CMakeLists.txt](https://github.com/crsib/audacity/blob/c9264d2478fe2af82aeb6e2a0295b00b3a27ce53/cmake-proxies/libcurl/CMakeLists.txt#L3-L6)
|
||
"vendor in" libcurl.[^fn:4] This is when an application directly includes
|
||
sources for a utility rather than making use utilities provided by the system
|
||
itself.
|
||
|
||
```c
|
||
ExternalProject_Add(curl
|
||
PREFIX "${CURL_DIR}"
|
||
INSTALL_DIR "${CURL_DIR}"
|
||
GIT_REPOSITORY https://github.com/curl/curl
|
||
GIT_TAG ${CURL_TAG}
|
||
GIT_SHALLOW Yes
|
||
CMAKE_CACHE_ARGS ${CURL_CMAKE_ARGS}
|
||
)
|
||
```
|
||
|
||
[Lines 29-36 of
|
||
CMakeLists.txt](https://github.com/crsib/audacity/blob/c9264d2478fe2af82aeb6e2a0295b00b3a27ce53/cmake-proxies/libcurl/CMakeLists.txt#L29-L36)
|
||
add curl as a remote dependency.[^fn:5] This means that the machine building
|
||
Audacity from its source code has to download curl during that build.
|
||
|
||
```c
|
||
S.Id (wxID_NO).AddButton (rejectButtonTitle);
|
||
S.Id (wxID_YES).AddButton (acceptButtonTitle)->SetDefault ();
|
||
```
|
||
|
||
[Lines 93-94 of
|
||
TelemetryDialog.cpp](https://github.com/crsib/audacity/blob/c9264d2478fe2af82aeb6e2a0295b00b3a27ce53/src/telemetry/TelemetryDialog.cpp#L93-L94)
|
||
add buttons to the dialogue asking the user whether they consent to data
|
||
collection.[^fn:6] `SetDefault` focuses the button indicating that the user does
|
||
consent. This means that if the user doesn't really look at the dialogue and
|
||
presses Spacebar or Enter, or if they do so accidentally by simply bumping the
|
||
key, they unintentionally consent to data collection. If the user desires, this
|
||
can later be changed in the settings menu. However, if they weren't aware what
|
||
they were consenting to _or that they did consent_, they won't know to go back
|
||
and opt out.
|
||
|
||
There are other problems with the code that include [simple
|
||
mistakes,](https://github.com/audacity/audacity/pull/835#discussion_r628816050)
|
||
[styling that's inconsistent with the rest of the
|
||
project,](https://github.https//github.com/audacity/audacity/pull/835#discussion_r628774985)
|
||
[unhandled return values resulting in skewed
|
||
data,](https://github.com/audacity/audacity/pull/835#discussion_r628500849) [use
|
||
of inappropriate
|
||
functions,](https://github.com/audacity/audacity/pull/835#discussion_r628792423)
|
||
and [spelling errors in the
|
||
comments.](https://github.com/audacity/audacity/pull/835#discussion_r628818054)
|
||
I believe these are less important than those above so they won't be discussed.
|
||
|
||
## Community opinions
|
||
|
||
There were many strong opinions regarding both the frontend and backend
|
||
implementations of this PR, from the wording of the dialogue and highlighting
|
||
the consent button to devices running something other than Windows and macOS not
|
||
being able to send telemetry and thus skewing the data that _was_ collected.
|
||
|
||
### Opinions on the frontend
|
||
|
||
Really, the only frontend here is the consent dialogue. However, there are
|
||
_many_ comments about it, the most common of which is probably that the wording
|
||
is not only too vague[^fn:7] but also inaccurate.[^fn:8] The assertion that
|
||
Google Analytics are not anonymous and any data sent can be trivially
|
||
de-anonymised (or de-pseudonymised) is repeated many times over. Below are a few
|
||
links to comments stating such. I searched for the term _"anonymous"_, copied
|
||
relevant links, and stopped when my scrollbar reached halfway down the page.
|
||
|
||
- [r628156527](https://github.com/audacity/audacity/pull/835#discussion_r628156527)
|
||
- [833969780](https://github.com/audacity/audacity/pull/835#issuecomment-833969780)
|
||
- [833969933](https://github.com/audacity/audacity/pull/835#issuecomment-833969933)
|
||
- [r627995927](https://github.com/audacity/audacity/pull/835#discussion_r627995927)
|
||
- [834358022](https://github.com/audacity/audacity/pull/835#issuecomment-834358022)
|
||
- [834377549](https://github.com/audacity/audacity/pull/835#issuecomment-834377549)
|
||
- [834382007](https://github.com/audacity/audacity/pull/835#issuecomment-834382007)
|
||
- [834385463](https://github.com/audacity/audacity/pull/835#issuecomment-834385463)
|
||
- [834405825](https://github.com/audacity/audacity/pull/835#issuecomment-834405825)
|
||
- [834531779](https://github.com/audacity/audacity/pull/835#issuecomment-834531779)
|
||
- [834546874](https://github.com/audacity/audacity/pull/835#issuecomment-834546874)
|
||
- [834638000](https://github.com/audacity/audacity/pull/835#issuecomment-834638000)
|
||
|
||
The next most pervasive comment is regarding the consent buttons at the bottom
|
||
of the dialogue where users opt in or out.[^fn:9] Many individuals call this
|
||
design a _dark pattern_. Harry Brignull, a UX specialist focusing on deceptive
|
||
interface practises, describes dark patterns as [_tricks used in websites and
|
||
apps that make you do things that you didn't mean
|
||
to_.](https://www.darkpatterns.org/) The dark pattern in this situation is the
|
||
opt-in button being highlighted. Many community members assert that users will
|
||
see the big blue button and click it without actually reading the dialogue's
|
||
contents. They just want to record their audio and this window is a distraction
|
||
that prevents them from doing so; it needs to get out of the way and the
|
||
quickest way to dismiss it is clicking that blue button. Below is a list of some
|
||
comments criticising this design.
|
||
|
||
- [834286641](https://github.com/audacity/audacity/pull/835#issuecomment-834286641)
|
||
- [834358022](https://github.com/audacity/audacity/pull/835#issuecomment-834358022)
|
||
- [834399813](https://github.com/audacity/audacity/pull/835#issuecomment-834399813)
|
||
- [834479968](https://github.com/audacity/audacity/pull/835#issuecomment-834479968)
|
||
- [835250737](https://github.com/audacity/audacity/pull/835#issuecomment-835250737)
|
||
- [835253882](https://github.com/audacity/audacity/pull/835#issuecomment-835253882)
|
||
- [835291066](https://github.com/audacity/audacity/pull/835#issuecomment-835291066)
|
||
- [835445481](https://github.com/audacity/audacity/pull/835#issuecomment-835445481)
|
||
|
||
Another issue that was brought up by a couple of individuals was the lack of a
|
||
privacy policy.[^fn:10] The consent dialogue links to one, but, at the time of
|
||
writing, one does not exist at [the provided
|
||
URL.](https://www.audacityteam.org/contact/privacy-policy/) I have [archived the
|
||
state of the
|
||
page](https://web.archive.org/web/20210510012924/https://www.audacityteam.org/contact/privacy-policy/)
|
||
in case that changes in the future.
|
||
|
||
### Opinions on the backend
|
||
|
||
```c
|
||
if (!inputFile.Write (wxString::FromUTF8 (ClientID + "\n")))
|
||
return false;
|
||
```
|
||
|
||
The issue many individuals take with this snippet is saving the `ClientID`. Say
|
||
an individual has an odd file that causes Audacity to crash any time they try to
|
||
open it. Say they attempt to open it a hundred times. Without giving the client
|
||
a unique ID, it could look like there are 100 people having an issue opening a
|
||
file instead of just the one. However, by virtue of each installation having an
|
||
entirely unique ID, this telemetry _is not anonymous_. Anonymity would be
|
||
sending statistics in such a way that connecting those failed attempts to a
|
||
single user would be impossible. At best, this implementation is _pseudonymous_
|
||
because the client is given a random ID, you don't have to sign in with an
|
||
account or something.
|
||
|
||
```c
|
||
def_vars()
|
||
|
||
set( CURL_DIR "${_INTDIR}/libcurl" )
|
||
set( CURL_TAG "curl-7_76_0")
|
||
```
|
||
|
||
Timothe Litt's comment gives a good description of why "vendoring in" libcurl is
|
||
a bad idea[^fn:11] and Tyler True's comment gives a good overview of the pros
|
||
and cons of doing so.[^fn:12] Many people take issue with this _specifically_
|
||
because it's libcurl. Security flaws in it are _very_ common and Audacity's copy
|
||
would need to be _manually_ kept up to date with every upstream release to
|
||
ensure none of its vulnerabilities can be leveraged to compromise users. If the
|
||
Audacity team was going to stay on top of all of the security fixes, they would
|
||
need to release a new version every week or so.
|
||
|
||
```c
|
||
ExternalProject_Add(curl
|
||
PREFIX "${CURL_DIR}"
|
||
INSTALL_DIR "${CURL_DIR}"
|
||
GIT_REPOSITORY https://github.com/curl/curl
|
||
GIT_TAG ${CURL_TAG}
|
||
GIT_SHALLOW Yes
|
||
CMAKE_CACHE_ARGS ${CURL_CMAKE_ARGS}
|
||
)
|
||
```
|
||
|
||
The problem with downloading curl at build-time is that it's simply disallowed
|
||
for many Linux- and BSD-based operation systems. When a distribution builds an
|
||
application from source, its build dependencies are often downloaded ahead of
|
||
time and, as a security measure, the build machine is cut off from the internet
|
||
to prevent any interference. Because this is disallowed, the build will fail and
|
||
the application won't be available on those operation systems.
|
||
|
||
Note, however, that these build machines would have the option to disable
|
||
telemetry at build-time. This means the machine wouldn't attempt to download
|
||
curl from GitHub and the build would succeed but, again, telemetry would be
|
||
disabled for anyone not on Windows or macOS. This defeats the whole purpose of
|
||
adding telemetry in the first place.
|
||
|
||
```c
|
||
S.Id (wxID_NO).AddButton (rejectButtonTitle);
|
||
S.Id (wxID_YES).AddButton (acceptButtonTitle)->SetDefault ();
|
||
```
|
||
|
||
There was a lot of feedback about the decision to highlight the consent button
|
||
but that was mentioned up in the frontend section; I won't rehash it here.
|
||
|
||
### Broader and particularly well-structured comments
|
||
|
||
These are simply some comments I feel deserve particular attention.
|
||
|
||
From SndChaser...
|
||
|
||
- [834037351](https://github.com/audacity/audacity/pull/835#issuecomment-834037351)
|
||
-
|
||
|
||
## The Audacity team's response
|
||
|
||
---
|
||
|
||
## The privacy policy modification
|
||
|
||
<https://github.com/audacity/audacity/issues/1213#issuecomment-875274890>
|
||
|
||
[^fn:1]:
|
||
[Link to the
|
||
comment](https://github.com/audacity/audacity/pull/835#issuecomment-836069326)
|
||
and [link to the screenshot](/assets/pngs/audacity-pr/tantacrulrole.png)
|
||
|
||
[^fn:2]:
|
||
Note that because I am not a C programmer, these reviews might not be
|
||
entirely accurate and I wouldn't be able to catch the reviewer's error. I am
|
||
relying on other community members to catch issues and comment on them; none
|
||
of the reviews I link to have such comments so I'm assuming they are
|
||
correct.
|
||
|
||
[^fn:3]:
|
||
[Link to the
|
||
review](https://github.com/audacity/audacity/pull/835#discussion_r627993755) and
|
||
[link to the screenshot](/assets/pngs/audacity-pr/writeanalyticsid.png)
|
||
|
||
[^fn:4]:
|
||
[Link to the
|
||
review](https://github.com/audacity/audacity/pull/835#discussion_r628005925) and
|
||
[link to the screenshot](/assets/pngs/audacity-pr/vendorcurl.png)
|
||
|
||
[^fn:5]:
|
||
[Link to the
|
||
review](https://github.com/audacity/audacity/pull/835#discussion_r628008821) and
|
||
[link to the screenshot](/assets/pngs/audacity-pr/externaldependency.png)
|
||
|
||
[^fn:6]:
|
||
[Link to the
|
||
review](https://github.com/audacity/audacity/pull/835#discussion_r628124998) and
|
||
[link to the screenshot](/assets/pngs/audacity-pr/defaultconsentbutton.png)
|
||
|
||
[^fn:7]:
|
||
[Link to the
|
||
comment](https://github.com/audacity/audacity/pull/835#discussion_r627756976)
|
||
and [link to the screenshot](/assets/pngs/audacity-pr/vaguedialogue.png)
|
||
|
||
[^fn:8]:
|
||
[Link to the
|
||
comment](https://github.com/audacity/audacity/pull/835#discussion_r627764300)
|
||
and the screenshot is the same as previous
|
||
|
||
[^fn:9]:
|
||
[Link to the
|
||
comment](https://github.com/audacity/audacity/pull/835#issuecomment-834286641)
|
||
and [link to the screenshot](/assets/pngs/audacity-pr/darkpattern.png)
|
||
|
||
[^fn:10]:
|
||
[Link to the
|
||
comment](https://github.com/audacity/audacity/pull/835#discussion_r627762185)
|
||
and [link to the screenshot](/assets/pngs/audacity-pr/missingprivacypolicy.png)
|
||
|
||
[^fn:11]:
|
||
[Link to the
|
||
comment](https://github.com/audacity/audacity/pull/835#issuecomment-834451187)
|
||
and [link to the screenshot](/assets/pngs/audacity-pr/privatelibcurl.png)
|
||
|
||
[^fn:12]:
|
||
[Link to the
|
||
comment](https://github.com/audacity/audacity/pull/835#issuecomment-834010117)
|
||
and [link to the screenshot](/assets/pngs/audacity-pr/vendorproscons.png)
|