<rss version="2.0">
  <channel>
    <title>fnordig - posts tagged with 'mozilla'</title>
    <link>https://fnordig.de</link>
    <description>fnordig - posts tagged with 'mozilla'</description>
    <item>
      <title>Eight-year Moziversary</title>
      <link>https://fnordig.de/2026/03/02/eight-year-moziversary</link>
      <description>&lt;p&gt;In March 2018 I started &lt;a href=&quot;/2018/02/18/a-new-job/&quot;&gt;a job as a Telemetry engineer at Mozilla&lt;/a&gt;.
Eight years later I&#39;m still here on my Moziversary, as I was in &lt;a href=&quot;/2019/03/01/one-year-moziversary/&quot;&gt;2019&lt;/a&gt;, &lt;a href=&quot;/2020/03/02/two-year-moziversary/&quot;&gt;2020&lt;/a&gt;, &lt;a href=&quot;/2021/03/01/three-year-moziversary/&quot;&gt;2021&lt;/a&gt;, &lt;a href=&quot;/2022/03/04/four-year-moziversary/&quot;&gt;2022&lt;/a&gt;, &lt;a href=&quot;/2023/03/01/five-year-moziversary/&quot;&gt;2023&lt;/a&gt;, &lt;a href=&quot;/2024/03/12/six-year-moziversary/&quot;&gt;2024&lt;/a&gt; and &lt;a href=&quot;/2025/03/03/seven-year-moziversary/&quot;&gt;2025&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the past year we had
&lt;a href=&quot;https://blog.mozilla.org/en/mozilla/leadership/mozillas-next-chapter-anthony-enzor-demeo-new-ceo/&quot;&gt;1 CEO change&lt;/a&gt;,
&lt;a href=&quot;https://arewereorganizedyet.com/&quot;&gt;14 reorgs&lt;/a&gt;,
&lt;a href=&quot;https://whattrainisitnow.com/&quot;&gt;12 Firefox releases&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
and &lt;a href=&quot;https://github.com/mozilla/glean/releases&quot;&gt;31 Glean releases&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;My team is still part of the Infrastructure Org, now under a bigger organization called Core Services.
Other Data Engineers however have been moved over to the neighboring Data org.
I was told nothing else changes and priorities stay the same.
My &lt;del&gt;goals&lt;/del&gt; individual expectations will be adjusted accordingly.
I haven&#39;t seen my team in person since Dublin, due to policy changes around work travel in and out of the US.&lt;/p&gt;
&lt;p&gt;Despite all the company changes, the work I&#39;m directly involved in did remain largely the same.
I&#39;m still focused on &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;Glean&lt;/a&gt;, as expected.
We (and by that I mean mostly chutten) moved legacy telemetry to Glean fully (&lt;a href=&quot;https://arewegleanyet.com/&quot;&gt;we are Glean now&lt;/a&gt;).
In the last half of 2025 I finally found dedicated time for performance work.
We now have the first benchmarks on Glean and I was able to close out some performance gaps previously identified.
More work remains.
Early this year then I was able to revive my prototype for moving Glean to a new storage backend based on SQLite and early benchmarks are very promising.
This year I will focus on finalizing that work, deploying a new Glean version with a more reliable (and faster!) client-side storage,
accompanied by benchmarks we can run and rely on.
Along with that I can do some refactoring and cleanups that will make our codebase easier to work with.
Other work includes a better integration with other Rust components that want to use Glean directly.&lt;/p&gt;
&lt;p&gt;The rest of Mozilla is still working on many big and small things.
Leadership is still chasing the AI hype, with questionable outcomes&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.
I don&#39;t know where that will take the company and I disagree with some of the approaches.
So far I&#39;ve been spared from the worst and no one is forcing AI tools on me just yet.&lt;/p&gt;
&lt;h2&gt;Thank you&lt;/h2&gt;
&lt;p&gt;Eight years in the same job is a long time.
I get to make decisions. I have to live with them.
I have to live with decisions of others and maintain them.
None of that however would be possible without a team, which makes it a joy to work alongside.
So a big thank you to my team members &lt;a href=&quot;https://chuttenblog.wordpress.com/&quot;&gt;Chris&lt;/a&gt;, &lt;a href=&quot;https://blogoftravis.wordpress.com/&quot;&gt;Travis&lt;/a&gt;, &lt;a href=&quot;https://github.com/jeddai&quot;&gt;Charlie&lt;/a&gt; and &lt;a href=&quot;https://github.com/abhi-agg&quot;&gt;Abhishek&lt;/a&gt; for being the Data Collection Tools team.
And also a thank you to &lt;a href=&quot;https://www.a2p.it/&quot;&gt;Alessio&lt;/a&gt;, our team manager.
There&#39;s many others across Mozilla I get to work with and chat with.
Thank you!&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Contrary to popular belief there is &lt;em&gt;not&lt;/em&gt; a fixed reorg schedule (that I know of), there is a Firefox release schedule though. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Now with a &lt;a href=&quot;https://www.youtube.com/playlist?list=PLuz3AGohFmM-mQTVhfUxSByKT99a05dzr&quot;&gt;release song playlist&lt;/a&gt; &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;You can &lt;a href=&quot;https://blog.mozilla.org/en/firefox/ai-controls/&quot;&gt;disable the things you don&#39;t want in Firefox&lt;/a&gt;. &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2026/03/02/eight-year-moziversary</guid>
      <pubDate>Mon, 02 Mar 2026 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>Incident Report: A compiler bug and JSON</title>
      <link>https://fnordig.de/2025/12/09/incident-report-a-compiler-bug-and-json</link>
      <description>&lt;hr /&gt;
&lt;p&gt;This article is &lt;a href=&quot;https://blog.mozilla.org/data/2025/12/09/incident-report-a-compiler-bug-and-json/&quot;&gt;cross-posted to the Data@Mozilla blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;It all started rather inconspicuous:
The Data Engineering team filed &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1999791&quot;&gt;a bug report&lt;/a&gt; about a sudden increase in schema errors at ingestion of telemetry data from Firefox for Android.
At that point in time about 0.9% of all incoming pings were not passing our schema validation checks.&lt;/p&gt;
&lt;p&gt;The data we were seeing was surprising.
Our ingestion endpoint received valid JSON that contained snippets like this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#183691;&quot;&gt;&amp;quot;metrics&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#183691;&quot;&gt;&amp;quot;schema: counter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#183691;&quot;&gt;&amp;quot;glean.validation.pings_submitted&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#183691;&quot;&gt;&amp;quot;events&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;background-color:#f5f5f5;font-weight:bold;color:#b52a1d;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;background-color:#f5f5f5;font-weight:bold;color:#b52a1d;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What we would expect and would pass our schema validation is this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#183691;&quot;&gt;&amp;quot;metrics&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#183691;&quot;&gt;&amp;quot;labeled_counter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#183691;&quot;&gt;&amp;quot;glean.validation.pings_submitted&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#183691;&quot;&gt;&amp;quot;events&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;background-color:#f5f5f5;font-weight:bold;color:#b52a1d;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;background-color:#f5f5f5;font-weight:bold;color:#b52a1d;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The difference? 8 characters:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#ffecec;color:#323232;&quot;&gt;-        &amp;quot;schema: counter&amp;quot;: {
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;        &amp;quot;labeled_counter&amp;quot;: {
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;8 different characters that still make up valid JSON, but break validation.&lt;/p&gt;
&lt;p&gt;A week later the number of errors kept increasing, affecting up to 2% of all ingested pings from Firefox for Android Beta.
That&#39;s worryingly high.
That&#39;s enough to drop other work and call an incident.&lt;/p&gt;
&lt;h2&gt;Aside: Telemetry ingestion&lt;/h2&gt;
&lt;p&gt;In Firefox the data is collected using the &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;Glean SDK&lt;/a&gt;.
Data is stored in a local database and eventually assembled into what we call a &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/glossary.html#ping&quot;&gt;ping&lt;/a&gt;:
A bundle of related metrics, gathered in a JSON payload to be transmitted.
This JSON document is then &lt;code&gt;POST&lt;/code&gt;ed to the &lt;a href=&quot;https://docs.telemetry.mozilla.org/concepts/pipeline/http_edge_spec&quot;&gt;Telemetry edge server&lt;/a&gt;.
From there the decoder eventually picks it up and processes it further.
One of the early things it does is verify the received data against one of the &lt;a href=&quot;https://github.com/mozilla-services/mozilla-pipeline-schemas&quot;&gt;pre-defined schemas&lt;/a&gt;.
When data is coming from the Glean SDK it must pass &lt;a href=&quot;https://github.com/mozilla-services/mozilla-pipeline-schemas/blob/main/schemas/glean/glean/glean.1.schema.json&quot;&gt;the pre-defined &lt;code&gt;glean.1.schema.json&lt;/code&gt;&lt;/a&gt;.
This essentially describes which fields to expect in the nested JSON object.
One thing it is expecting is &lt;a href=&quot;https://github.com/mozilla-services/mozilla-pipeline-schemas/blob/1f4e1dada6a32f7ff1718034c74427b1a351a1df/schemas/glean/glean/glean.1.schema.json#L299-L310&quot;&gt;a &lt;code&gt;labeled_counter&lt;/code&gt;&lt;/a&gt;
A thing it is NOT expecting is &lt;code&gt;schema: counter&lt;/code&gt;. In fact keys other than the listed ones &lt;a href=&quot;https://github.com/mozilla-services/mozilla-pipeline-schemas/blob/1f4e1dada6a32f7ff1718034c74427b1a351a1df/schemas/glean/glean/glean.1.schema.json#L173&quot;&gt;are forbidden&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The missing schema:_&lt;/h2&gt;
&lt;p&gt;The data we were receiving from a growing number of clients contained 8 bytes that we didn&#39;t expect in that place: &lt;code&gt;schema: &lt;/code&gt;.
That 8-character string didn&#39;t even show up in the &lt;a href=&quot;https://searchfox.org/glean/search?q=schema%3A+&amp;amp;path=*.rs&amp;amp;case=true&amp;amp;regexp=false&quot;&gt;Glean SDK source code&lt;/a&gt;.
Where does it come from? Why was it showing up now?&lt;/p&gt;
&lt;p&gt;We did receive entirely valid JSON, so it&#39;s unlikely to be simple memory corruption&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
More like memory confusion, if that&#39;s a thing.&lt;/p&gt;
&lt;p&gt;We know where the payload is constructed.
The nested object for labeled metrics is constructed &lt;a href=&quot;https://github.com/mozilla/glean/blob/88e30a21f6bf621757c4139c271afda8c8a6123e/glean-core/src/storage/mod.rs#L35&quot;&gt;in its own function&lt;/a&gt;.
It starts with string formatting:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; ping_section &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;format!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;labeled_&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, metric.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;ping_section&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;());
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There&#39;s our 8-character string &lt;code&gt;labeled_&lt;/code&gt; that gets swapped.
The Glean SDK is embedded into Firefox inside mozilla-central and compiled with all the other code together.
A single candidate for the &lt;code&gt;schema: &lt;/code&gt; string &lt;a href=&quot;https://searchfox.org/firefox-main/search?q=%22schema%3A&amp;amp;path=&amp;amp;case=false&amp;amp;regexp=false&quot;&gt;exists in that codebase&lt;/a&gt;.
That&#39;s another clue it could be memory confusion.&lt;/p&gt;
&lt;h2&gt;My schema? Confused.&lt;/h2&gt;
&lt;p&gt;I don&#39;t know much about how string formatting in Rust works under the hood,
but luckily &lt;a href=&quot;https://marabos.nl/&quot;&gt;Mara&lt;/a&gt; blogged about it 2 years ago: &lt;a href=&quot;https://blog.m-ou.se/format-args/&quot;&gt;Behind the Scenes of Rust String Formatting: format_args!()&lt;/a&gt;
(and then &lt;a href=&quot;https://hachyderm.io/@Mara/115542621720999480&quot;&gt;recently improved the implementation&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;).&lt;/p&gt;
&lt;p&gt;So the &lt;code&gt;format!&lt;/code&gt; from above expands into something like this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::io::_format(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;// Simplified expansion of format_args!():
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    std::fmt::Arguments {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        template: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[Str(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;labeled_ &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;), Arg(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)],
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        arguments: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;metric.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;ping_section&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;as &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;dyn Display],
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another clue that the &lt;code&gt;labeled_&lt;/code&gt; string is referenced all by itself and swapping out the pointer to it would be enough to lead to the corrupted data we were seeing.&lt;/p&gt;
&lt;h2&gt;Architecturing more clues&lt;/h2&gt;
&lt;p&gt;Whenever we&#39;re faced with data anomalies we &lt;a href=&quot;https://mozilla.github.io/glean/book/user/howto/investigating-data-issues/investigating-data-issues.html&quot;&gt;start by dissecting the data&lt;/a&gt; to figure out if the anomalies are from a particular subset of clients.
The hope is that identifying the subset of clients where it happens gives us more clues about the bug itself.&lt;/p&gt;
&lt;p&gt;After initially focusing too much on actual &lt;em&gt;devices&lt;/em&gt; colleagues helpfully pointed out that the actual split was the device&#39;s architecture&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2025/2025-12-01-schema-counter-error-architecture.png&quot; alt=&quot;Data since 2025-11-11 showing a sharp increase in errors for armeabi-v7a clients&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ARMv8, the 64-bit architecture, did not run into this issue&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.
ARMv7, purely 32-bit, was the sole driver of this data anomaly.
Another clue that something in the code specifically for this architecture was causing this.&lt;/p&gt;
&lt;h2&gt;Logically unchanged&lt;/h2&gt;
&lt;p&gt;With a hypothesis what was happening, but no definite answer why, we went to speculative engineering:
Let&#39;s avoid the code path that we think is problematic.&lt;/p&gt;
&lt;p&gt;By explicitly listing out the different strings we want to have in the JSON payload we avoid the formatting
and thus hopefully any memory confusion.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; ping_section &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= match&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; metric.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;ping_section&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;boolean&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;labeled_boolean&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;to_string&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;counter&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;labeled_counter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;to_string&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;// &amp;lt;snip&amp;gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;_ =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;format!(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;labeled_&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, metric.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;ping_section&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;};
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This was implemented in &lt;a href=&quot;https://github.com/mozilla/glean/commit/912fc8063575df48c5b3d838944036a1a37d6fc3&quot;&gt;912fc80&lt;/a&gt; and shipped in &lt;a href=&quot;https://github.com/mozilla/glean/releases/tag/v66.1.2&quot;&gt;Glean v66.1.2&lt;/a&gt;.
It landed in Firefox the same day of the SDK release and made it to Firefox for Android Beta the Friday after.
The data shows: It&#39;s working, no more memory confusion!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2025/2025-12-01-schema-counter-error-downwards.png&quot; alt=&quot;The number of errors have been on a downturn ever since the fix landed on 2025-11-26&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;A bug gone but still there&lt;/h2&gt;
&lt;p&gt;The immediate incident-causing data anomaly was mitigated, the bug is not making it to the &lt;a href=&quot;https://whattrainisitnow.com/release/?version=146&quot;&gt;Firefox 146 release&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But we still didn&#39;t know why this was happening in the first place.
My colleagues Yannis and Serge kept working and searching and were finally able to track down what exactly is happening in the code.
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=2003320&quot;&gt;The bug&lt;/a&gt; contains more information on the investigation.&lt;/p&gt;
&lt;p&gt;While I was trying to read and understand the disassembly of the broken builds,
they went ahead and wrote a tiny emulator (based on the &lt;a href=&quot;https://www.unicorn-engine.org/&quot;&gt;Unicorn engine&lt;/a&gt;)
that runs just enough of the code to find the offending code path&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;gt; python ./emulator.py libxul.so
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Path: libxul.so
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;GNU build id: 1b9e9c8f439b649244c7b3acf649d1f33200f441
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Symbol server ID: 8F9C9E1B9B43926444C7B3ACF649D1F30
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Please wait, downloading symbols from: https://symbols.mozilla.org/try/libxul.so/8F9C9E1B9B43926444C7B3ACF649D1F30/libxul.so.sym
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Please wait, uncompressing symbols...
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Please wait, processing symbols...
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Proceeding to emulation.
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Result of emulation: bytearray(b&amp;#39;schema: &amp;#39;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;This is a BAD build.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The relevant section of the code boils down to this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;ldr   r3, [pc, #0x20c]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;add   r3, pc
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;strd  r3, r0, [sp, #0xd0]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;add   r1, sp, #0xd0
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;bl    alloc::fmt::format_inner
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;The first two instructions build the pointer to the slice in r3, by using a pc-relative offset found in a nearby constant.
Then we store that pointer at &lt;code&gt;sp+0xd0&lt;/code&gt;, and we put the address &lt;code&gt;sp+0xd0&lt;/code&gt; into &lt;code&gt;r1&lt;/code&gt;.
So before we reach &lt;code&gt;alloc::fmt::format_inner&lt;/code&gt;, &lt;code&gt;r1&lt;/code&gt; points to a stack location that contains a pointer to the slice of interest.
The slice lives in &lt;code&gt;.data.rel.ro&lt;/code&gt; and contains a pointer to the string, and the length of the string (8).
The string itself lives in &lt;code&gt;.rodata&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In good builds the &lt;code&gt;.rodata&lt;/code&gt; &lt;code&gt;r3&lt;/code&gt; points to looks like this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06f0c3d4: 0x005dac18  --&amp;gt;  &amp;quot;labeled_&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06f0c3d8:        0x8
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06f0c3dc: 0x0185d707  --&amp;gt;  &amp;quot;/builds/&amp;lt;snip&amp;gt;/rust/glean-core/src/storage/mod.rs&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06f0c3e0:       0x4d
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In bad builds however it points to something that has our dreaded &lt;code&gt;schema: &lt;/code&gt; string:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06d651c8: 0x010aa2e8  --&amp;gt;  &amp;quot;schema: &amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06d651cc:        0x8
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06d651d0: 0x01a869a7  --&amp;gt;  &amp;quot;maintenance: &amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06d651d4:        0xd
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06d651d8: 0x01a869b4  --&amp;gt;  &amp;quot;storage dir: &amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06d651dc:        0xd
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06d651e0: 0x01a869c8  --&amp;gt;  &amp;quot;from variant of type &amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06d651e4:       0x15
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06d651e8: 0x017f793c  --&amp;gt;  &amp;quot;: &amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;0x06d651ec:        0x2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This confirms the suspicion that it&#39;s a compiler/linker bug.
Now the question was how to fix that.&lt;/p&gt;
&lt;p&gt;Firefox builds with a variety of Clang/LLVM versions.
Mozilla uses its own build of LLVM and Clang to build the final applications,
the exact version used is &lt;a href=&quot;https://firefox-source-docs.mozilla.org/build/buildsystem/toolchains-update-policy.html#clang&quot;&gt;updated as soon as possible, but never on release&lt;/a&gt;.
Sometimes additional patches are applied on top of the Clang release, like some backports fixing other compiler bugs.&lt;/p&gt;
&lt;p&gt;After identifying that this is indeed a bug in the linker and that it has already been patched in later LLVM versions,
Serge did all the work to bisect the LLVM release to find which patches to apply to Mozilla&#39;s own Clang build.
Ultimately he tracked it down to these two patches for LLVM:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/llvm/llvm-project/pull/151346&quot;&gt;[InstCombine] Don&#39;t handle non-canonical index type in icmp of load fold&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/llvm/llvm-project/pull/150639&quot;&gt;[InstCombine] Make foldCmpLoadFromIndexedGlobal more resiliant to non-array geps.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With those patches applied, the old code, without our small code rearrangement, does not lead to broken builds anymore.&lt;/p&gt;
&lt;p&gt;With the Glean code patched, the ingestion errors dropping and the certainty that we have identified and patched the compiler bug, we can safely ship the next release of Firefox (for Android).&lt;/p&gt;
&lt;h2&gt;Collaboration&lt;/h2&gt;
&lt;p&gt;Incidents are stressful situations, but a great place for collaboration across the whole company.
The number of people involved in resolving this is long.&lt;/p&gt;
&lt;p&gt;Thanks to Eduardo &amp;amp; Ben from Data Engineering for raising the issue.&lt;br /&gt;
Thanks to Alessio (my manager) for managing the incident.&lt;br /&gt;
Thanks to chutten and Travis (from my team) for brainstorming what caused this and suggesting solutions/workarounds.&lt;br /&gt;
Thanks to Donal (Release Management) for fast-tracking the mitigation into a Beta release.&lt;br /&gt;
Thanks to Alex (Release Engineering) for some initial investigation into the linker bug.&lt;br /&gt;
Thanks to Brad (Data Science) for handling the data analysis side.&lt;br /&gt;
Thanks to Yannis and Serge (OS integration) for identifying, finding and patching the linker bug.&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Memory corruption is never &quot;simple&quot;. But if it were memory corruption I would expect data to be broken worse or in other places too. Not just a string swap in a single place. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;That improvement is not yet available to us. The application experiencing the issue was compiled using Rust 1.86.0. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Our checklist initially omitted architecture. &lt;a href=&quot;https://github.com/mozilla/glean/commit/8693a13ff9057454984cc4cbff08a1ff712d87ff&quot;&gt;A mistake we since fixed&lt;/a&gt;. &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;Apparently we do see &lt;em&gt;some&lt;/em&gt; errors, but they are so infrequent that we can ignore them for now. &lt;a href=&quot;#fr-4-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;Later Yannis wrote a script that can identify broken builds purely much quicker, just by searching for the right string patterns. &lt;a href=&quot;#fr-5-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2025/12/09/incident-report-a-compiler-bug-and-json</guid>
      <pubDate>Tue, 09 Dec 2025 16:01:00 +0100</pubDate>
    </item>
    <item>
      <title>Glean Memory Usage Reporting</title>
      <link>https://fnordig.de/2025/05/28/glean-memory-usage-reporting</link>
      <description>&lt;p&gt;(This article is cross-posted on the &lt;a href=&quot;https://blog.mozilla.org/data/2025/05/28/glean-memory-usage-reporting/&quot;&gt;Data@Mozilla blog&lt;/a&gt;.)&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Since &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1896609&quot;&gt;Bug 1896609&lt;/a&gt; landed we now have &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;Glean&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/glean/index.html&quot;&gt;Firefox on Glean (FOG)&lt;/a&gt; memory reporting built into the Firefox Memory Reporter.
This allows us to measure the allocated memory in use by Glean and FOG.
It currently covers memory allocated by the C++ module of FOG and all instantiated Glean metrics. It does not yet measure the memory used by Glean and its database.&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;How it works&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Firefox has a built-in memory usage reporter, available as &lt;a href=&quot;https://firefox-source-docs.mozilla.org/performance/memory/about_colon_memory.html&quot;&gt;&lt;code&gt;about:memory&lt;/code&gt;&lt;/a&gt;.
Components of Firefox can expose their own memory usage by implementing the &lt;a href=&quot;https://searchfox.org/mozilla-central/source/xpcom/base/nsIMemoryReporter.idl&quot;&gt;&lt;code&gt;nsIMemoryReporter&lt;/code&gt;&lt;/a&gt; interface.
FOG implements this interface and delegates the measurement to the &lt;code&gt;firefox-on-glean&lt;/code&gt; Rust component.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;firefox-on-glean&lt;/code&gt; then collects the memory usage of objects under its own control: all user-defined and runtime-instantiated metrics, additional hashmaps used to track metrics &amp;amp; all user-defined and runtime-instantiated pings. It will soon also collect the memory size of the global Glean object, and thus the memory used for built-in metrics as well as the in-memory database.&lt;/p&gt;
&lt;p&gt;Memory measurement works by following all heap-allocated pointers, asking the allocator for the memory size of each and summing everything up. Because we do most of this measurement in Rust we use the existing &lt;a href=&quot;https://crates.io/crates/wr_malloc_size_of&quot;&gt;wr_malloc_size_of&lt;/a&gt; crate, which already implements the correct measurement for most Rust libstd types as well as some additional library-provided types. Our own types implement the required trait using &lt;a href=&quot;https://crates.io/crates/malloc_size_of_derive&quot;&gt;malloc_size_of_derive&lt;/a&gt; for automatically deriving the trait, or manual implementations.&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;How it looks&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;The memory measurement is built into Firefox and works in every shipped build. Open up &lt;code&gt;about:memory&lt;/code&gt; in a running Firefox,
click the “Measure” button and wait for the measurement.
Once all data is collected it will show a long tree of measured allocations across all processes.
Type &lt;code&gt;fog&lt;/code&gt; into the filter box on the right to trim it down to only allocations from the fog component.
The exact numbers differ between runs and operating systems.&lt;/p&gt;
&lt;p&gt;You will see a view similar to this:&lt;/p&gt;
&lt;figure&gt;
  &lt;img
    src=&quot;https://tmp.fnordig.de/blog/2025/2025-05-28-glean-memory-reporting.png&quot;
    alt=&quot;about:memory on a freshly launched developer build of Firefox. fog reports 0.35 MB of allocated memory in the main process.&quot; /&gt;
  &lt;figcaption&gt;about:memory on a freshly launched developer build of Firefox. fog reports 0.35 MB of allocated memory in the main process.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;After opening a few tabs and browsing the web a new measurement on &lt;code&gt;about:memory&lt;/code&gt; will show a different number,
as Glean is instantiating more metrics and therefore allocating more memory. This number will grow as more metrics are instantiated and kept in memory.&lt;/p&gt;
&lt;p&gt;This currently does not show the allocations from the global Glean object and its in-memory database.
In the future we will be able to measure those allocations as well.
In a prototype locally this already works as expected: As more data is recorded and stored the allocated memory grows.
Once a ping is assembled, submitted and sent the allocations will be freed and &lt;code&gt;about:memory&lt;/code&gt; will report less memory allocated again.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2025/05/28/glean-memory-usage-reporting</guid>
      <pubDate>Wed, 28 May 2025 14:00:00 +0200</pubDate>
    </item>
    <item>
      <title>Seven-year Moziversary</title>
      <link>https://fnordig.de/2025/03/03/seven-year-moziversary</link>
      <description>&lt;p&gt;In March 2018 I started &lt;a href=&quot;/2018/02/18/a-new-job/&quot;&gt;a job as a Telemetry engineer at Mozilla&lt;/a&gt;.
Seven years later I&#39;m still here on my Moziversary, as I was in &lt;a href=&quot;/2019/03/01/one-year-moziversary/&quot;&gt;2019&lt;/a&gt;, &lt;a href=&quot;/2020/03/02/two-year-moziversary/&quot;&gt;2020&lt;/a&gt;, &lt;a href=&quot;/2021/03/01/three-year-moziversary/&quot;&gt;2021&lt;/a&gt;, &lt;a href=&quot;/2022/03/04/four-year-moziversary/&quot;&gt;2022&lt;/a&gt;, &lt;a href=&quot;/2023/03/01/five-year-moziversary/&quot;&gt;2023&lt;/a&gt; and &lt;a href=&quot;/2024/03/12/six-year-moziversary/&quot;&gt;2024&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mozilla is not the same company it was when I joined.
No one on the C-level is here for as long as I am.
There have been 5 larger reorgs in the past year and two layoffs in different departments, plus the big round of layoffs at the Mozilla Foundation.
My part of the organization was moved around again and for the moment Data Engineering is nested under the Infrastructure Org.
Good colleagues left or were laid off.
Just recently my team shrunk again.
Notably I haven&#39;t posted anything under the &lt;a href=&quot;/tagged/mozilla.html&quot;&gt;mozilla tag&lt;/a&gt; since 2022, other than my Moziversary blog posts.&lt;/p&gt;
&lt;p&gt;&lt;strike&gt;All-Hands&lt;/strike&gt; MozWeek&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; Dublin happened.
The next one will be in Washington, D.C.
Probably one of the worst choices given the state of the USA right now, and I might just skip it.
I do hope for a team work week, but that&#39;s not decided yet.&lt;/p&gt;
&lt;p&gt;The one constant over the past years is my work on &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;Glean&lt;/a&gt;, which hasn&#39;t stopped.
We&#39;re finally putting dedicated effort to move legacy telemetry in Firefox Desktop over to Glean (&lt;a href=&quot;https://arewegleanyet.com/&quot;&gt;Are we Glean yet?&lt;/a&gt;).
But still Glean isn&#39;t where I&#39;d like it to be.
Some of the early decisions in its design are coming back to bite us,
the codebase grew significantly and could use a bit of cleanup,
we never got the time to work on performance and memory improvements and our chosen local data storage desperately needs an update.
Some of that was on my list last year already.
If only there were less distractions that pull me of this work again and again.
It&#39;s on my list of goals &lt;em&gt;again&lt;/em&gt; this year, so maybe it works out better this time.&lt;/p&gt;
&lt;p&gt;But other than that I don&#39;t know where Mozilla will be a year from now.
It&#39;s going to be a challenging year.&lt;/p&gt;
&lt;h2&gt;Thank you&lt;/h2&gt;
&lt;p&gt;I&#39;m in this job for seven years not only because I like the tech I get to work on,
but also because my colleagues make it a delight to come back to work every day.
Thanks to &lt;a href=&quot;https://www.a2p.it/&quot;&gt;Alessio&lt;/a&gt;, &lt;a href=&quot;https://chuttenblog.wordpress.com/&quot;&gt;Chris&lt;/a&gt;, &lt;a href=&quot;https://blogoftravis.wordpress.com/&quot;&gt;Travis&lt;/a&gt; and &lt;a href=&quot;https://github.com/abhi-agg&quot;&gt;Abhishek&lt;/a&gt; for being the Data Collection Tools team.
Also thanks to &lt;a href=&quot;https://rosahbruno.github.io/&quot;&gt;Bruno&lt;/a&gt;, who was part of the team until recently.
There&#39;s countless other people at Mozilla,
inside Data Engineering but also across other parts of the organization,
that I got to connect, chat and work with. Thank you!&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Change everywhere. Those Mozilla work weeks were renamed by Marketing. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2025/03/03/seven-year-moziversary</guid>
      <pubDate>Mon, 03 Mar 2025 10:50:00 +0100</pubDate>
    </item>
    <item>
      <title>Six-year Moziversary</title>
      <link>https://fnordig.de/2024/03/12/six-year-moziversary</link>
      <description>&lt;p&gt;Another year went by, so that it&#39;s now been 6 years since I &lt;a href=&quot;/2018/02/18/a-new-job/&quot;&gt;joined Mozilla as a Telemetry engineer&lt;/a&gt;,
I blogged every year since then: &lt;a href=&quot;/2019/03/01/one-year-moziversary/&quot;&gt;2019&lt;/a&gt;, &lt;a href=&quot;/2020/03/02/two-year-moziversary/&quot;&gt;2020&lt;/a&gt;, &lt;a href=&quot;/2021/03/01/three-year-moziversary/&quot;&gt;2021&lt;/a&gt;, &lt;a href=&quot;/2022/03/04/four-year-moziversary/&quot;&gt;2022&lt;/a&gt;, &lt;a href=&quot;/2023/03/01/five-year-moziversary/&quot;&gt;2023&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Looking back at the past year it sure was different than the years before, again.
Obviously we left most of the pandemic isolation behind us and I got to meet more of my coworkers in person:
At the Mozilla All-Hands in Montreal, Canada, though that was cut short for me due to ... of course: Covid.
At PyCon DE and PyData here in Berlin.
And at another workweek with my extended team also here in Berlin.&lt;/p&gt;
&lt;p&gt;My work also changed.
As predicted a year ago I branched out beyond the Glean SDK, took a &lt;a href=&quot;https://youtu.be/nZupfJy6I0A&quot;&gt;look at our data pipeline&lt;/a&gt;,
worked on features across the stack and wrote a ton of stuff that is not code.
Most of that work spanned months and months and some is still not 100% finished.&lt;/p&gt;
&lt;p&gt;For this year I&#39;m focusing a bit more on the SDK and client-side world again.
With Glean used just about everywhere it&#39;s time we look into some optimizations.
In the past we made it correct first and paid less attention to optimize resource usage (CPU &amp;amp; memory for example).
Now that we have more and more usage in Firefox Desktop (Use Counters!) we need to look into making data collection more efficient.
The first step is to get better insights where and how much memory we use.
Then we can optimize.
Firefox comes with some of its own tooling for that with which we need to integrate, see &lt;a href=&quot;about:memory&quot;&gt;about:memory&lt;/a&gt; for example.&lt;/p&gt;
&lt;p&gt;I&#39;m also noticing some parts in our codebase where in hindsight I wish we had made different implementation decisions.
At the time though we did make the right choices, now we need to deal with that (memory usage might be one of these, storage sure is another one).&lt;/p&gt;
&lt;p&gt;And Mozilla more broadly?
It&#39;s changing. All the time.
We just had layoffs and reprioritization of projects.
That certainly dampens the mood.
Focus shifts and work changes.
But underneath there&#39;s still the need to use data to drive our decisions and so I&#39;m rather confident that there&#39;s work for me to do.&lt;/p&gt;
&lt;h2&gt;Thank you&lt;/h2&gt;
&lt;p&gt;None of my work would happen if it weren&#39;t for my manager &lt;a href=&quot;https://www.a2p.it/&quot;&gt;Alessio&lt;/a&gt; and team mates &lt;a href=&quot;https://chuttenblog.wordpress.com/&quot;&gt;Chris&lt;/a&gt;, &lt;a href=&quot;https://blogoftravis.wordpress.com/&quot;&gt;Travis&lt;/a&gt;, &lt;a href=&quot;https://github.com/perrymcmanis144/&quot;&gt;Perry&lt;/a&gt;, &lt;a href=&quot;https://rosahbruno.github.io/&quot;&gt;Bruno&lt;/a&gt; and &lt;a href=&quot;https://github.com/abhi-agg&quot;&gt;Abhishek&lt;/a&gt;.
They make it fun to work here, always have some interesting things to share and they still endure my bad jokes all the time.
Thank you!&lt;br /&gt;
Thanks also goes out to the bigger data engineering team within Mozilla, and all the other people at Mozilla I work or chat with.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;This post was planned to be published more than a week ago. It&#39;s still perfectly in time. I wasn&#39;t able to focus on it earlier.&lt;/em&gt;&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2024/03/12/six-year-moziversary</guid>
      <pubDate>Tue, 12 Mar 2024 11:30:00 +0100</pubDate>
    </item>
    <item>
      <title>Five-year Moziversary</title>
      <link>https://fnordig.de/2023/03/01/five-year-moziversary</link>
      <description>&lt;p&gt;I can&#39;t believe it&#39;s already my fifth Moziversary.
It&#39;s been 5 years now since I &lt;a href=&quot;/2018/02/18/a-new-job/&quot;&gt;joined Mozilla as a Telemetry engineer&lt;/a&gt;,
I blogged every year since then: &lt;a href=&quot;/2019/03/01/one-year-moziversary/&quot;&gt;2019&lt;/a&gt;, &lt;a href=&quot;/2020/03/02/two-year-moziversary/&quot;&gt;2020&lt;/a&gt;, &lt;a href=&quot;/2021/03/01/three-year-moziversary/&quot;&gt;2021&lt;/a&gt;, &lt;a href=&quot;/2022/03/04/four-year-moziversary/&quot;&gt;2022&lt;/a&gt;.
As I&#39;m writing this I&#39;m actually off on vacation (and will be for another week or so) and also it&#39;s super early here.
Nonetheless it&#39;s time to look back and forward.&lt;/p&gt;
&lt;p&gt;So what have I been up to in the past year?
My team changed again. We onboarded Perry and Bruno and when Mike left we got Alessio as the manager of us all.
In September we finally met again at the Mozilla All Hands in Hawaii.
Not everyone was there, but it was great to meet those that were.
I also went to the Berlin office more often. It&#39;s still good to have that other place to work from.&lt;/p&gt;
&lt;p&gt;I didn&#39;t add any new posts to the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;&quot;This Week in Glean&quot;&lt;/a&gt; series and it was effectively retired.
I still believe that openly communicating about our work is very useful and would like to see more of that again.
Maybe I&#39;ll find some topics to write about this year
(and I have some drafts lying around I should finish).
One major piece of work in the past year was migrating Glean to use &lt;a href=&quot;https://github.com/mozilla/uniffi-rs/&quot;&gt;UniFFI&lt;/a&gt;.
That &lt;a href=&quot;https://github.com/mozilla/glean/releases/tag/v50.0.0&quot;&gt;shipped&lt;/a&gt; and I&#39;m proud we rolled it out.
Beyond that I spent large parts of my time supporting our users (other Mozilla applications, mostly mobile),
fixing bugs and slowly tackling some feature improvements.&lt;/p&gt;
&lt;p&gt;And what is for the next year?
I&#39;m in the process of handing over my Glean SDK tech lead role to Travis.
After over 2 years I feel it&#39;s the right time to give up some responsibility and decision power over the project.
I believe that sharing responsibilities and empowering others to fill tech lead positions is an overwhelmingly good and important thing.&lt;/p&gt;
&lt;p&gt;This shift will free me up to expand my work into other places.
I&#39;m staying with the same team and of course a major part of my work will be on the SDK regardless,
but I also hope to expand my knowledge about our data systems end-to-end and have a high-level view and opinion about it.
For the most part Glean feels &quot;complete&quot;, but of course there&#39;s always feature requests, use cases we want to support better and improvements to make.
My list of little things I would like to improve keeps growing, but now also gets new items beyond just the SDK.&lt;/p&gt;
&lt;p&gt;To the next year and beyond!&lt;/p&gt;
&lt;h2&gt;Thank you&lt;/h2&gt;
&lt;p&gt;Thanks to my team mates &lt;a href=&quot;https://www.a2p.it/wordpress/&quot;&gt;Alessio&lt;/a&gt;, &lt;a href=&quot;https://chuttenblog.wordpress.com/&quot;&gt;Chris&lt;/a&gt;, &lt;a href=&quot;https://blogoftravis.wordpress.com/&quot;&gt;Travis&lt;/a&gt;, &lt;a href=&quot;https://github.com/perrymcmanis144/&quot;&gt;Perry&lt;/a&gt; and &lt;a href=&quot;https://rosahbruno.github.io/&quot;&gt;Bruno&lt;/a&gt;
and also thanks to the bigger data engineering team within Mozilla.
And thanks to all the other people at Mozilla I work with.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2023/03/01/five-year-moziversary</guid>
      <pubDate>Wed, 01 Mar 2023 08:00:00 +0200</pubDate>
    </item>
    <item>
      <title>Four-year Moziversary</title>
      <link>https://fnordig.de/2022/03/04/four-year-moziversary</link>
      <description>&lt;p&gt;It&#39;s my fourth Moziversary. It&#39;s been 4 years (and three days) now since I joined Mozilla as a Telemetry engineer.
I joined Mozilla as a Firefox Telemetry Engineer in &lt;a href=&quot;/2018/02/18/a-new-job/&quot;&gt;March 2018&lt;/a&gt;, I blogged three times already: &lt;a href=&quot;/2019/03/01/one-year-moziversary/&quot;&gt;2019&lt;/a&gt;, &lt;a href=&quot;/2020/03/02/two-year-moziversary/&quot;&gt;2020&lt;/a&gt;, &lt;a href=&quot;/2021/03/01/three-year-moziversary/&quot;&gt;2021&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The past year continued to be challenging.
Except for a brief 3-week period the Berlin office stayed close,
so we all continue to work from home.
I haven&#39;t met (most of) my team mates in person since 2020.
I hope that in 2022 I will have the chance to meet some of them again, maybe even all at once.&lt;/p&gt;
&lt;p&gt;I already spent some time on looking back on most of the work that happened on the Glean project last year in a &lt;a href=&quot;/2021/12/17/glean-in-2021/&quot;&gt;This Week in Glean post&lt;/a&gt;,
so no need to reiterate that.&lt;/p&gt;
&lt;p&gt;For 2022 Glean will be about stabilizing, some new features and more widespread adoption across our products.
I&#39;m still excited to continue that work.
We will see what else I pick up along the way.&lt;/p&gt;
&lt;h2&gt;Thank you&lt;/h2&gt;
&lt;p&gt;Thanks to my team mates &lt;a href=&quot;https://www.a2p.it/wordpress/&quot;&gt;Alessio&lt;/a&gt;, &lt;a href=&quot;https://brizental.github.io/&quot;&gt;Bea&lt;/a&gt;, &lt;a href=&quot;https://chuttenblog.wordpress.com/&quot;&gt;Chris&lt;/a&gt;, &lt;a href=&quot;https://blogoftravis.wordpress.com/&quot;&gt;Travis&lt;/a&gt;, and &lt;a href=&quot;http://droettboom.com/&quot;&gt;Mike&lt;/a&gt;,
and also thanks to the bigger data engineering team within Mozilla.
And thanks to all the other people at Mozilla I work with.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2022/03/04/four-year-moziversary</guid>
      <pubDate>Fri, 04 Mar 2022 15:20:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Your personal Glean data pipeline</title>
      <link>https://fnordig.de/2022/02/25/your-personal-glean-data-pipeline</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work.
They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2022/02/25/this-week-in-glean-your-personal-glean-data-pipeline&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;On February 11th, 2022 we hosted a Data Club Lightning Talk session.
There I presented my small side project of setting up a minimal data pipeline &amp;amp; data storage for Glean.&lt;/p&gt;
&lt;p&gt;The premise:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Can I build and run a small pipeline &amp;amp; data server to collect telemetry data from my own usage of tools?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To which I can now answer: Yes, it&#39;s possible.
The complete ingestion server is a couple hundred lines of Rust code.
It&#39;s able to receive pings conforming to the Glean ping schema, transform them and store it into an SQLite database.
It&#39;s very robust, not crashing once on me (except when I created an infinite loop within it).&lt;/p&gt;
&lt;p&gt;You can watch the lightning talk here:&lt;/p&gt;
&lt;br&gt;
&lt;lite-youtube videoid=&quot;V5FgVbxm-cc&quot; playlabel=&quot;Play: Your personal Glean data pipeline&quot;&gt;
 &lt;a href=&quot;https://youtube.com/watch?v=V5FgVbxm-cc&quot; class=&quot;lty-playbtn&quot; title=&quot;Play Video&quot;&gt;
    &lt;span class=&quot;lyt-visually-hidden&quot;&gt;Play Video: Your personal Glean data pipeline&lt;/span&gt;
  &lt;/a&gt;
&lt;/lite-youtube&gt;
&lt;p&gt;Instead of creating some slides for the talk I created an interactive report.
The full report &lt;a href=&quot;https://data.fnordig.de/glean/report.html&quot;&gt;can be read online&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Besides actually writing a small pipeline server this was also an experiment
in trying out &lt;a href=&quot;https://irydium.dev/&quot;&gt;Irydium&lt;/a&gt; and &lt;a href=&quot;https://datasette.io/&quot;&gt;Datasette&lt;/a&gt;
to produce an interactive &amp;amp; live-updated data report.&lt;/p&gt;
&lt;p&gt;Irydium is a set of tooling designed to allow people to create interactive documents using web technologies, started by &lt;a href=&quot;https://twitter.com/wrlach&quot;&gt;wlach&lt;/a&gt; a while back.
Datasette is an open source multi-tool for exploring and publishing data, created and maintained by &lt;a href=&quot;https://twitter.com/simonw&quot;&gt;simonw&lt;/a&gt;.
Combining both makes for a nice experience, even though there&#39;s still some things that could be simplified.&lt;/p&gt;
&lt;p&gt;My pipeline server is currently not open source.
I might publish it as an example at a later point.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2022/02/25/your-personal-glean-data-pipeline</guid>
      <pubDate>Fri, 25 Feb 2022 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Building and Deploying a Rust library on iOS</title>
      <link>https://fnordig.de/2022/01/31/rust-libraries-on-ios</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work.
They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2022/01/31/this-week-in-glean-building-and-deploying-a-rust-library-on-ios/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;We ship the Glean SDK for multiple platforms, one of them being iOS applications.
Previously I talked about &lt;a href=&quot;/2021/04/16/rustc-ios-and-an-m1/&quot;&gt;how we got it to build on the Apple ARM machines&lt;/a&gt;.
Today we will take a closer look at how to bundle a Rust static library into an iOS application.&lt;/p&gt;
&lt;p&gt;The Glean SDK project was set up in 2019 and we have evolved its project configuration over time.
A lot has changed in Xcode since then, so for this article we&#39;re starting with a fresh Xcode project, a fresh Rust library and put it all together step by step.&lt;br /&gt;
This is essentially an update to the &lt;a href=&quot;https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-06-rust-on-ios.html&quot;&gt;Building and Deploying a Rust library on iOS&lt;/a&gt; article from 2017.&lt;/p&gt;
&lt;p&gt;For future readers: This was done using Xcode 13.2.1 and rustc 1.58.1.&lt;br /&gt;
&lt;em&gt;One note: I learned iOS development to the extent required to ship Glean iOS.
I&#39;ve never written a full iOS application and lack a lot of experience with Xcode.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;The application&lt;/h2&gt;
&lt;p&gt;The premise of our application is easy:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Show a non-interactive message to the user with data from a Rust library.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let&#39;s get started on that.&lt;/p&gt;
&lt;h2&gt;The project&lt;/h2&gt;
&lt;p&gt;We start with a fresh iOS project.
Go to File -&amp;gt; New -&amp;gt; Project, then choose the iOS App template,
give it a name such as &lt;code&gt;ShippingRust&lt;/code&gt;,
select where to store it and finally create it.
You&#39;re greeted with &lt;code&gt;ContentView.swift&lt;/code&gt; and the following code:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;import SwiftUI
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;struct ContentView: View {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    var body: some View {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        Text(&amp;quot;Hello, world!&amp;quot;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            .padding()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can build and run it now. This will open the Simulator and display &quot;Hello, world!&quot;.
We&#39;ll get back to the Swift application later.&lt;/p&gt;
&lt;h2&gt;The Rust parts&lt;/h2&gt;
&lt;p&gt;First we set up the Rust library.&lt;/p&gt;
&lt;p&gt;In a terminal navigate to your &lt;code&gt;ShippingRust&lt;/code&gt; project directory.
In there create a new Rust crate:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo new --lib shipping-rust-ffi
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We will need a static library, so we change the crate type in the generated &lt;code&gt;shipping-rust-ffi/Cargo.toml&lt;/code&gt;.
Add the following below the package configuration:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[lib]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;crate-type = [&amp;quot;staticlib&amp;quot;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s also turn the project into a Cargo workspace.
Create a new top-level &lt;code&gt;Cargo.toml&lt;/code&gt; with the content:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[workspace]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;members = [
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &amp;quot;shipping-rust-ffi&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;cargo build&lt;/code&gt; in the project directory should work now and create a new static library.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ ls -l target/debug/libshipping_rust_ffi.a
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;-rw-r--r-- 2 jer staff 16061952 Jan 28 13:09 target/debug/libshipping_rust_ffi.a
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s add some code to &lt;code&gt;shipping-rust-ffi/src/lib.rs&lt;/code&gt; next.
Nothing fancy, a simple function taking some arguments and returning the sum:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::os::raw::&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;c_int&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[no_mangle]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;shipping_rust_addition&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(a: c_int, b: c_int) -&amp;gt; c_int {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    a &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; b
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;no_mangle&lt;/code&gt; ensures the name lands in the compiled library as-is
and the &lt;code&gt;extern &quot;C&quot;&lt;/code&gt; makes sure it uses the right ABI.&lt;/p&gt;
&lt;p&gt;We now have a Rust library exporting a C-ABI compatible interface.
We can now consume this in our iOS application.&lt;/p&gt;
&lt;h2&gt;The Xcode parts&lt;/h2&gt;
&lt;p&gt;Before we can use the code we need a bit more setup.
Strap in, there&#39;s a lot of fiddly manual steps now&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;We start by linking against the &lt;code&gt;libshipping_rust_ffi.a&lt;/code&gt; library.
In your Xcode project open your target configuration&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;,
go to &quot;Build Phases&quot;, then look for &quot;Link Binary with Libraries&quot;.
Add a new one, in the popup select &quot;Add files&quot; on the bottom left
and look for the &lt;code&gt;target/debug/libshipping_rust_ffi.a&lt;/code&gt; file.
Yes, that&#39;s actually for the wrong target. This is just for the name, we&#39;ll fix up the path next.
Go to &quot;Build Settings&quot; and search for &quot;Library Search Paths&quot;.
It probably has the path to file in there right now for both &lt;code&gt;Debug&lt;/code&gt; and &lt;code&gt;Release&lt;/code&gt; builds.
Remove that one for &lt;code&gt;Debug&lt;/code&gt;, then add a new row by clicking the small &lt;code&gt;+&lt;/code&gt; symbol.
Select the &lt;code&gt;Any Driverkit&lt;/code&gt; matcher.
It doesn&#39;t matter which matcher you choose or what value you give it,
but when we overwrite this manually in the next step I&#39;ll assume you chose &lt;code&gt;Any Driverkit&lt;/code&gt;.
Do the same for the &lt;code&gt;Release&lt;/code&gt; configuration.&lt;/p&gt;
&lt;p&gt;Once that&#39;s done, save your project and go back to your project directory.
We will modify the project configuration to have Xcode look for the library based on the target it is building for&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.
Open up &lt;code&gt;ShippingRust.xcodeproj/project.pbxproj&lt;/code&gt; in a text editor,
then search for the first line with &lt;code&gt;&quot;LIBRARY_SEARCH_PATHS[sdk=driverkit*]&quot;&lt;/code&gt;.
It should be in a section saying &lt;code&gt;/* Debug */&lt;/code&gt;.
Remove the &lt;code&gt;LIBRARY_SEARCH_PATHS&lt;/code&gt; line and add 3 new ones:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/aarch64-apple-ios/debug&amp;quot;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/aarch64-apple-ios-sim/debug&amp;quot;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/x86_64-apple-ios/debug&amp;quot;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Look for the next line with &lt;code&gt;&quot;LIBRARY_SEARCH_PATHS[sdk=driverkit*]&quot;&lt;/code&gt;, now in a &lt;code&gt;/* Release */&lt;/code&gt; section and replace it with:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/aarch64-apple-ios/release&amp;quot;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/aarch64-apple-ios-sim/release&amp;quot;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;quot;LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]&amp;quot; = &amp;quot;$(PROJECT_DIR)/target/x86_64-apple-ios/release&amp;quot;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save the file and return focus back to Xcode.
If you didn&#39;t make any typos Xcode should still have your project open.
In the settings you will find the library search paths as we&#39;ve just defined them.
If you messed something up Xcode will complain that it cannot read the project file if you try to go to the settings.&lt;/p&gt;
&lt;p&gt;Next we need to teach Xcode how to compile Rust code.
Once again go to your target settings, selecting the &quot;Build Phases&quot; tab again.&lt;/p&gt;
&lt;p&gt;There add a new &quot;Run Script&quot; phase, give it the name &quot;Build Rust library&quot;
(double-click the &quot;Run Script&quot; section header),
and set the command to:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;bash ${PROJECT_DIR}/bin/compile-library.sh shipping-rust-ffi $buildvariant
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;compile-library.sh&lt;/code&gt; script is going to do the heavy lifting.
The first argument is the crate name we want to compile, the second is the build variant to select.
This is not yet defined, so let&#39;s do it first.&lt;/p&gt;
&lt;p&gt;Go to the &quot;Build Settings&quot; tab and click the &lt;code&gt;+&lt;/code&gt; button to add a new &quot;User-Defined Setting&quot;.
Give it the name &lt;code&gt;buildvariant&lt;/code&gt; and choose a value based on the build variant: &lt;code&gt;debug&lt;/code&gt; for &lt;code&gt;Debug&lt;/code&gt; and &lt;code&gt;release&lt;/code&gt; for &lt;code&gt;Release&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now we need the actual script to build the Rust library for the right targets.
It&#39;s a bit long to write out, but the logic is not too complex:
First we select the Cargo profile to use based on our &lt;code&gt;buildvariant&lt;/code&gt; (that is whether to pass &lt;code&gt;--release&lt;/code&gt; or not),
then we set up &lt;code&gt;LIBRARY_PATH&lt;/code&gt; if necessary and finally compile the Rust library for the selected target.
Xcode passes the architectures to build in &lt;code&gt;ARCHS&lt;/code&gt;.
It&#39;s either &lt;code&gt;x86_64&lt;/code&gt; for simulator builds on Intel Mac hardware or &lt;code&gt;arm64&lt;/code&gt;.
If it&#39;s &lt;code&gt;arm64&lt;/code&gt; it can be either the simulator or an actual hardware target.
Those differ, but we can know which is which from what&#39;s in &lt;code&gt;LLVM_TARGET_TRIPLE_SUFFIX&lt;/code&gt; and select the right Rust target.&lt;/p&gt;
&lt;p&gt;Let&#39;s put all of that into a &lt;code&gt;compile-library.sh&lt;/code&gt; script.
Create a new directory &lt;code&gt;bin&lt;/code&gt; in your project directory.
In there create the file with the following content:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;$&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;-ne 2 &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;echo &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;Usage (note: only call inside xcode!):&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;echo &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;compile-library.sh &amp;lt;FFI_TARGET&amp;gt; &amp;lt;buildvariant&amp;gt;&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;exit&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; 1
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# what to pass to cargo build -p, e.g. your_lib_ffi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FFI_TARGET&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;1
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# buildvariant from our xcconfigs
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;BUILDVARIANT&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;2
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;RELFLAG&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[[ &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;$&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;BUILDVARIANT&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;debug&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]]&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  RELFLAG&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;--release
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;set &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;-euvx
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[[ &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;-n &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;${&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;DEVELOPER_SDK_DIR&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;:-&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;}&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]]&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# Assume we&amp;#39;re in Xcode, which means we&amp;#39;re probably cross-compiling.
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# In this case, we need to add an extra library search path for build scripts and proc-macros,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# which run on the host instead of the target.
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# (macOS Big Sur does not have linkable libraries in /usr/lib/.)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;export &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;LIBRARY_PATH&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;${&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;DEVELOPER_SDK_DIR&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;}/MacOSX.sdk/usr/lib:${&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;LIBRARY_PATH&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;:-&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;}&amp;quot;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;IS_SIMULATOR&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;0
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;${&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;LLVM_TARGET_TRIPLE_SUFFIX&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;}&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;-simulator&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  IS_SIMULATOR&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;1
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; arch &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$ARCHS&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; do
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;case &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;$&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;arch&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;in
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    x86_64&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$IS_SIMULATOR -eq 0 &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;echo &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;Building for x86_64, but not a simulator build. What&amp;#39;s going on?&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;2
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;exit&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; 2
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# Intel iOS simulator
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;export &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CFLAGS_x86_64_apple_ios&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;-target x86_64-apple-ios&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      $HOME/.cargo/bin/cargo build -p $FFI_TARGET --lib $RELFLAG --target x86_64-apple-ios
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      ;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    arm64&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;$IS_SIMULATOR -eq 0 &lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;; then
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;# Hardware iOS targets
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        $HOME/.cargo/bin/cargo build -p $FFI_TARGET --lib $RELFLAG --target aarch64-apple-ios
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;else
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        $HOME/.cargo/bin/cargo build -p $FFI_TARGET --lib $RELFLAG --target aarch64-apple-ios-sim
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fi
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;esac
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;done
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now we&#39;re done with the setup for compiling the Rust library automatically as part of the Xcode project build.&lt;/p&gt;
&lt;h2&gt;The code parts&lt;/h2&gt;
&lt;p&gt;We now have an Xcode project that builds our Rust library and links against it.
We now need to use this library!&lt;/p&gt;
&lt;p&gt;Swift speaks Objective-C, which is an extension to C,
but we need to tell it about the things available.
In C land that&#39;s done with a header.
Let&#39;s create a new file, select the &quot;Header File&quot; template and name it &lt;code&gt;FfiBridge.h&lt;/code&gt;.
This will create a new file with this content:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;#ifndef&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; FfiBridge_h
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;#define &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiBridge_h
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;#endif &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;/* FfiBridge_h */
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we need to add the definition of our function.
As a reminder this is its definition in Rust:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;shipping_rust_addition&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(a: c_int, b: c_int) -&amp;gt; c_int;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This translates to the following in C:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;int &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;shipping_rust_addition&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;int &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;a, &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;int &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;b);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add that line between the &lt;code&gt;#define&lt;/code&gt; and &lt;code&gt;#endif&lt;/code&gt; lines.
Xcode doesn&#39;t know about that file yet, so once more into the &lt;code&gt;Build Settings&lt;/code&gt; of the target.
Search for &lt;code&gt;Objective-C Bridging Header&lt;/code&gt; and set it to &lt;code&gt;$(PROJECT_DIR)/ShippingRust/FfiBridge.h&lt;/code&gt;.
In &lt;code&gt;Build Phases&lt;/code&gt; add a new &lt;code&gt;Header Phase&lt;/code&gt;.
There you add the &lt;code&gt;FfiBridge.h&lt;/code&gt; as well.&lt;/p&gt;
&lt;p&gt;If it now all compiles we&#39;re finally ready to use our Rust library.&lt;/p&gt;
&lt;p&gt;Open up &lt;code&gt;ContentView.swift&lt;/code&gt; and change the code to call your Rust library:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;struct ContentView: View {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    var body: some View {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        Text(&amp;quot;Hello, world! \(shipping_rust_addition(30, 1))&amp;quot;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            .padding()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We simply interpolate the result of &lt;code&gt;shipping_rust_addition(30, 1)&lt;/code&gt; into the string displayed.&lt;/p&gt;
&lt;p&gt;Once we compile and run it in the simulator we see we&#39;ve succeeded at satisfying our premise:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Show a non-interactive message to the user with data from a Rust library.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2022/ios-simulator-helloworld31.png&quot; alt=&quot;iOS simulator running our application showing &amp;quot;Hello, world! 31&amp;quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Compiling for any iOS device should work just as well.&lt;/p&gt;
&lt;h2&gt;The next steps&lt;/h2&gt;
&lt;p&gt;This was a lot of setup for calling one simple function.
Luckily this is a one-time setup. From here on you can extend your Rust library, define them in the header file and call them from Swift.
If you go that route you should really start using &lt;a href=&quot;https://github.com/eqrion/cbindgen&quot;&gt;cbindgen&lt;/a&gt; to generate that header file automatically for you.&lt;/p&gt;
&lt;p&gt;This time we looked at building an iOS application directly calling a Rust library.
That&#39;s not actually how Glean works. The Glean Swift SDK itself wraps the Rust library and exposes a Swift library.
In a next blog post I&#39;ll showcase how we ship that as a Swift package.&lt;/p&gt;
&lt;p&gt;For Glean we&#39;re stepping away from manually writing our FFI functions.
We&#39;re instead migrating our code base to use &lt;a href=&quot;https://github.com/mozilla/uniffi-rs/&quot;&gt;UniFFI&lt;/a&gt;.
UniFFI will generate the C API from an API definitions file and also comes with a bit of runtime code to handle conversion between Rust, C and Swift data types for us.
We&#39;re not there yet for Glean, but you can try it on your own. &lt;a href=&quot;https://mozilla.github.io/uniffi-rs/&quot;&gt;Read the UniFFI documentation&lt;/a&gt; and integrate it into your project.
It should be possible to extent the setup we done her to also run the necessary steps for UniFFI.
Eventually I&#39;ll document how we did it as well.&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;And most of these steps are user-interface-dependent and might be different in future Xcode version. :( &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Click your project name in the tree view on the left. This gets you to the project configuration (backed by the &lt;code&gt;ShippingRust.xcodeproj/project.pbxproj&lt;/code&gt; file). You should then see the Targets, including your &lt;code&gt;ShippingRust&lt;/code&gt; target and probably &lt;code&gt;ShippingRustTests&lt;/code&gt; as well. We need the former. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Previously we would have built a universal library containing the library of multiple targets. That doesn&#39;t work anymore now that &lt;code&gt;arm64&lt;/code&gt; can stand for both the simulator and hardware targets. Thus linking to the individual libraries is the way to go, as the now-deprecated &lt;a href=&quot;https://github.com/TimNN/cargo-lipo&quot;&gt;&lt;code&gt;cargo-lipo&lt;/code&gt;&lt;/a&gt; also points out. &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2022/01/31/rust-libraries-on-ios</guid>
      <pubDate>Mon, 31 Jan 2022 12:40:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Looking back at Glean in 2021</title>
      <link>https://fnordig.de/2021/12/17/glean-in-2021</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2021/12/17/this-week-in-glean-looking-back-at-glean-in-2021&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;A year ago I posted &lt;a href=&quot;/2020/12/18/glean-in-2021/&quot;&gt;Glean in 2021&lt;/a&gt; as a way to look into the future
and set out a vision and plan for the project.
Today I&#39;m looking back at 2021, if we were able to follow up on my plans back then and look at all the other things we did for Glean.&lt;/p&gt;
&lt;p&gt;Let&#39;s start easy:
According to &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;the index&lt;/a&gt; we wrote 21 This Week in Glean blog posts (including this one).
Close enough to one every other week.
Communicating about our work is important and TWiGs are one way to put our ideas and thoughts about the project out there.&lt;/p&gt;
&lt;p&gt;Let&#39;s first look at the topics I identified as important in last year&#39;s blog post.&lt;/p&gt;
&lt;h2&gt;The vision&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The Glean SDK is a fully self-servable telemetry SDK, usable across different platforms.
It enables product owners and engineers to instrument their products and rely on their data collection,
while following Mozilla policies &amp;amp; privacy standards.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&#39;d say we&#39;re in pretty good shape here.
The docs on &lt;a href=&quot;https://mozilla.github.io/glean/book/user/adding-glean-to-your-project/index.html&quot;&gt;how to add Glean to a project&lt;/a&gt; need some updates,
but we also added a post for a slightly different audience: &lt;a href=&quot;https://mozilla.github.io/glean/book/user/integrating-glean-for-product-managers.html&quot;&gt;Integrating Glean for product managers&lt;/a&gt;,
so it&#39;s not only for engineers anymore.
We assisted others when they integrated Glean, but more for general data and instrumentation knowledge.&lt;/p&gt;
&lt;h2&gt;The ideas&lt;/h2&gt;
&lt;h3&gt;Metric types&lt;/h3&gt;
&lt;p&gt;We specified &amp;amp; implemented 3 new metric types this year.
The &lt;a href=&quot;https://mozilla.github.io/glean/book/reference/metrics/rate.html&quot;&gt;&lt;code&gt;rate&lt;/code&gt; metric&lt;/a&gt; has been implemented in the Rust and JavaScript SDKs and is also available on Firefox Desktop.
The &lt;a href=&quot;https://mozilla.github.io/glean/book/reference/metrics/url.html&quot;&gt;&lt;code&gt;url&lt;/code&gt; metric&lt;/a&gt; is available in all SDKs, but not yet exposed on Firefox Desktop.
The &lt;a href=&quot;https://mozilla.github.io/glean/book/reference/metrics/text.html&quot;&gt;&lt;code&gt;text&lt;/code&gt; metric&lt;/a&gt; is currently JavaScript-only.&lt;/p&gt;
&lt;p&gt;However the &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;text&lt;/code&gt; metric were not usable until recently because of bugs in our schema generation tool.
We had to change how we generate the table schema for these and other metric types in the future a bit,
but the pipeline now correctly ingests data for these metrics
and users can query the data in the columns where they expect them.&lt;/p&gt;
&lt;h3&gt;Revamped testing APIs&lt;/h3&gt;
&lt;p&gt;We implemented some of the new testing APIs, namely &lt;a href=&quot;https://github.com/mozilla/glean/pull/1482&quot;&gt;metric coverage support&lt;/a&gt; and &lt;a href=&quot;https://github.com/mozilla/glean/pull/1507&quot;&gt;&lt;code&gt;Ping.testBeforeNextSubmit&lt;/code&gt;&lt;/a&gt;.
Glean and FOG already use these new testing capabilities, but to my knowledge other Glean users are not yet relying on that.
Certainly an area we should make more progress on in the coming year.&lt;/p&gt;
&lt;h3&gt;UniFFI - generate all the code&lt;/h3&gt;
&lt;p&gt;Migration to rely on &lt;a href=&quot;https://github.com/mozilla/uniffi-rs/&quot;&gt;UniFFI&lt;/a&gt; for code generation has started!
Right now adding new features to Glean &lt;a href=&quot;https://mozilla.github.io/glean/dev/core/new-metric-type.html&quot;&gt;requires changes across all SDKs&lt;/a&gt;.
With UniFFI we can define the API of metric types once, implement it in Rust and get the code for the SDKs generated automatically.
Less manual code means less potential for bugs and easier maintenance.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/mozilla/glean/tree/uniffi&quot;&gt;&lt;code&gt;uniffi&lt;/code&gt; branch&lt;/a&gt; is used for slowly migrating Glean piece by piece.
Most of the metric types are &lt;a href=&quot;https://github.com/badboy/glean/blob/4ae34b0f217160924a8c74165e387e190937fd33/glean-core/src/glean.udl&quot;&gt;defined in UDL now&lt;/a&gt; and the Kotlin code base has been migrated to it already,
with all tests passing again.
Work on this will continue next year, migrating the Swift, Python and Rust SDKs and then eventually merging it back into the main branch,
so we can ship it to users.
From there adding new metrics will require less implementation work and thus will allow us to follow up with some of the existing but currently paused requests.&lt;/p&gt;
&lt;h2&gt;All the other things&lt;/h2&gt;
&lt;h3&gt;Glean&lt;/h3&gt;
&lt;p&gt;We &lt;a href=&quot;https://github.com/mozilla/glean/releases&quot;&gt;released&lt;/a&gt; 9 major versions of Glean and did 33 releases in total.
We&#39;re very liberal with breaking changes &amp;amp; major releases,
though we make sure that upgrades require minimal changes where possible.
The Kotlin, Swift, Python &amp;amp; Rust SDKs are versioned all the same,
so a breaking change in only one SDK will still cause a major release for other SDKs, even without breaking changes.&lt;/p&gt;
&lt;p&gt;More products and projects are now using Glean, including &lt;a href=&quot;https://rally.mozilla.org/&quot;&gt;Rally studies&lt;/a&gt;, the &lt;a href=&quot;https://www.mozilla.org/products/vpn/&quot;&gt;Mozilla VPN client&lt;/a&gt;, and the new version of &lt;a href=&quot;https://dictionary.telemetry.mozilla.org/apps/focus_android&quot;&gt;Focus for Android&lt;/a&gt;.
A full list of products is available in the &lt;a href=&quot;https://dictionary.telemetry.mozilla.org/&quot;&gt;Glean Dictionary&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To ease integration between telemetry collected in Gecko and telemetry collected in the Android parts of the browser
we&#39;re now &lt;a href=&quot;https://fnordig.de/2021/09/17/glean-geckoview/&quot;&gt;shipping Glean through GeckoView&lt;/a&gt;. (After &lt;a href=&quot;https://fnordig.de/2021/11/01/crashes-and-a-buggy-glean/&quot;&gt;crashing it&lt;/a&gt;, fixing it and shipping it again without new bugs cropping up.)
There&#39;s some work to be done next year to make local development easier again and to automate some of the tasks of upgrading Glean across applications.&lt;/p&gt;
&lt;h3&gt;Firefox on Glean (FOG)&lt;/h3&gt;
&lt;p&gt;We invested a lot of time in making the Firefox integration better,
fixing bugs and convincing people to migrate their instrumentation to the new Glean-based system.
It&#39;s going slow, but we now have the &lt;a href=&quot;https://dictionary.telemetry.mozilla.org/apps/firefox_desktop&quot;&gt;first few important metrics&lt;/a&gt; in Glean pings coming from Firefox Desktop.
Additionally Glean was used to provide telemetry for the new &lt;a href=&quot;https://dictionary.telemetry.mozilla.org/apps/firefox_desktop_background_update&quot;&gt;Desktop Background Updater&lt;/a&gt;.
Next year we hope to convince more people to start using Glean in Desktop,
with the added benefit that this data will also be available in Firefox for Android.&lt;/p&gt;
&lt;h3&gt;Glean.js&lt;/h3&gt;
&lt;p&gt;A year ago &lt;a href=&quot;https://github.com/mozilla/glean.js/commit/46f028fb4ea7b8f312daf4666904c81d0a3eb171&quot;&gt;Glean.js was just started&lt;/a&gt;.
Thanks to Bea&#39;s tireless work it&#39;s now nearly feature-complete compared to the other Glean SDKs
and used in production in applications &amp;amp; web extensions and soon even used to instrument websites.
Next year Bea aims for a proper stable v1.0 release and hopefully more use across different products.
It&#39;s a real alternative for those platforms where the initial set of SDKs don&#39;t cut it.&lt;/p&gt;
&lt;p&gt;Glean surely is becoming the one telemetry solution across Mozilla products.&lt;/p&gt;
&lt;h3&gt;Tooling: GLAM, Dictionary, Looker&lt;/h3&gt;
&lt;p&gt;These are the tools I&#39;m much less directly involved in,
but they make up an important part of the Glean ecosystem.
After all these are where users actually get to analyze at the data they collect.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.telemetry.mozilla.org/cookbooks/glam.html&quot;&gt;GLAM&lt;/a&gt; currently only serves data for Firefox Desktop using legacy telemetry data as well as Firefox for Android using Glean data.
Things are in place to enable more Glean-powered products soon, once we &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1742448&quot;&gt;iron out some details around data expectations from applications&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://dictionary.telemetry.mozilla.org/&quot;&gt;Glean Dictionary&lt;/a&gt; saw near-weekly releases
and went from &quot;promising prototype&quot; into &quot;valuable production tool&quot; this year,
thanks to a lot of work from &lt;a href=&quot;https://github.com/wlach&quot;&gt;wlach&lt;/a&gt; and &lt;a href=&quot;https://github.com/Iinh&quot;&gt;linh&lt;/a&gt;.
It was the basis of several initiatives such as &lt;a href=&quot;https://github.com/mozilla/glean-annotations/&quot;&gt;metric annotations&lt;/a&gt; and &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1734011&quot;&gt;tagging support&lt;/a&gt;.
These things will be helpful to make data at Mozilla more discoverable and better documented.&lt;/p&gt;
&lt;p&gt;The primary tool for analyzing data at Mozilla is now &lt;a href=&quot;https://looker.com/&quot;&gt;Looker&lt;/a&gt;.
Folks have been very busy making more and more data accessible to both data experts and non-experts alike&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
Glean data is (more or less) automatically available in Looker explores, for example &lt;a href=&quot;https://docs.telemetry.mozilla.org/cookbooks/looker/event_counts_explore.html&quot;&gt;event counts&lt;/a&gt;.
Instead of bringing up ad hoc dashboards for initiatives when needed we can usually recommend that people just build things in Looker.
That has the major advantage that exploration beyond what the dashboard summarizes is just one or two clicks away.
I&#39;m excited to shift my own use away from &lt;a href=&quot;https://docs.telemetry.mozilla.org/tools/stmo.html&quot;&gt;fiddling around with SQL&lt;/a&gt; to more approachable explores &amp;amp; dashboards,
even for one-time analysis.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2022&lt;/h2&gt;
&lt;p&gt;I&#39;m saving an outlook on the next year of Glean for some other time.
I called out some areas of work above that will see more work next year,
and then there&#39;s also new projects &amp;amp; ideas coming up.
I still plan to continue work on Glean for the vast majority of my time.&lt;/p&gt;
&lt;h2&gt;Thanks&lt;/h2&gt;
&lt;p&gt;The This Week in Glean series is going into winter hiatus until January 2022.
Thanks to everyone who contributed to This Week in Glean blog posts in 2021:&lt;/p&gt;
&lt;p&gt;Alessio, Travis, Chutten, Bea, Raphael, Anthony, Will.&lt;/p&gt;
&lt;p&gt;And of course thanks to everyone who contributed to Glean and the wider ecosystem around it.&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;We have some &lt;a href=&quot;https://docs.telemetry.mozilla.org/cookbooks/looker/intro.html&quot;&gt;pretty cool documentation to get you started with Looker!&lt;/a&gt; &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2021/12/17/glean-in-2021</guid>
      <pubDate>Fri, 17 Dec 2021 14:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Crashes &amp; a buggy Glean</title>
      <link>https://fnordig.de/2021/11/01/crashes-and-a-buggy-glean</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2021/11/01/this-week-in-glean-crashes-a-buggy-glean&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;In September I finally &lt;a href=&quot;/2021/09/17/glean-geckoview/&quot;&gt;landed work to ship Glean through GeckoView&lt;/a&gt;.
Contrary to what that post said Fenix did not actually &lt;em&gt;use&lt;/em&gt; Glean coming from GeckoView immediately due to another bug that took us &lt;a href=&quot;https://github.com/mozilla-mobile/android-components/pull/11045&quot;&gt;another few days&lt;/a&gt; to land.
Shortly after that was shipped in a Fenix Nightly release we received a crash report (&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1733757&quot;&gt;bug 1733757&lt;/a&gt;) pointing to code that we haven&#39;t touched in a long time.
And yet the change of switching from a standalone Glean library to shipping Glean in GeckoView uncovered a crashing bug, that quickly rose to be the top crasher for Fenix for more than a week.&lt;/p&gt;
&lt;p&gt;When I picked up that bug after the weekend I was still thinking that this would be &lt;em&gt;just&lt;/em&gt; a bug, which we can identify &amp;amp; fix and then get into the next Fenix release.
But in data land nothing is ever &lt;em&gt;just&lt;/em&gt; a bug.&lt;/p&gt;
&lt;p&gt;As I don&#39;t own an Android device myself I was initially restricted to the Android emulator,
but I was unsuccessful in triggering that bug in my simple use of Fenix or in any tests I wrote.
At some point I went as far as &lt;a href=&quot;https://fnordig.de/2021/10/14/fenix-physical-device-testing/&quot;&gt;leveraging physical devices in the Firebase test lab&lt;/a&gt;,
still with no success of hitting the bug.
Later that week I picked up an Android test device, hoping to find easy steps to reproduce the crash.
Thankfully we also have quality assurance people running tests and simply &lt;em&gt;using&lt;/em&gt; the browser
and reporting back steps to reproduce bugs and crashes.
And so that&#39;s what one of them, Delia, did: &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/issues/21767&quot;&gt;Providing simple steps to reproduce the crash&lt;/a&gt;.
Simple here meant: open a website and leave the phone untouched for roughly 8-9 minutes.
With those steps I was able to reproduce the crash in both the emulator and my test device as well.&lt;/p&gt;
&lt;p&gt;As I was waiting for the crash to occur I started reading the code again.
From the crash report I already knew the &lt;a href=&quot;https://github.com/mozilla/ffi-support/blob/0fdc22a8dfe3731be5fd39b311e4e4885219e26c/src/handle_map.rs#L409&quot;&gt;exact place where the code panics&lt;/a&gt; and thus crashes the application,
I just didn&#39;t know how it got there.
While reading the code around the panic and the knowledge that it takes several minutes to get to the panic I finally stumbled upon a clue:
The map implementation that was used internally has &lt;a href=&quot;https://github.com/mozilla/ffi-support/blob/0fdc22a8dfe3731be5fd39b311e4e4885219e26c/src/handle_map.rs#L160-L166&quot;&gt;a maximum capacity of elements it can store&lt;/a&gt;.
It even documents that it will panic&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;!&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;/// The maximum capacity of a [`HandleMap`]. Attempting to instantiate one with
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;/// a larger capacity will cause a panic.
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;///
&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;/// [...]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub const &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;MAX_CAPACITY&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;usize = &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;&amp;lt;&amp;lt; &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I now knew that at some point Glean exhausts the map capacity,
slowly but eventually leading to a panic&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.
Most of Glean is set up to not require dynamically allocating new things other than the data itself,
but we never store the data itself within such a map.
So where are we using a map and dynamically add new entries to it and potentially forget to remove them after use?&lt;/p&gt;
&lt;p&gt;Luckily the stack trace from those crash reports gave me another clue:
All crashes were caused by &lt;a href=&quot;https://mozilla.github.io/glean/book/reference/metrics/labeled_counters.html&quot;&gt;labeled counters&lt;/a&gt;.
Some instrument-the-code-paths-and-recompile cycles later I was able to pinpoint it to the exact metric that was causing the crash.&lt;/p&gt;
&lt;p&gt;With all this information collected I was able to determine that while the panic was happening in a library we use,
the problem was that Glean had the wrong assumptions about how the use of labeled counters in Kotlin maps to objects in a Rust map.
On every subscript access to a labeled counter (&lt;code&gt;myCounter[&quot;label&quot;]&lt;/code&gt;) Glean would create a new object, store it in the map and return a handle to this object.
The solution was to avoid creating new entries in that map on every access from a foreign language and instead cache created objects by a unique identifier
and hand out already-created objects when re-accessed.
This fix &lt;a href=&quot;https://github.com/mozilla/glean/commit/499309475f4f002bdd6c19db4aa051634760efe1#diff-fe013beaf77cb562dae30dd3e639f386b9c9f01d6bc6800538ccd72eb89ad68cR77-R107&quot;&gt;was implemented in a few lines&lt;/a&gt;, accompanied by an extensive commit message as well as tests in all of the 3 major foreign-language Glean SDKs.&lt;/p&gt;
&lt;p&gt;That fix was released in &lt;a href=&quot;https://github.com/mozilla/glean/releases/tag/v42.0.1&quot;&gt;Glean v42.0.1&lt;/a&gt;, and shortly after in Fenix Nightly and Beta.&lt;/p&gt;
&lt;p&gt;The bug was fixed and the crash prevented, but that wasn&#39;t the end of it.
The code leading to the bug has been in Glean since at least March 2020
and yet we only started seeing crashes with the GeckoView change.
What was happening before? Did we miss these crashes for more than a year or were there simply no crashes?&lt;/p&gt;
&lt;p&gt;To get a satisfying answer to these questions I had to retrace the issue in older Glean versions.
I took older versions of Glean &amp;amp; Fenix from just before the GeckoView-Glean changes,
added logging and built myself a Fenix to run in the emulator.
And as quickly as that&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; &lt;code&gt;logcat&lt;/code&gt; spit out the following lines repeatedly:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;E  ffi_support::error: Caught a panic calling rust code: &amp;quot;called `Result::unwrap()` on an `Err` value: \&amp;quot;PoisonError { inner: .. }\&amp;quot;&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;E  glean_ffi::handlemap_ext: Glean failed (ErrorCode(-1)): called `Result::unwrap()` on an `Err` value: &amp;quot;PoisonError { inner: .. }&amp;quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No crashes! It panics, but it doesn&#39;t crash in old Fenix versions.
So why does it crash in new versions?
It&#39;s a combination of things.&lt;/p&gt;
&lt;p&gt;First Glean data recording happens in a thread to avoid blocking the main thread.
Right now that thread is handled on the Kotlin side.
A panic in the Rust code base will bubble up the stack and crash the thread, thus poisoning the internal lock of the map,
but it will not abort the whole application by itself.
Subsequent calls will run on a new thread, handled by the Kotlin side.
When using a labeled counter again it will try to acquire the lock,
detect that it is poisoned and panic once more.
That panic is caught by the FFI layer of Glean and turned into a log message.&lt;/p&gt;
&lt;p&gt;Second the standalone Glean library is compiled with &lt;a href=&quot;https://doc.rust-lang.org/cargo/reference/profiles.html#panic&quot;&gt;&lt;code&gt;panic=unwind&lt;/code&gt;&lt;/a&gt;, the default in Rust,
which unwinds the stack on panics.
If not caught the runtime will abort the current thread, writing a panic message to the error output.
&lt;code&gt;ffi-support&lt;/code&gt; however catches it, logs it and returns without crashing or aborting.
Gecko on the other hand sets &lt;a href=&quot;https://searchfox.org/mozilla-central/rev/a9e0a3f5e5f7cde941d419db967997aaa1f06b0f/Cargo.toml#63&quot;&gt;&lt;code&gt;panic=abort&lt;/code&gt;&lt;/a&gt;.
In this mode a panic will immediately terminate the current process (after writing the crash message to the error output),
without ever trying to unwind the stack, giving no chance for the support library to catch it.
The Gecko crash reporter is able to catch those hard aborts and send them as crash reports.
As Glean is now part of the overall Gecko build all of Gecko&#39;s build flags will transitively apply to Glean and its dependencies, too.
So when Glean is shipped as part of GeckoView it runs in &lt;code&gt;panic=abort&lt;/code&gt; mode, leading to internal panics aborting the whole application.&lt;/p&gt;
&lt;p&gt;That behavior by itself is fine: Glean should only panic in exceptional cases and we&#39;d like to know about them.
It&#39;s good to know that an application could continue running without Glean working correctly;
we won&#39;t be able to record and send telemetry data, but at least we&#39;re not interrupting someone using the application.
However unless we engineers run into those bugs and see the log we will not notice them and thus can&#39;t fix them.
So ultimately this change in (crashing) behavior is acceptable (and wanted) going forward.&lt;/p&gt;
&lt;p&gt;After fixing the initial bug and being able to answer why it only started crashing recently my work was still not done.
We were likely not recording data in exceptional cases for quite some time, which is not acceptable for a telemetry library.
I had to explore our data, estimate how many metrics for how many clients were affected, inform relevant stakeholders and plan further mitigations.
But that part of the investigation is a story for another time.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This bug investigation had help from a lot of people.
Thanks to Mike Droettboom for coordination,
Marissa Gorlick for pushing me to evaluate the impact on data &amp;amp; reaching the right people,
Travis Long for help with the Glean code &amp;amp; speedy reviews,
Alessio Placitelli for reviews on the Gecko side,
Delia Pop for the initial steps to reproduce the bug
&amp;amp; Christian Sadilek for help on the Android Components &amp;amp; Fenix side.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Except that it panics at a slightly different place than the explicit check in the code base would suggest. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;That meant I could also &lt;em&gt;tune&lt;/em&gt; how quickly it crashed. A smaller maximum capacity means its reached more quickly, reducing my bug reproduction time significantly. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;#fr-2-2&quot; class=&quot;footnotes-backref&quot;&gt;↩2&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;No, not after 9 minutes, but in just under 3 minutes after tuning the maximum map capacity, see &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-2&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2021/11/01/crashes-and-a-buggy-glean</guid>
      <pubDate>Mon, 01 Nov 2021 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>Fenix Physical Device Testing</title>
      <link>https://fnordig.de/2021/10/14/fenix-physical-device-testing</link>
      <description>&lt;p&gt;The &lt;a href=&quot;https://github.com/mozilla-mobile/fenix&quot;&gt;Firefox for Android (Fenix)&lt;/a&gt; project runs extensive tests on every pull request and when merging code back into the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;
&lt;p&gt;While many tests run within an isolated Java environment, Fenix also contains a multitude of UI tests.
They allow testing the full application, interaction with the UI and other events.
Running these requires the Android emulator running or a physical Android device connected.
To run these tests in the CI environment the Fenix team relies on the &lt;a href=&quot;https://firebase.google.com/docs/test-lab/&quot;&gt;Firebase test lab&lt;/a&gt;,
a cloud-based testing service offering access to a range of physical and virtual devices to run Android applications on.&lt;/p&gt;
&lt;p&gt;To speed up development, the automatically scheduled tests associated with a  pull request are only run on virtual devices.
These are quick to spin up, there is basically no upper limit of devices that can spawn on the cloud infrastructure and they usually produce the same result as running the test on a physical device.&lt;/p&gt;
&lt;p&gt;But once in a while you encounter a bug that can only be reproduced reliably on a physical device.
If you don&#39;t have access to such a device, what do you do? Or you know the bug happens on that one specific device type you don’t have?&lt;/p&gt;
&lt;p&gt;You remember that the Firebase Test Lab offers physical devices as well and the Fenix repository is very well set up to run your test on these too if needed!&lt;/p&gt;
&lt;p&gt;Here&#39;s how you change the CI configuration to do this.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Do not land a Pull Request that switches CI from virtual to physical devices! Add the &lt;code&gt;pr:do-not-land&lt;/code&gt; label and call out that the PR is only there for testing!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By default the Fenix CI runs tests using virtual devices on &lt;code&gt;x86&lt;/code&gt;.
That&#39;s faster when the host is also a &lt;code&gt;x86(_64)&lt;/code&gt; system, but most physical devices use the Arm platform.
So first we need to instruct it to run tests on Arm.&lt;/p&gt;
&lt;p&gt;Which platform to test on is defined in &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/blob/58e12b18e6e9f4f67c059fe9c9bf9f02579a55db/taskcluster/ci/ui-test/kind.yml#L65&quot;&gt;&lt;code&gt;taskcluster/ci/ui-test/kind.yml&lt;/code&gt;&lt;/a&gt;.
Find the line where it downloads the &lt;code&gt;target.apk&lt;/code&gt; produced in a previous step and change it from &lt;code&gt;x86&lt;/code&gt; to &lt;code&gt;arm64-v8a&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  run:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      commands:
&lt;/span&gt;&lt;span style=&quot;background-color:#ffecec;color:#323232;&quot;&gt;-         - [wget, {artifact-reference: &amp;#39;&amp;lt;signing/public/build/x86/target.apk&amp;gt;&amp;#39;}, &amp;#39;-O&amp;#39;, app.apk]
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;         - [wget, {artifact-reference: &amp;#39;&amp;lt;signing/public/build/arm64-v8a/target.apk&amp;gt;&amp;#39;}, &amp;#39;-O&amp;#39;, app.apk]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then look for the line where it invokes the &lt;code&gt;ui-test.sh&lt;/code&gt; and tell it to use &lt;code&gt;arm64-v8a&lt;/code&gt; again:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  run:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      commands:
&lt;/span&gt;&lt;span style=&quot;background-color:#ffecec;color:#323232;&quot;&gt;-         - [automation/taskcluster/androidTest/ui-test.sh, x86, app.apk, android-test.apk, &amp;#39;-1&amp;#39;]
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;         - [automation/taskcluster/androidTest/ui-test.sh, arm64-v8a, app.apk, android-test.apk, &amp;#39;-1&amp;#39;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the old CI configuration it will look for Firebase parameters in &lt;code&gt;automation/taskcluster/androidTest/flank-x86.yml&lt;/code&gt;.
Now that we switched the architecture it will pick up &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/blob/58e12b18e6e9f4f67c059fe9c9bf9f02579a55db/automation/taskcluster/androidTest/flank-arm64-v8a.yml&quot;&gt;&lt;code&gt;automation/taskcluster/androidTest/flank-arm64-v8a.yml&lt;/code&gt;&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;In that file we can now pick the device we want to run on:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   device:
&lt;/span&gt;&lt;span style=&quot;background-color:#ffecec;color:#323232;&quot;&gt;-   - model: Pixel2
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;   - model: dreamlte
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      version: 28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can get a &lt;a href=&quot;https://firebase.google.com/docs/test-lab/android/available-testing-devices&quot;&gt;list of available devices&lt;/a&gt; by running &lt;code&gt;gcloud&lt;/code&gt; locally:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;gcloud firebase test android models list
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The value from the &lt;code&gt;MODEL_ID&lt;/code&gt; column is what you use for the &lt;code&gt;model&lt;/code&gt; parameter in &lt;code&gt;flank-arm64-v8a.yml&lt;/code&gt;.
&lt;code&gt;dreamlte&lt;/code&gt; translates to a Samsung Galaxy S8, which is available on Android API version 28.&lt;/p&gt;
&lt;p&gt;If you only want to run a subset of tests define the &lt;code&gt;test-targets&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;test-targets&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;class org.mozilla.fenix.glean.BaselinePingTest
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Specify an exact test class as above to run tests from just that class.&lt;/p&gt;
&lt;p&gt;And that&#39;s all the configuration necessary.
Save your changes, commit them, then push up your code and create a pull request.
Once the decision task on your PR finishes you will find a &lt;code&gt;ui-test-x86-debug&lt;/code&gt; job (yes, &lt;code&gt;x86&lt;/code&gt;, we didn&#39;t rename the job).
Its log file will have details on the test run and contain links to the test run summary.
Follow them to get more details, including the logcat output and a video of the test run.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;This explanation will eventually move into documentation for Mozilla&#39;s Android projects.&lt;br /&gt;
Thanks to Richard Pappalardo &amp;amp; Aaron Train for the help figuring out how to run tests on physical devices and early feedback on the post.
Thanks to &lt;a href=&quot;https://wrla.ch/&quot;&gt;Will Lachance&lt;/a&gt; for feedback and corrections. Any further errors are mine alone.&lt;/em&gt;&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2021/10/14/fenix-physical-device-testing</guid>
      <pubDate>Thu, 14 Oct 2021 17:00:00 +0200</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Glean &amp; GeckoView</title>
      <link>https://fnordig.de/2021/09/17/glean-geckoview</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2021/09/17/this-week-in-glean-glean-geckoview/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;This is a followup post to &lt;a href=&quot;/2021/07/26/shipping-glean-with-geckoview/&quot;&gt;Shipping Glean with GeckoView&lt;/a&gt;.&lt;/p&gt;
&lt;center&gt;
&lt;h2&gt;It landed!&lt;/h2&gt;
&lt;/center&gt;
&lt;p&gt;It took us several more weeks to put everything into place, but we&#39;re finally shipping the Rust parts of the Glean Android SDK with GeckoView
and consume that in &lt;a href=&quot;https://github.com/mozilla-mobile/android-components/pull/10828&quot;&gt;Android Components&lt;/a&gt; and &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/pull/20889&quot;&gt;Fenix&lt;/a&gt;.
And it still all works, collects data and is sending pings!
Additionally this results in a slightly smaller APK as well.&lt;/p&gt;
&lt;p&gt;This unblocks further work now.
Currently Gecko simply stubs out all calls to Glean when compiled for Android,
but we will enable recording Glean metrics within Gecko and exposing them in pings sent from Fenix.
We will also start work on moving other Rust components into mozilla-central in order for them to use the Rust API of Glean directly.
Changing how we deliver the Rust code also made testing Glean changes across these different components a bit more challenging,
so I want to invest some time to make that easier again.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2021/09/17/glean-geckoview</guid>
      <pubDate>Fri, 17 Sep 2021 13:00:00 +0200</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Shipping Glean with GeckoView</title>
      <link>https://fnordig.de/2021/07/26/shipping-glean-with-geckoview</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2021/07/26/this-week-in-glean-shipping-glean-with-geckoview&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Glean SDK&lt;/h2&gt;
&lt;p&gt;The Glean SDK is Mozilla&#39;s telemetry library, used in most mobile products and now for Firefox Desktop as well.
By now it has grown to a sizable code base with a lot of functionality beyond just storing some metric data.
Since its first release as a Rust crate in 2019 we managed to move more and more logic from the language SDKs
(previously also known as &quot;language bindings&quot;) into the core Rust crate.
This allows us to maintain business logic only once and can easily share that across different implementations and platforms.
The Rust core is shipped precompiled for multiple target platforms, with the language SDK distributed through the respective package manager.&lt;/p&gt;
&lt;p&gt;I talked about how this all works in more detail
&lt;a href=&quot;https://www.youtube.com/watch?v=j5rczOF7pzg&quot;&gt;last year&lt;/a&gt;,
&lt;a href=&quot;https://www.youtube.com/watch?v=j5rczOF7pzg&quot;&gt;this year&lt;/a&gt;
and blogged about it &lt;a href=&quot;/2020/09/01/leveraging-rust-to-build-cross-platform-mobile-libraries/&quot;&gt;in a previous TWiG&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;GeckoView&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://mozilla.github.io/geckoview/&quot;&gt;GeckoView&lt;/a&gt; is Mozilla&#39;s alternative implementation for WebViews on Android, based on Gecko, the web engine that also powers Firefox Desktop.
It is used as the engine behind &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/&quot;&gt;Firefox for Android&lt;/a&gt; (also called Fenix).
The visible parts of what makes up Firefox for Android is written in Kotlin, but it all delegates to the underlying Gecko engine,
written in a combination of C++, Rust &amp;amp; JavaScript.&lt;/p&gt;
&lt;p&gt;The GeckoView code resides in the mozilla-central repository, next to all the other Gecko code.
From there releases are pushed to Mozilla&#39;s own &lt;a href=&quot;https://maven.mozilla.org/maven2/&quot;&gt;Maven repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;One Glean too many&lt;/h2&gt;
&lt;p&gt;Initially Firefox for Android was the only user of the Glean SDK.
Up until today it consumes Glean through its release as part of &lt;a href=&quot;https://github.com/mozilla-mobile/android-components/&quot;&gt;Android Components&lt;/a&gt;, a collection of libraries to build browser-like applications.&lt;/p&gt;
&lt;p&gt;But the Glean SDK is also available outside of Android Components, as its own package.
And additionally it&#39;s available for other languages and platforms too, including a &lt;a href=&quot;https://crates.io/crates/glean&quot;&gt;Rust crate&lt;/a&gt;.
&lt;a href=&quot;https://blog.mozilla.org/data/2020/10/06/this-week-in-glean-fog-progress-report/&quot;&gt;Over the past year we&#39;ve been busy&lt;/a&gt; getting Gecko to use Glean through the Rust crate to build its own telemetry on top.&lt;/p&gt;
&lt;p&gt;With the Glean SDK used in all these applications we&#39;re in a difficult position:
There&#39;s a Glean in Firefox for Android that&#39;s reporting data.
Firefox for Android is using Gecko to render the web.
And Gecko is starting to use Glean to report data.&lt;/p&gt;
&lt;p&gt;That&#39;s one Glean too many if we want coherent data from the full application.&lt;/p&gt;
&lt;h2&gt;Shipping it all together, take one&lt;/h2&gt;
&lt;p&gt;Of course we knew about this scenario for a long time.
It&#39;s been one of the goals of Project FOG to transparently collect data from Gecko and the embedding application!&lt;/p&gt;
&lt;p&gt;We set out to find a solution so that we can connect both sides and have only one Glean be responsible for the data collection &amp;amp; sending.&lt;/p&gt;
&lt;p&gt;We started with more detailed planning all the way back in August of last year
and agreed on a design in October.
Due to changed priorities &amp;amp; availability of people we didn&#39;t get into the implementation phase until earlier this year.&lt;/p&gt;
&lt;p&gt;By February I had a first rough prototype in place.
When Gecko was shipped as part of GeckoView it would automatically look up the Glean library that is shipped as a dynamic library with the Android application.
All function calls to record data from within Gecko would thus ultimately land in the Glean instance that is controlled by Fenix.
Glean and the abstraction layer within Gecko would do the heavy work, but users of the Glean API would notice no difference,
except their data would now show up in pings sent from Fenix.&lt;/p&gt;
&lt;p&gt;This integration was brittle.
It required finding the right dynamic library, looking up symbols at runtime as well as reimplementing all metric types to switch to the FFI API in a GeckoView build.
We abandoned this approach and started looking for a better one.&lt;/p&gt;
&lt;h2&gt;Shipping it all together, take two&lt;/h2&gt;
&lt;p&gt;After the first failed approach the issue was acknowledged by other teams, including the GeckoView and Android teams.&lt;/p&gt;
&lt;p&gt;Glean is not the only Rust project shipped for mobile,
the &lt;a href=&quot;https://github.com/mozilla/application-services&quot;&gt;application-services team&lt;/a&gt; is also shipping components written in Rust.
They bundle all components into a single library, dubbed the &lt;a href=&quot;https://github.com/mozilla/application-services/blob/main/docs/design/megazords.md&quot;&gt;megazord&lt;/a&gt;.
This reduces its size (dependencies &amp;amp; the Rust standard library are only linked once) and simplifies shipping, because there&#39;s only one library to ship.
We always talked about pulling in Glean as well into such a megazord, but ultimately didn&#39;t do it (except for &lt;a href=&quot;https://github.com/mozilla/application-services/tree/main/megazords/ios&quot;&gt;iOS builds&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;With that in mind we decided it&#39;s now the time to design a solution, so that eventually we can bundle multiple Rust components in a single build.
We came up with the following plan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Glean Kotlin SDK will be split into 2 packages: a &lt;code&gt;glean-native&lt;/code&gt; package, that only exists to ship the compiled Rust library, and a &lt;code&gt;glean&lt;/code&gt; package,
that contains the Kotlin code and has a dependency on &lt;code&gt;glean-native&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The GeckoView-provided &lt;code&gt;libxul&lt;/code&gt; library (that&#39;s &quot;Gecko&quot;) will bundle the Glean Rust library and export the C-compatible FFI symbols,
that are used by the Glean Kotlin SDK to call into Glean core.&lt;/li&gt;
&lt;li&gt;The GeckoView Kotlin package will then use Gradle capabilities to replace the &lt;code&gt;glean-native&lt;/code&gt; package with itself (this is actually handle by the Glean Gradle plugin).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Consumers such as Fenix will depend on both GeckoView and Glean.
At build time the Glean Gradle plugin will detect this and will ensure the &lt;code&gt;glean-native&lt;/code&gt; package, and thus the Glean library, is not part of the build.
Instead it assumes &lt;code&gt;libxul&lt;/code&gt; from GeckoView will take that role.&lt;/p&gt;
&lt;p&gt;This has some advantages.
First off everything is compiled together into one big library.
Rust code gets linked together and even Rust consumers within Gecko can directly use the Glean Rust API.
Next up we can ensure that the version of the Glean core library matches the Glean Kotlin package used by the final application.
It is important that the code matches, otherwise calling native functions could lead to memory or safety issues.&lt;/p&gt;
&lt;p&gt;Glean is running ahead here, paving the way for more components to be shipped the same way.
Eventually the experimentation SDK called Nimbus and other application-services components will start using the Rust API of Glean.
This will require compiling Glean alongside them and that&#39;s the exact case that is handled in mozilla-central for GeckoView then.&lt;/p&gt;
&lt;p&gt;Now the unfortunate truth is: these changes have not landed yet.
It&#39;s been implemented for both the Glean SDK and mozilla-central,
but also requires changes for the build system of mozilla-central.
Initially that looked like simple changes to adopt the new bundling,
but it turned into bigger changes across the board.
Some of the infrastructure used to build and test Android code from mozilla-central was untouched for years and thus is very outdated
and not easy to change.
With everything else going on for Firefox it&#39;s been a slow process to update the infrastructure, prepare the remaining changes and finally getting this landed.&lt;/p&gt;
&lt;p&gt;But we&#39;re close now!&lt;/p&gt;
&lt;p&gt;Big thanks to &lt;a href=&quot;https://github.com/agi/&quot;&gt;Agi&lt;/a&gt; for connecting the right people, driving the initial design and helping me with the GeckoView changes.
He also took on the challenge of changing the build system.
And also thanks to &lt;a href=&quot;https://github.com/chutten&quot;&gt;chutten&lt;/a&gt; for his reviews and input. He&#39;s driving the FOG work forward and thus really really needs us to ship GeckoView support.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2021/07/26/shipping-glean-with-geckoview</guid>
      <pubDate>Mon, 26 Jul 2021 12:00:00 +0200</pubDate>
    </item>
    <item>
      <title>This Week in Glean: rustc, iOS and an M1</title>
      <link>https://fnordig.de/2021/04/16/rustc-ios-and-an-m1</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2021/04/16/this-week-in-glean-rustc-ios-and-an-m1/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Back in February I got an M1 MacBook.
That&#39;s Apple&#39;s new ARM-based hardware.&lt;/p&gt;
&lt;p&gt;I got it with the explicit task to ensure that we are able to develop and build &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;Glean&lt;/a&gt; on it.
We maintain a &lt;a href=&quot;https://github.com/mozilla/glean/tree/main/glean-core/ios&quot;&gt;Swift language binding&lt;/a&gt;, targeting iOS, and that one is used in &lt;a href=&quot;https://github.com/mozilla-mobile/firefox-ios&quot;&gt;Firefox iOS&lt;/a&gt;.
Eventually these iOS developers will also have M1-based machines and want to test their code, thus Glean needs to work.&lt;/p&gt;
&lt;p&gt;Here&#39;s what we need to get to work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Compile the Rust portions of Glean natively on an M1 machine&lt;/li&gt;
&lt;li&gt;Build &amp;amp; test the Kotlin &amp;amp; Swift language bindings on an M1 machine, even if non-native (e.g. Rosetta 2 emulation for x86_64)&lt;/li&gt;
&lt;li&gt;Build &amp;amp; test the Swift language bindings natively and in the iPhone simulator on an M1 machine&lt;/li&gt;
&lt;li&gt;Stretch goal: Get iOS projects using Glean running as well&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Rust on an M1&lt;/h2&gt;
&lt;p&gt;Work on getting Rust compiled on M1 hardware started last year in June already, with the availability of the first developer kits.
See &lt;a href=&quot;https://github.com/rust-lang/rust/issues/73908&quot;&gt;Rust issue 73908&lt;/a&gt; for all the work and details.
First and foremost this required a new target: &lt;code&gt;aarch64-apple-darwin&lt;/code&gt;.
This landed in August and was promoted to Tier 2&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; with the &lt;a href=&quot;https://blog.rust-lang.org/2020/12/31/Rust-1.49.0.html#64-bit-arm-macos-and-windows-reach-tier-2&quot;&gt;December release of Rust 1.49.0&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By the time I got my MacBook compiling Rust code on it was as easy as on an Intel MacBook.
Developers on Intel MacBooks can cross-compile just as easily:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;rustup target add aarch64-apple-darwin
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo build --target aarch64-apple-darwin
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Glean Python &amp;amp; Kotlin on an M1&lt;/h2&gt;
&lt;p&gt;Glean Python just ... worked.
We use &lt;code&gt;cffi&lt;/code&gt; to load the native library into Python.
It gained &lt;code&gt;aarch64&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; macOS support in &lt;a href=&quot;https://cffi.readthedocs.io/en/latest/whatsnew.html#v1-14-1&quot;&gt;v14.4.1&lt;/a&gt;.
My colleague glandium later &lt;a href=&quot;https://github.com/mozilla/glean/pull/1534&quot;&gt;contributed support code&lt;/a&gt; so we build release wheels for that target too.
So it&#39;s both possible to develop &amp;amp; test Glean Python, as well as use it as a dependency without having a full Rust development environment around.&lt;/p&gt;
&lt;p&gt;Glean Android is not that straight forward.
Some of our transitive dependencies are based on years-old pre-built binaries of SQLite
and of course there&#39;s not much support behind updating those Java libraries.
It&#39;s possible. A friend managed to compile and run that library on an M1.
But for Glean development we simply recommend relying on Rosetta 2 (the x86_64 compatibility layer) for now.
It&#39;s as easy as:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;arch -x86_64 $SHELL
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;make build-kotlin
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At least if you have Java set up correctly...
The default Android emulator isn&#39;t usable on M1 hardware yet, but Google is working on a compatible one: &lt;a href=&quot;https://github.com/google/android-emulator-m1-preview&quot;&gt;Android M1 emulator preview&lt;/a&gt;.
It&#39;s usable enough for some testing, but for that part I most often switch back to my Linux Desktop (that has the additional CPU power on top).&lt;/p&gt;
&lt;h2&gt;Glean iOS on an M1&lt;/h2&gt;
&lt;p&gt;Now we&#39;re getting to the interesting part: Native iOS development on an M1.
Obviously for Apple this is a priority:
Their new machines should become the main machine people do iOS development on.
Thus Xcode gained &lt;code&gt;aarch64&lt;/code&gt; support in version 12 long before the hardware was available.
That caused quite some issues with existing tooling, such as the &lt;a href=&quot;https://github.com/Carthage/Carthage/issues/3019&quot;&gt;dependency manager Carthage&lt;/a&gt;.
Here&#39;s the issue:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When compiling for iOS hardware you would pick a target named &lt;code&gt;aarch64-apple-ios&lt;/code&gt;,
because ... iPhones and iPads are ARM-based since forever.&lt;/li&gt;
&lt;li&gt;When compiling for the iOS simulator you would pick a target named &lt;code&gt;x86_64-apple-ios&lt;/code&gt;,
because conveniently the simulator uses the host&#39;s CPU (that&#39;s what makes it fast)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So when the compiler saw &lt;code&gt;x86_64&lt;/code&gt; and &lt;code&gt;iOS&lt;/code&gt; it knew &quot;Ah, simulator target&quot;
and when it saw &lt;code&gt;aarch64&lt;/code&gt; and &lt;code&gt;ios&lt;/code&gt; it knew &quot;Ah, hardware&quot;.
And everyone went with this, Xcode happily built both targets and, if asked to, was able to bundle them into one package.&lt;/p&gt;
&lt;p&gt;With the introduction of Apple Silicion&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;
the iOS simulator run on these machines would &lt;em&gt;also&lt;/em&gt; be &lt;code&gt;aarch64&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;,
and also contain &lt;code&gt;ios&lt;/code&gt;, but not be for the iOS hardware.&lt;/p&gt;
&lt;p&gt;Now Xcode and the compiler will get confused what to put where when building on M1 hardware for both iOS hardware and the host architecture.&lt;/p&gt;
&lt;p&gt;So the compiler toolchain gained knowledge of a new thing: &lt;code&gt;arm64-apple-ios14.0-simulator&lt;/code&gt;,
explicitly marking the simulator target.
The compiler knows from where to pick the libraries and other SDK files when using that target.
You still can&#39;t put code compiled for &lt;code&gt;arm64-apple-ios&lt;/code&gt; and &lt;code&gt;arm64-apple-ios14.0-simulator&lt;/code&gt; into the same universal binary&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;,
because you can have each architecture only once (the &lt;code&gt;arm64&lt;/code&gt; part in there).
That&#39;s what Carthage and others stumbled over.&lt;/p&gt;
&lt;p&gt;Again Apple prepared for that and for a long time they have wanted you to use &lt;a href=&quot;https://developer.apple.com/documentation/swift_packages/distributing_binary_frameworks_as_swift_packages&quot;&gt;XCFramework bundles&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.
Carthage just didn&#39;t used to support that.
The &lt;a href=&quot;https://github.com/Carthage/Carthage/releases/tag/0.37.0&quot;&gt;0.37.0 release&lt;/a&gt; fixed that.&lt;/p&gt;
&lt;p&gt;That still leaves Rust behind, as it doesn&#39;t know the new &lt;code&gt;-simulator&lt;/code&gt; target.
But as always the Rust community is ahead of the game and &lt;a href=&quot;https://github.com/deg4uss3r&quot;&gt;deg4uss3r&lt;/a&gt; started adding a new target in &lt;a href=&quot;https://github.com/rust-lang/rust/pull/81966/&quot;&gt;Rust PR #81966&lt;/a&gt;.
He got half way there when I jumped in to push it over the finish line.
How these targets work and how LLVM picks the right things to put into the compiled artifacts is severly underdocumented,
so I had to go the trial-and-error route in combination with looking at LLVM source code to find the missing pieces.
Turns out: the &lt;code&gt;14.0&lt;/code&gt; in &lt;code&gt;arm64-apple-ios14.0-simulator&lt;/code&gt; is actually important.&lt;/p&gt;
&lt;p&gt;With the last missing piece in place, the new Rust target landed in February and is available in Nightly.
Contrary to the main &lt;code&gt;aarch64-apple-darwin&lt;/code&gt; or &lt;code&gt;aarch64-apple-ios&lt;/code&gt; target, the simulator target is not Tier 2 yet
and thus no prebuilt support is available.
&lt;code&gt;rustup target add aarch64-apple-darwin&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; work right now.
I am now in discussions to &lt;a href=&quot;https://github.com/rust-lang/rust/issues/82412&quot;&gt;promote it to Tier 2&lt;/a&gt;,
but it&#39;s currently blocked by the &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2803&quot;&gt;RFC: Target Tier Policy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It works on nightly however and in combination with another &lt;a href=&quot;https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std&quot;&gt;cargo capability&lt;/a&gt; I&#39;m able to build libraries for the M1 iOS simulator:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo +nightly build -Z build-std --target aarch64-apple-ios-sim
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For now Glean iOS development on an M1 is possible, but &lt;a href=&quot;https://github.com/mozilla/glean/pull/1498&quot;&gt;requires Nightly&lt;/a&gt;.
Goal achieved, I can actually work with this!&lt;/p&gt;
&lt;p&gt;In a future blog post I want to explain in more detail how to teach Xcode about all the different targets it should build native code for.&lt;/p&gt;
&lt;h2&gt;All The Other Projects&lt;/h2&gt;
&lt;p&gt;This was marked a stretch goal for a reason.
This involves all the other teams with Rust code and the iOS teams too.
We&#39;re not there yet and there&#39;s currently no explicit priority to make development of Firefox iOS on M1 hardware possible.
But when it comes to it, Glean will be ready for it and the team can assist others to get it over the finish line.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Want to hear more about Glean and our cross-platform Rust development?
Come to next week&#39;s &lt;a href=&quot;https://www.meetup.com/Rust-Linz/events/276521001/&quot;&gt;Rust Linz meetup&lt;/a&gt;, where I will be talking about this.&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://doc.rust-lang.org/nightly/rustc/platform-support.html&quot;&gt;Platform Support&lt;/a&gt; for what the Tiers means. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;The other name for that target. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;&quot;Apple Silicon&quot; is yet another name for what is essentially the same as &quot;M1&quot; or &quot;macOS aarch64&quot; &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;Or &lt;code&gt;arm64&lt;/code&gt; for that matter. Yes, yet another name for the same thing. &lt;a href=&quot;#fr-4-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary&quot;&gt;&quot;Universal Binaries&quot;&lt;/a&gt; have existed for a long time now and allow for one binary to include the compiled artifacts for multiple targets. It&#39;s how there&#39;s only one Firefox for Mac download which runs natively on either Mac platform. &lt;a href=&quot;#fr-5-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;Yup, the main documentation they link to is a &lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2019/416/&quot;&gt;WWDC 2019 talk recording video&lt;/a&gt;. &lt;a href=&quot;#fr-6-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2021/04/16/rustc-ios-and-an-m1</guid>
      <pubDate>Fri, 16 Apr 2021 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>Three-year Moziversary</title>
      <link>https://fnordig.de/2021/03/01/three-year-moziversary</link>
      <description>&lt;p&gt;Has it really been 3 years?
I guess it has.
I joined Mozilla as a Firefox Telemetry Engineer in &lt;a href=&quot;https://fnordig.de/2018/02/18/a-new-job/&quot;&gt;March 2018&lt;/a&gt;, I blogged twice already: &lt;a href=&quot;https://fnordig.de/2019/03/01/one-year-moziversary/&quot;&gt;2019&lt;/a&gt;, &lt;a href=&quot;https://fnordig.de/2020/03/02/two-year-moziversary/&quot;&gt;2020&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And now it&#39;s 2021. 2020 was nothing like I thought it would and still been a lot like I said last year at this point.
It&#39;s been Glean all over the year, but instead of working from the office and occasionally meeting my team in person, it&#39;s been working from home for 12 months now.&lt;/p&gt;
&lt;p&gt;In September of last year I officially became the Glean SDK tech lead and thus I&#39;m now responsible for the technical direction and organisation of the whole project,
but really this is a team effort.
Throughout the year we made &lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/glean/index.html&quot;&gt;Project FOG&lt;/a&gt; happen. At least the code is there and we can start migrating now. It&#39;s far from finished of course.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://fnordig.de/2020/12/18/glean-in-2021/&quot;&gt;I blogged about Glean in 2021&lt;/a&gt; and we&#39;re already seeing the first pieces of that plan being implemented.
After some reorganization the team I&#39;m in grew again so now we have &lt;a href=&quot;http://www.relud.com/&quot;&gt;Daniel&lt;/a&gt;, &lt;a href=&quot;https://acmiyaguchi.me/&quot;&gt;Anthony&lt;/a&gt; and &lt;a href=&quot;https://github.com/fbertsch&quot;&gt;Frank&lt;/a&gt; there as well (we&#39;re still Team &quot;Browser Measurement III&quot;).
This brings two parts of the Glean project closer together (not that it was far apart).&lt;/p&gt;
&lt;p&gt;There&#39;s more work ahead, interesting challenges to tackle and projects to support in migrating to Glean.
To the next year and beyond!&lt;/p&gt;
&lt;h2&gt;Thank you&lt;/h2&gt;
&lt;p&gt;Thanks to my team: &lt;a href=&quot;https://brizental.github.io/&quot;&gt;Bea&lt;/a&gt;, &lt;a href=&quot;https://chuttenblog.wordpress.com/&quot;&gt;Chris&lt;/a&gt;, &lt;a href=&quot;https://blogoftravis.wordpress.com/&quot;&gt;Travis&lt;/a&gt;, &lt;a href=&quot;https://www.a2p.it/wordpress/&quot;&gt;Alessio&lt;/a&gt;, &lt;a href=&quot;http://droettboom.com/&quot;&gt;Mike&lt;/a&gt;, &lt;a href=&quot;http://www.relud.com/&quot;&gt;Daniel&lt;/a&gt;, &lt;a href=&quot;https://acmiyaguchi.me/&quot;&gt;Anthony&lt;/a&gt; and &lt;a href=&quot;https://github.com/fbertsch&quot;&gt;Frank&lt;/a&gt;
and also thanks to the bigger data engineering team within Mozilla.
And thanks to all the other people at Mozilla I work with.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2021/03/01/three-year-moziversary</guid>
      <pubDate>Mon, 01 Mar 2021 11:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Boring Monitoring</title>
      <link>https://fnordig.de/2021/02/24/boring-monitoring</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2021/02/24/this-week-in-glean-boring-monitoring/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Every Monday the Glean has its weekly Glean SDK meeting.
This meeting is used for 2 main parts:
First discussing the features and bugs the team is currently investigating or that were requested by outside stakeholders.
And second bug triage &amp;amp; monitoring of data that Glean reports in the wild.&lt;/p&gt;
&lt;p&gt;Most of the time looking at our monitoring is boring and that&#39;s a good thing.&lt;/p&gt;
&lt;p&gt;From the beginning the Glean SDK supported extensive &lt;a href=&quot;https://mozilla.github.io/glean/book/user/error-reporting.html&quot;&gt;error reporting&lt;/a&gt; on data collected by the framework inside end-user applications.
Errors are produced when the application tries to record invalid values.
That could be a negative value for a counter that should only ever go up or stopping a timer that was never started.
Sometimes this comes down to a simple bug in the code logic and should be fixed in the implementation.
But often this is due to unexpected and surprising behavior of the application the developers definitely didn&#39;t think about.
Do you know all the ways that your Android application can be started?
There&#39;s a whole lot of events that can launch it, even in the background, and you might miss instrumenting all the right parts sometimes.
Of course this should then also be fixed in the implementation.&lt;/p&gt;
&lt;h2&gt;Monitoring Firefox for Android&lt;/h2&gt;
&lt;p&gt;For our weekly monitoring we look at one application in particular: &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/&quot;&gt;Firefox for Android&lt;/a&gt;.
Because errors are reported in the same way as other metrics we are able to query our database, aggregate the data by specific metrics and errors, generate graphs from it
and create dashboards on our instance of &lt;a href=&quot;https://redash.io/&quot;&gt;Redash&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2021/fenix-error-monitoring.png&quot; alt=&quot;Graph of the error counts for different metrics in Firefox for Android&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The above graph displays error counts for different metrics. Each line is a specific metric and error (such as &lt;code&gt;Invalid Value&lt;/code&gt; or &lt;code&gt;Invalid State&lt;/code&gt;).
The exact numbers are not important.
What we&#39;re interested in is the general trend.
Are the errors per metrics stable or are there sudden jumps?
Upward jumps indicate a problem, downward jumps probably means the underlying bug got fixed and is finally rolled out in an update to users.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2021/fenix-error-monitoring2.png&quot; alt=&quot;Rate of affected clients in Firefox for Android&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We have another graph that doesn&#39;t take the raw number of errors, but averages it across the entire population.
A sharp increase in error counts sometimes comes from a small number of clients, whereas the errors for others stay at the same low-level.
That&#39;s still a concern for us, but knowing that a potential bug is limited to a small number of clients may help with finding and fixing it.
And sometimes it&#39;s really just bogus client data we get and can dismiss fully.&lt;/p&gt;
&lt;p&gt;Most of the time these graphs stay rather flat and boring and we can quickly continue with other work.
Sometimes though we can catch potential issues in the first days after a rollout.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2021/fenix-error-monitoring3.png&quot; alt=&quot;Sudden jump upwards in errors for 2 metrics in Firefox for Android Nightly&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In this graph from the nightly release of Firefox for Android two metrics started reporting a number of errors that&#39;s far above any other error we see.
We can then quickly find the implementation of these metrics and report that to the responsible team (&lt;a href=&quot;https://github.com/mozilla-mobile/fenix/issues/18114&quot;&gt;Filed bug&lt;/a&gt;, and the &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/pull/18115&quot;&gt;remediation PR&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;But can&#39;t that be automated?&lt;/h2&gt;
&lt;p&gt;It probably can!
But it requires more work than throwing together a dashboard with graphs.
It&#39;s also not as easy to define thresholds on these changes and when to report them.
There&#39;s work underway that hopefully enables us to more quickly build up these dashboards for any product using the Glean SDK,
which we can then also extend to do more reporting automated.
The final goal should be that the product teams themselves are responsible for monitoring their data.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2021/02/24/boring-monitoring</guid>
      <pubDate>Wed, 24 Feb 2021 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Glean in 2021</title>
      <link>https://fnordig.de/2020/12/18/glean-in-2021</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2020/12/18/this-week-in-glean-glean-in-2021/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;A year ago the Glean project was different.
We had just released &lt;a href=&quot;https://github.com/mozilla/glean/releases/tag/v22.1.0&quot;&gt;Glean v22.1.0&lt;/a&gt;
and &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/&quot;&gt;Fenix&lt;/a&gt; (aka Firefox for Android aka Firefox Daylight) was not released yet,
Project FOG was &lt;a href=&quot;https://chuttenblog.wordpress.com/2019/10/17/this-week-in-glean-glean-on-desktop-project-fog/&quot;&gt;just an idea&lt;/a&gt; for the year to come.&lt;/p&gt;
&lt;p&gt;2020 changed that, but 2020 changed a lot.
What didn&#39;t change was my main assignment: I kept working all throughout the year on the Glean SDK, fixing bugs, expanding its capabilities,
enabling more platforms and integrating it into more products.
Of course this was only possible because the whole team did that as well.&lt;/p&gt;
&lt;p&gt;In September I took over the tech lead role for the SDK from &lt;a href=&quot;https://twitter.com/dexterp37/&quot;&gt;Alessio&lt;/a&gt;.
One part of this role includes thinking bigger and sketching out the future for the Glean SDK.&lt;/p&gt;
&lt;p&gt;Let&#39;s look at this future and what ideas we have for 2021.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(One note: right now these are ideas more than a plan. It neither includes a timeline nor does it include all the other things maintenance includes.)&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;The vision&lt;/h2&gt;
&lt;p&gt;The Glean SDK is a fully self-servable telemetry SDK, usable across different platforms.
It enables product owners and engineers to instrument their products and rely on their data collection, while following Mozilla policies &amp;amp; privacy standards.&lt;/p&gt;
&lt;h2&gt;The ideas&lt;/h2&gt;
&lt;p&gt;In the past weeks I started a list of things I want the Glean SDK to do next.
This is a short and incomplete list of not-yet-proposed or accepted ideas.
For 2021 we will need to fit this in with the larger Glean project, including plans and ideas for the pipeline and tooling.
Oh, and I need to talk with my team to actually decide on the plan and allocate who does what when.&lt;/p&gt;
&lt;h3&gt;Metric types&lt;/h3&gt;
&lt;p&gt;When we set out to revamp our telemetry system we build it with the idea of offering higher-level metric types,
that give more meaning to individual data points, allowing more correct data collection and better aggregation, analysis and visualisation of this data.
We&#39;re not there yet.
We currently support &lt;a href=&quot;https://mozilla.github.io/glean/book/user/metrics/index.html&quot;&gt;more than a dozen metric types&lt;/a&gt; across all platforms equally,
with the same user-friendly APIs in all supported languages.
We also know that this still does not cover all intended use cases that, for example, Firefox Desktop wants.
In 2021 we will probably need to work on a few more types, better ergonomics and especially documentation on when which metric type is appropriate.&lt;/p&gt;
&lt;h3&gt;Revamped testing APIs&lt;/h3&gt;
&lt;p&gt;Engineers should instrument their code where appropriate and use the collected data to analysis behavior and performance in the wild.
The Glean SDK ensures their data is reliably collected and sent to our pipeline.
But we cannot ensure that the way the data is collected is correct or whether the metric even makes sense.
That&#39;s why we encourage that each metric recording is accompanied by tests to ensure data is collected under the right circumstances and that its the right data under the given test case.
Only that way folks will be able to verify and analyse the incoming data later and rely on their results.&lt;/p&gt;
&lt;p&gt;The available testing APIs in the Glean SDK provide a bare minimum.
For each metric type one can check which data it currently holds.
That&#39;s probably easy to validate for simpler metrics such as strings, booleans and counters,
but as soon as you have more complex one like any of the distributions or a timespan it gets a bit more complex.
Additionally we offer a way to check if any errors occured during recording, which are usually also reported in the data.
But here again developers need to know which errors can happen under what circumstances for which metric type.&lt;/p&gt;
&lt;p&gt;And at last we want developers to reach for &lt;a href=&quot;https://mozilla.github.io/glean/book/user/pings/custom.html&quot;&gt;custom pings&lt;/a&gt; when the default pings are not sufficient.
Testing these is currently near impossible.&lt;/p&gt;
&lt;p&gt;Testing these different usages of the SDK can and should be improved.
We already have the first proposals and bugs for this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/18JSwvz2HFDHfVB3MrJh_ON3gnMfTF-nHFxaBzXqPR_I/&quot;&gt;Custom Ping Unit Tests&lt;/a&gt; proposes a simple callback-like API to validate data in custom pings&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/1RrN3JoXVLMV5wwS56WXMqT35DhNfFkf5taRvU0WJlUA/&quot;&gt;Testing parameter in Glean metric definitions&lt;/a&gt; proposes to make existing tests/testing documentation for metrics more visible&lt;/li&gt;
&lt;li&gt;Improvements to Glinter, the Glean linter (e.g. &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1682980&quot;&gt;opinions on naming of things&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(Note: as of writing these document might be inaccessible to the wider public, but they will be made public once we gather wider feedback)&lt;/p&gt;
&lt;p&gt;For sure we will have more ideas on this in 2021.&lt;/p&gt;
&lt;h3&gt;UniFFI - generate all the code&lt;/h3&gt;
&lt;p&gt;The Glean SDK is cross-platform by shipping a core library written in Rust with language bindings on top that connect it with the target platform.
This has the advantage that most of the logic is written once and works across all the targets we have.
But this also has the downside that each language binding sort of duplicates the user-visible API in their target language again.
Currently all metric type implementations need to happen in Rust first, followed by implementations in the language bindings.&lt;/p&gt;
&lt;p&gt;All of the implementation work today is mostly manual, but usually follows the same approach.
The language binding implementations should not hold additional state, but currently some still do.&lt;/p&gt;
&lt;p&gt;Implementation of new metric types and fixing bugs or improving the recording APIs of existing ones results in a lot of busy work replicating the same code patterns in all the languages
(of which we now have have 7: Kotlin, Swift, Python, C#, Rust, JavaScript and C++).
If we also come up with new metric types next year this becomes worse.&lt;/p&gt;
&lt;p&gt;A while ago some of my colleagues started the &lt;a href=&quot;https://github.com/mozilla/uniffi-rs&quot;&gt;UniFFI&lt;/a&gt; project, a multi-language bindings generator for Rust.
For a couple of reasons the Glean SDK cannot rely on that yet.&lt;/p&gt;
&lt;p&gt;In 2021 I want us to work towards the goal of using UniFFI (or something like it) to reduce the manual work required on each language binding.
This should reduce our general workload supporting several languages and help us avoid accidental bugs on implementing (and maintaining) metric types.&lt;/p&gt;
&lt;p&gt;This is a rather short list of things that only focus on the SDK.
Let&#39;s see what we get tackled in 2021.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;End of 2020&lt;/h2&gt;
&lt;p&gt;The This Week in Glean series is going into winter hiatus until the second week of January 2021.
Thanks to everyone who contributed to 25 This Week in Glean blog posts in 2020:&lt;/p&gt;
&lt;p&gt;Alessio, Travis, Mike, Chutten, Bea, Raphael, Anthony, Will &amp;amp; Daosheng&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2020/12/18/glean-in-2021</guid>
      <pubDate>Fri, 18 Dec 2020 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: FOG progress report</title>
      <link>https://fnordig.de/2020/10/06/fog-progress-report</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2020/10/06/this-week-in-glean-fog-progress-report/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;About a year ago chutten started the &quot;This Week in Glean&quot; series with an initial
&lt;a href=&quot;https://chuttenblog.wordpress.com/2019/10/17/this-week-in-glean-glean-on-desktop-project-fog/&quot;&gt;blog post about Glean on Desktop&lt;/a&gt;.
Back then we were just getting started to bring Glean to Firefox Desktop.
No code had been written for Firefox Desktop, no proposals had been written to discuss how we even do it.&lt;/p&gt;
&lt;p&gt;Now, 12 months later, after four completed milestones, a dozen or so proposal and quite a bit of code,
the Project Firefox on Glean (FOG) is finally getting into a stage where we can actually use and test it.
It&#39;s not ready for prime time yet, but FOG is enabled in Firefox Nightly already.&lt;/p&gt;
&lt;p&gt;Over the past 4 weeks I&#39;ve been on and off working on building out our support for a C++ and a JavaScript API.
Soon Firefox engineers will be able to instrument their code using Glean.
In C++ this will look like:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;mozilla::glean::test_only::count_something.Add(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;42&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;JavaScript developers will use it like this:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Glean&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.test_only.count_something.&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My work is done in &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1646165&quot;&gt;bug 1646165&lt;/a&gt;.
It&#39;s still under review and needs some fine-tuning before that, but I hope to land it by next week.
We will then gather some data from Nightly and validate that it works as expected (&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1651110&quot;&gt;bug 1651110&lt;/a&gt;),
before we let it ride the trains to land in stable (&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1651111&quot;&gt;bug 1651111&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Our work won&#39;t end there.
With my initial API work landing we can start supporting all metric types,
we still need to figure out some details of how FOG will handle IPC,
and then there&#39;s the whole process of convincing other people to use the new system.&lt;/p&gt;
&lt;p&gt;2020 will be the year of Glean on the Desktop.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2020/10/06/fog-progress-report</guid>
      <pubDate>Tue, 06 Oct 2020 16:00:00 +0200</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Leveraging Rust to build cross-platform mobile libraries</title>
      <link>https://fnordig.de/2020/09/01/leveraging-rust-to-build-cross-platform-mobile-libraries</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2020/09/01/twig-leveraging-rust/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;A couple of weeks ago I gave a talk titled &lt;a href=&quot;https://www.youtube.com/watch?v=j5rczOF7pzg&quot;&gt;&quot;Leveraging Rust to build cross-platform mobile libraries&quot;&lt;/a&gt;.
You can find my &lt;a href=&quot;https://fnordig.de/talks/2020/rustydays/slides.pdf&quot;&gt;slides as a PDF&lt;/a&gt;.
It was part of the &lt;a href=&quot;https://rusty-days.org/&quot;&gt;Rusty Days&lt;/a&gt; Webference, an online conference that was initially planned to happen in Poland, but had to move online.
Definitely check out &lt;a href=&quot;https://www.youtube.com/watch?v=QaCvUKrxNLI&amp;amp;list=PLf3u8NhoEikhTC5radGrmmqdkOK-xMDoZ&quot;&gt;the other talks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One thing I wanted to achieve with that talk is putting that knowledge out there.
While multiple teams at Mozilla are already building cross-platform libraries, with a focus on mobile integration,
the available material and documentation is lacking.
I&#39;d like to see better guides online, and I probably have to start with what we have done.
But that should also be encouragement for those out there doing similar things to blog, tweet &amp;amp; speak about it.&lt;/p&gt;
&lt;h3&gt;Who else is using Rust to build cross-platform libraries, targetting mobile?&lt;/h3&gt;
&lt;p&gt;I&#39;d like to hear about it.
Find me on Twitter (&lt;a href=&quot;https://twitter.com/badboy_&quot;&gt;@badboy_&lt;/a&gt;) or drop me &lt;a href=&quot;mailto:janerik@fnordig.de&quot;&gt;an email&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The Glean SDK&lt;/h2&gt;
&lt;p&gt;I won&#39;t reiterate the full talk (&lt;a href=&quot;https://www.youtube.com/watch?v=j5rczOF7pzg&quot;&gt;go watch it&lt;/a&gt;, really!), so this is just a brief overview of the Glean SDK itself.&lt;/p&gt;
&lt;p&gt;The Glean SDK is our approach to build a modern Telemetry library, used in Mozilla&#39;s mobile products and soon in Firefox on Desktop as well.&lt;/p&gt;
&lt;p&gt;The SDK consists of multiple components, spanning multiple programming languages for different implementations.
All of the Glean SDK lives in the GitHub repository at &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;mozilla/glean&lt;/a&gt;.
This is a rough diagram of the Glean SDK tech stack:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2020/glean-stack.png&quot; alt=&quot;Glean SDK Stack&quot; /&gt;&lt;/p&gt;
&lt;p&gt;On the very bottom we have &lt;code&gt;glean-core&lt;/code&gt;, a pure Rust library that is the heart of the SDK.
It&#39;s responsible for controlling the database, storing data and handling additional logic (e.g. assembling pings, clearing data, ..).
As it is pure Rust we can rely on all Rust tooling for its development.
We can write tests that &lt;code&gt;cargo test&lt;/code&gt; picks up. We can generate the full API documentation thanks to &lt;code&gt;rustdoc&lt;/code&gt;
and we rely on &lt;code&gt;clippy&lt;/code&gt; to tell us when our code is suboptimal.
Working on &lt;code&gt;glean-core&lt;/code&gt; should be possible for everyone that knows some Rust.&lt;/p&gt;
&lt;p&gt;On top of that sits &lt;code&gt;glean-ffi&lt;/code&gt;.
This is the FFI layer connecting &lt;code&gt;glean-core&lt;/code&gt; with everything else.
While glean-core is pure Rust, it doesn&#39;t actually provide the &lt;em&gt;nice API&lt;/em&gt; we intend for users of Glean.
That one is later implemented on top of it all.
glean-ffi doesn&#39;t contain much logic.
It&#39;s a translation between the proper Rust API of glean-core and C-compatible functions exposed into the dynamic library.
In it we rely on the excellent &lt;a href=&quot;https://docs.rs/ffi-support/&quot;&gt;&lt;code&gt;ffi-support&lt;/code&gt; crate&lt;/a&gt;.
ffi-support knows how to translate between Rust and C types, offers a nice (and safer) abstraction for C strings.
glean-ffi holds &lt;em&gt;some&lt;/em&gt; state: the instantiated global Glean object and metric objects.
We don&#39;t need to pass pointers back and forth. Instead we use opaque handles that index into a map held inside the FFI crate.&lt;/p&gt;
&lt;p&gt;The top layer of the Glean SDK are the different &lt;a href=&quot;https://mozilla.github.io/glean/book/dev/core/internal/implementations.html&quot;&gt;language implementations&lt;/a&gt;.
Language implementations expose a nice ergonomic API to initialize Glean and record metrics in the respective language.
Additionally each implementation handles some special cases for the platform they are running on, like gathering application and platform data or hooking into system events.
The nice API calls into the Glean SDK using the exposed FFI functions of &lt;code&gt;glean-ffi&lt;/code&gt;.
Unfortunately at the moment different language implementations carry different amounts of actual logic in them.
Sometimes metric implementations require this (e.g. we rely on the clock source of Kotlin for timing metrics),
in other parts we just didn&#39;t move the logic out of the implementations yet.
We&#39;re actively working on &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1651382&quot;&gt;moving logic into the Rust part where we can&lt;/a&gt; and might eventually use some code generation to unify the other parts.
&lt;a href=&quot;https://github.com/mozilla/uniffi-rs&quot;&gt;uniffi&lt;/a&gt; is a current experiment for a multi-language bindings generator for Rust we might end up using.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2020/09/01/leveraging-rust-to-build-cross-platform-mobile-libraries</guid>
      <pubDate>Tue, 01 Sep 2020 15:00:00 +0200</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Bytes in Memory (on Android)</title>
      <link>https://fnordig.de/2020/05/04/this-week-in-glean</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;Last week&#39;s blog post: &lt;a href=&quot;https://blog.mozilla.org/data/2020/04/27/this-week-in-glean-glean-for-python-on-windows/&quot;&gt;This Week in Glean: Glean for Python on Windows&lt;/a&gt;
by Mike Droettboom.
All &quot;This Week in Glean&quot; blog posts are listed in the &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;TWiG index&lt;/a&gt;
(and on the &lt;a href=&quot;https://blog.mozilla.org/data/category/glean/&quot;&gt;Mozilla Data blog&lt;/a&gt;).
This article is &lt;a href=&quot;https://blog.mozilla.org/data/2020/05/04/this-week-in-glean-bytes-in-memory-on-android/&quot;&gt;cross-posted on the Mozilla Data blog&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;With the Glean SDK we follow in the footsteps of &lt;a href=&quot;https://github.com/mozilla/application-services&quot;&gt;other teams&lt;/a&gt; to build a cross-platform library to be used in both mobile and desktop applications alike.
In this blog post we&#39;re taking a look at how we transport some rich data across the FFI boundary to be reused on the Kotlin side of things.
We&#39;re using a recent example of a new API in Glean that will &lt;a href=&quot;https://github.com/mozilla/glean/blob/8e0599b4df6c1a08f985e4ad5328fcf81a56a084/docs/dev/core/internal/upload.md&quot;&gt;drive the HTTP upload of pings&lt;/a&gt;,
but the concepts I&#39;m explaining here apply more generally.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; This blog post is not a good introduction on doing Rust on Android, but I do plan to write about that in the future as well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Most of this implementation was done by &lt;a href=&quot;https://brizental.github.io/&quot;&gt;Bea&lt;/a&gt; and I have been merely a reviewer,
around for questions and currently responsible for running final tests on this feature.&lt;/p&gt;
&lt;h2&gt;The problem&lt;/h2&gt;
&lt;p&gt;The Glean SDK provides an &lt;a href=&quot;https://github.com/mozilla/glean/tree/master/glean-core/ffi&quot;&gt;FFI API&lt;/a&gt; that can be consumed by what we call language bindings.
For the most part we pass &lt;abbr title=&quot;Plain Old Data&quot;&gt;POD&lt;/abbr&gt; over that API boundary:
integers of various sizes (a problem in and of itself if the sides disagree about certain integer sizes and signedness),
bools (but actually encoded as an 8-bit integer&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;),
but also strings as pointers to null-terminated UTF-8 strings in memory (for test APIs we encode data into JSON and pass that over as strings).&lt;/p&gt;
&lt;p&gt;However for some internal mechanisms we needed to communicate a bit more data back and forth.
We wanted to have different &lt;em&gt;tasks&lt;/em&gt;, where each task variant could have additional data.
Luckily this additional data is either some integers or a bunch of strings only and not further nested data.&lt;/p&gt;
&lt;p&gt;So this is the data we have on the Rust side:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;enum &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Task {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Upload(Request),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Wait,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Done,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;struct &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Request {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    id: String,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    url: String,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(This code is simplified for the sake of this blog post.
You can find the full code online &lt;a href=&quot;https://github.com/mozilla/glean/blob/8e0599b4df6c1a08f985e4ad5328fcf81a56a084/glean-core/src/upload/mod.rs#L38-L48&quot;&gt;in the Glean repository&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;And this is the API a user would call:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;get_next_task&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() -&amp;gt; Task
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The solution&lt;/h2&gt;
&lt;p&gt;Before we can expose a task through FFI we need to transform it into something C-compatible:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;std::os::raw::&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;c_char&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[repr(u8)]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;pub enum &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Upload {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        id: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*mut c_char&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        url: &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;*mut c_char&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Wait,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    Done,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We define a new enum that&#39;s going to be represent its variant as an 8-bit integer plus the additional data for &lt;code&gt;Upload&lt;/code&gt;.
The other variants stay data-less.&lt;/p&gt;
&lt;p&gt;We also provide conversion from the proper Rust type to the FFI-compatible type:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;From&amp;lt;Task&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;for &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(task: Task) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;Self &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; task {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            Task::Upload(request) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CString::new(request.id).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; url &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;CString::new(request.url).&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                FfiTask::Upload {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    id: document_id.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;into_raw&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    url: path.&lt;/span&gt;&lt;span style=&quot;color:#62a35c;&quot;&gt;into_raw&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            Task::Wait &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask::Wait,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            Task::Done &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask::Done,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The FFI API becomes:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;#[no_mangle]
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;extern &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;C&amp;quot; &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;glean_get_next_task&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() -&amp;gt; FfiTask
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this all set we can throw &lt;a href=&quot;https://github.com/eqrion/cbindgen&quot;&gt;cbindgen&lt;/a&gt; at our code to generate the C header, which will produce this snippet of code:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;enum &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask_Tag {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Upload,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Wait,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Done,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;};
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;typedef &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;uint8_t &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask_Tag;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;typedef struct &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Tag tag;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;char *&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;id;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;char *&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;url;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;} FfiTask_Upload_Body;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;typedef union &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Tag tag;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  FfiTask_Upload_Body upload;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;} FfiTask;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the C representation of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union&quot;&gt;tagged union&lt;/a&gt;.
The layout of these tagged unions has been formally defined in &lt;a href=&quot;https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md&quot;&gt;Rust RFC 2195&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Each variant&#39;s first element is the &lt;code&gt;tag&lt;/code&gt;, allowing us to identify which variant we have.
cbindgen automatically inlined the &lt;code&gt;Wait&lt;/code&gt; and &lt;code&gt;Done&lt;/code&gt; variants: they are nothing more than a &lt;code&gt;tag&lt;/code&gt;.
The &lt;code&gt;Upload&lt;/code&gt; variant however gets its own struct.&lt;/p&gt;
&lt;p&gt;On the Kotlin side of things we use &lt;a href=&quot;https://github.com/java-native-access/jna&quot;&gt;JNA (Java Native Access)&lt;/a&gt; to call C-like functions and interact with C types.
After some research by Bea we found that it already provides abstractions over C unions and structs
and we could implement the equivalent parts for our &lt;code&gt;Task&lt;/code&gt; in Kotlin.&lt;/p&gt;
&lt;p&gt;First some imports and replicating the variants our tag takes.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;import &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;com.sun.jna.Structure
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;import &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;com.sun.jna.Pointer
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;import &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;com.sun.jna.Union
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;enum &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;class TaskTag &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Upload&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Wait&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Done
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next is the body of our &lt;code&gt;Upload&lt;/code&gt; variant. It&#39;s a structure with two pointers to strings.
Kotlin requires some annotations to specify the order of fields in memory.
We also  inherit from &lt;code&gt;Structure&lt;/code&gt;, a class provided by JNA, that will take care of reading from memory and making the data accessible in Kotlin.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;@Structure.FieldOrder(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;UploadBody&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    @&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;JvmField&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; val tag&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Byte &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TaskTag.Done&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.ordinal.toByte(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    @&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;JvmField&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; val id&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Pointer&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;? = &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    @&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;JvmField&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; val url&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Pointer&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;? = &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Structure() { }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And at last we define our union.
We don&#39;t need a field order, it&#39;s a union afterall, only one of the fields is valid at a time.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;open &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;FfiTask&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    @&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;JvmField&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; var tag&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Byte &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TaskTag.Done&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.ordinal.toByte(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    @&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;JvmField&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; var upload&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;UploadBody &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;UploadBody()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Union() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;ByValue &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;FfiTask(), &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Structure.ByValue
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    fun toTask()&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        this.readField(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;when (this.tag.toInt()) {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TaskTag.Upload&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.ordinal &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                this.readField(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;upload&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                val request &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;Request(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    this.upload.id.getRustString(),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                    this.upload.url.getRustString()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                )
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Upload&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(request)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;TaskTag.Wait&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.ordinal &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Wait
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;            else &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Done
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This also defines the conversion to a new Kotlin type that eases usage on the Kotlin side.
&lt;code&gt;getRustString&lt;/code&gt; is a &lt;a href=&quot;https://github.com/mozilla/glean/blob/da1e014e378660f243b92ce6012b7b29188d72d8/glean-core/android/src/main/java/mozilla/telemetry/glean/rust/LibGleanFFI.kt#L40-L42&quot;&gt;small helper&lt;/a&gt;
to copy the null-terminated C-like string to a Kotlin string.&lt;/p&gt;
&lt;p&gt;The FFI function on the Kotlin side is defined as:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;fun glean_get_next_task()&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;FfiTask.ByValue
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The types we convert to and then work with in Kotlin are small classes around the data.
If there&#39;s no attached data it&#39;s an object.&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    val id&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    val url&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) { }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;sealed &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Upload&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;(val request: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;) : &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    object &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Wait&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    object &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Done&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As the final piece of this code on the Kotlin side we can now fetch new tasks, convert it to more convenient Kotlin objects and work with them:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;val incomingTask &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;LibGleanFFI.INSTANCE&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.glean_get_next_task()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;when (val action &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; incomingTask.toTask()) {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    is &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Upload &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;upload(action.request.id, action.request.url)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Wait &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; return &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Result&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.retry()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Task.Done &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;-&amp;gt; return &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Result&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.success()
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;What&#39;s next?&lt;/h2&gt;
&lt;p&gt;Currently our new upload mechanism is under testing.
We&#39;re reasonably sure that our approach of passing rich data across the FFI boundary is sound and not causing memory safety issues for now.&lt;/p&gt;
&lt;p&gt;The advantage of going the way of encoding Rust enums into tagged unions for us is that we can use this API in all our current API consumers.
C structs and unions are supported in Kotlin (for Android), Swift (for our iOS users) and Python (e.g. Desktop apps such as &lt;a href=&quot;https://wlach.github.io/blog/2020/04/mozregression-for-macos/&quot;&gt;mozregression&lt;/a&gt;).
It didn&#39;t require new tooling or dependencies to get it working and it&#39;s reasonably cheap in terms of processing cost (it&#39;s copying around a few bytes of data in memory).&lt;/p&gt;
&lt;p&gt;The disadvantage however is that it requires quite a bit of coordination of the different pieces of code.
As you&#39;ve seen above for Kotlin we need to be careful to replicate the exact layout of data and all of this is (currently) hand-written.
Any change on the Rust side might break this easily.
Swift is a bit easier on this front as it has direct C translation.&lt;/p&gt;
&lt;p&gt;The application-services team faced the same problem of how to transport rich data across the FFI boundary.
They decided to go with protocol buffers and generate code for both sides of the FFI. They wrote about it in &lt;a href=&quot;https://hacks.mozilla.org/2019/04/crossing-the-rust-ffi-frontier-with-protocol-buffers/&quot;&gt;Crossing the Rust FFI frontier with Protocol Buffers&lt;/a&gt;.
We decided against this way (for now), as it requires a bit more of a heavy-handed setup initially.
We might reconsider this if we need to expand this API further.&lt;/p&gt;
&lt;p&gt;My dream solution is still a &lt;code&gt;*-bindgen&lt;/code&gt; crate akin to &lt;a href=&quot;https://crates.io/crates/wasm-bindgen&quot;&gt;wasm-bindgen&lt;/a&gt; that creates all this code.&lt;/p&gt;
&lt;br&gt;
&lt;hr /&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Don&#39;t use a bool with JNA. JNA doesn&#39;t handle it well and has its own conception of the size of a bool that differs from what C and Rust think. See &lt;a href=&quot;https://mozilla.github.io/glean/book/dev/ffi/when-to-use-what-in-the-ffi.html#primitives&quot;&gt;When to use what method of passing data between Rust and Java/Swift&lt;/a&gt; in the Glean SDK book. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2020/05/04/this-week-in-glean</guid>
      <pubDate>Mon, 04 May 2020 15:30:00 +0200</pubDate>
    </item>
    <item>
      <title>Review Feedback: a response to the Feedback Ladder</title>
      <link>https://fnordig.de/2020/03/18/review-feedback</link>
      <description>&lt;p&gt;Last week I read &lt;a href=&quot;https://www.netlify.com/blog/2020/03/05/feedback-ladders-how-we-encode-code-reviews-at-netlify/&quot;&gt;Feedback Ladders: How We Encode Code Reviews at Netlify&lt;/a&gt; and also shared that with my team at Mozilla.
In this post I want to summarize how we organize our reviews and compare that to Netlify&#39;s &lt;em&gt;Feedback Ladder&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;My team is mainly responsible for all work on &lt;a href=&quot;https://searchfox.org/mozilla-central/source/toolkit/components/telemetry&quot;&gt;Firefox Telemetry&lt;/a&gt; and &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;our other projects&lt;/a&gt;.
(Nearly) everything we do is first tracked in Bugs on &lt;a href=&quot;https://bugzilla.mozilla.org/home&quot;&gt;Bugzilla&lt;/a&gt;.
No code change (nor doc change) will land without review.
For changes to land in Firefox the developer is responsible for picking the right reviewer, though right now that&#39;s mostly shared work between chutten and me. Sometimes we need to involve experts from other components of Firefox.&lt;/p&gt;
&lt;p&gt;On Glean we rely on an &lt;a href=&quot;https://github.com/apps/auto-assign&quot;&gt;auto-assign bot&lt;/a&gt; to pick a reviewer after opening a pull request.
Sometimes the submitter also actively picks one from the team as a reviewer, e.g. if it&#39;s a followup to previous work or if some niche expertise is needed.&lt;/p&gt;
&lt;p&gt;When reviewing we use a system not too dissimilar to the Feedback ladder.
However it is much more informal.&lt;/p&gt;
&lt;p&gt;Let&#39;s compare the different steps:&lt;/p&gt;
&lt;h2&gt;⛰ Mountain / Blocking and requires immediate action&lt;/h2&gt;
&lt;p&gt;In Mozilla speak that would be an &quot;r-&quot; - &quot;Rejected&quot;.
In my team this rarely (never?) happens on code changes.&lt;/p&gt;
&lt;p&gt;On any bigger changes or features we usually start with a design proposal, that goes through feedback iterations with stakeholders (the direct team or colleagues from other teams, depending on scope).
This would be the point to shut down ideas or turn them around to fit our and our user&#39;s needs.
Design proposals vary in depth, but may already include implementation details where required.&lt;/p&gt;
&lt;h2&gt;🧗‍♀️ Boulder / Blocking&lt;/h2&gt;
&lt;p&gt;For us this is &quot;Changes requested&quot;.
Both review tools we use (Phabricator and plain GitHub PRs) have this as explicit review states.&lt;/p&gt;
&lt;p&gt;The code change can&#39;t land until problems are fixed.
Once the developer pushed new changes the pull request will need another round of review.&lt;/p&gt;
&lt;p&gt;All problems should be clearly pointed out during the review and comments attached to where the problem is.
However, unlike the Feedback ladder, our individual comments don&#39;t follow a strict wording, so the developer who submitted the change can&#39;t differentiate between them easily.&lt;/p&gt;
&lt;h2&gt;⚪️ Pebble / Non-blocking but requires future action&lt;/h2&gt;
&lt;p&gt;This is famously known here as &quot;r+wc&quot; - &quot;review accepted, with comments&quot;.&lt;/p&gt;
&lt;p&gt;Now for us this is actually two different parts:&lt;/p&gt;
&lt;p&gt;First, the reviewer is fine with the overall change, but found some smaller things that definitely need to be changed, such as documentation wording, code comments or naming.
However, it is considered the developer&#39;s task to ensure these changes get made before the PR is landed and no additional round of review needs to follow.
GitHub luckily allows reviewers to submit the &lt;em&gt;exact change&lt;/em&gt; required and the developer can apply it with a button click, so there&#39;s not always the need to go back to the code editor, commit code, push it, ...&lt;/p&gt;
&lt;p&gt;Second, some things require a follow-up, such as some possible code refactor, additional features or tracking the bug fix through the release process for later validation
(we deal with data, so for some fixes we need to see real-world data coming in to determine if the fix worked).
Reviewers should ask for a bug to be filed and the developer usually posts the filed bug as a comment.
In that state the pull request is then ready to get merged.&lt;/p&gt;
&lt;p&gt;Again, there&#39;s no formal concept or wording (other than &quot;this needs a follow-up bug&quot; and GitHub&#39;s &quot;Apply suggestion&quot;) we use to make the review comments stick out.&lt;/p&gt;
&lt;h2&gt;⏳ Sand / Non-blocking but requires future consideration&lt;/h2&gt;
&lt;p&gt;This is very similar to the &quot;⚪️ Pebble&quot; step, but the follow-up bugs filed are more likely going to be &quot;Investigate ...&quot; or &quot;Proposal for ...&quot;.&lt;/p&gt;
&lt;h2&gt;🌫 Dust / Non-blocking, “take it or leave it”&lt;/h2&gt;
&lt;p&gt;This is all the other little comments and will usually end in a &quot;r+&quot; - &quot;Review done &amp;amp; accepted&quot;.
We enforce code formatting via tools, so there&#39;s rarely need to discuss this.
Therefore this comes down to naming or slightly different code patterns.&lt;/p&gt;
&lt;p&gt;More often than not I label these in my comments as &quot;small nit: ...&quot;.
More often than not these are still taken in and applied.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;So ... ?&lt;/h2&gt;
&lt;p&gt;In my team we already use an informal but working method to express the different kinds of review feedback.
We certainly lack in clarity and immediate visibility of the different patterns and that&#39;s certainly a thing we can improve.
Not only might that help us right now, it would also help in later onboarding new folks.&lt;/p&gt;
&lt;p&gt;I&#39;m not fully sold on the metaphors used in the &lt;em&gt;Feedback Ladder&lt;/em&gt;, but I do like using emojis in combination with plaintext to signal things.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2020/03/18/review-feedback</guid>
      <pubDate>Wed, 18 Mar 2020 12:30:00 +0100</pubDate>
    </item>
    <item>
      <title>Two-year Moziversary</title>
      <link>https://fnordig.de/2020/03/02/two-year-moziversary</link>
      <description>&lt;p&gt;Woops, looks like I missed my Two Year Moziversary!
2 years ago, in March 2018, I joined Mozilla as a Firefox Telemetry Engineer.
Last year I blogged about &lt;a href=&quot;https://fnordig.de/2019/03/01/one-year-moziversary/&quot;&gt;what happened in my first year&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One year later I am still in the same team, but other things changed.
Our team grew (hello Bea &amp;amp; Mike!), and shrank (bye Georg!), lots of other changes at Mozilla happened as well.&lt;/p&gt;
&lt;p&gt;However one thing stayed during the whole year: Glean.&lt;br /&gt;
Culminating in the &lt;a href=&quot;https://fnordig.de/2019/10/24/this-week-in-glean/&quot;&gt;very first Glean-written-in-Rust release&lt;/a&gt;, but not slowing down after,
the Glean project is changing how we do telemetry in Mozilla products.&lt;/p&gt;
&lt;p&gt;Glean is now being used in multiple products across mobile and desktop operating systems
(&lt;a href=&quot;https://github.com/mozilla-mobile/fenix/&quot;&gt;Firefox Preview&lt;/a&gt;,
&lt;a href=&quot;https://github.com/mozilla-lockwise/lockwise-android&quot;&gt;Lockwise for Android&lt;/a&gt;,
&lt;a href=&quot;https://github.com/mozilla-lockwise/lockwise-ios&quot;&gt;Lockwise for iOS&lt;/a&gt;,
&lt;a href=&quot;https://searchfox.org/mozilla-central/source/toolkit/components/telemetry/fog&quot;&gt;Project FOG&lt;/a&gt;).
We&#39;ve seen over 2000 commits on that project,
published 16 &lt;a href=&quot;https://github.com/mozilla/glean/releases&quot;&gt;releases&lt;/a&gt;
and posted 14 &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;This Week in Glean blogposts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This year will be focused on maintaining Glean, building new capabailities and bringing more of Glean back into Firefox on Desktop.
I am also looking forward to speak more about Rust and how we use it to build and maintain cross-platform libraries.&lt;/p&gt;
&lt;p&gt;To the next year and beyond!&lt;/p&gt;
&lt;h2&gt;Thank you&lt;/h2&gt;
&lt;p&gt;Thanks to my team: &lt;a href=&quot;https://brizental.github.io/2019/12/06/this-week-in-glean-migrations.html&quot;&gt;:bea&lt;/a&gt;, &lt;a href=&quot;https://chuttenblog.wordpress.com/&quot;&gt;:chutten&lt;/a&gt;, &lt;a href=&quot;https://www.a2p.it/wordpress/tech-stuff/mozilla/geckoview-glean-fenix-performance-metrics/&quot;&gt;:Dexter&lt;/a&gt;, &lt;a href=&quot;http://droettboom.com/&quot;&gt;:mdboom&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://blogoftravis.wordpress.com/&quot;&gt;:travis&lt;/a&gt;!&lt;br /&gt;
Lots of my work involves collaborating with people outside my direct team, gathering feedback, taking in feature requests and triaging bug reports.
So thanks also to all the other people at Mozilla I work with.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2020/03/02/two-year-moziversary</guid>
      <pubDate>Mon, 02 Mar 2020 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>&quot;Edit this file on GitHub&quot;</title>
      <link>https://fnordig.de/2020/02/06/edit-this-file-on-github</link>
      <description>&lt;p&gt;At work I help with maintaining two large documentation books:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.telemetry.mozilla.org/&quot;&gt;Firefox Data Docs&lt;/a&gt; aka docs.telemetry.mozilla.org aka dtmo&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mozilla.github.io/glean/book/index.html&quot;&gt;The Glean SDK book&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Back in 2018 I migrated dtmo from gitbook to &lt;a href=&quot;https://github.com/rust-lang/mdBook&quot;&gt;mdbook&lt;/a&gt; (see &lt;a href=&quot;https://github.com/mozilla/firefox-data-docs/pull/187&quot;&gt;the pull request&lt;/a&gt;).
mdbook is maintained by the Rust project and hosts the &lt;a href=&quot;https://doc.rust-lang.org/book/&quot;&gt;Rust book&lt;/a&gt; as well as a multitude of other community projects.
It provided all we need, plus a way to extend it with some small things, I blogged about &lt;a href=&quot;http://localhost:8000/2019/07/11/mdbook-toc-and-mermaid-preprocessors/&quot;&gt;ToC and mermaid&lt;/a&gt; before.&lt;/p&gt;
&lt;p&gt;During the Mozilla All Hands last week my colleague Mike casually asked why we don&#39;t have links to quickly edit the documentation.
When someone discovers a mistake or inaccuracy in the book the current process involves finding the repository of the book, then finding the right file, then edit that file (through the GitHub UI or by cloning the repository),
then push changes, open a pull request, wait for review and finally get it merged and deployed.&lt;/p&gt;
&lt;p&gt;I immediately set out to build this feature.&lt;/p&gt;
&lt;p&gt;I present to you: &lt;strong&gt;&lt;a href=&quot;https://github.com/badboy/mdbook-open-on-gh/&quot;&gt;mdbook-open-on-gh&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It&#39;s another preprocessor for mdbook, that adds a link to the edit dialog on GitHub (if your book is actually hosted on GitHub).
And that&#39;s how it looks:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2020/open-on-gh-gleanbook.png&quot; alt=&quot;Screenshot of a Glean SDK book site showing the &amp;quot;Edit this file on GitHub&amp;quot; link&quot; /&gt;&lt;/p&gt;
&lt;p&gt;It&#39;s already deployed on dtmo and the Glean SDK book and simplifies the workflow to: click the link, edit the file on GitHub, commit and open a PR, get a review and merge it to deploy.&lt;/p&gt;
&lt;p&gt;If you want to use this preprocessor, install it:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo install mdbook-open-on-gh
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add it as a preprocessor to your &lt;code&gt;book.toml&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[preprocessor.open-on-gh]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;command = &amp;quot;mdbook-open-on-gh&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;renderer = [&amp;quot;html&amp;quot;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add a repository URL to use as a base in your &lt;code&gt;book.toml&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[output.html]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;git-repository-url = &amp;quot;https://github.com/mozilla/glean&amp;quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To style the footer add a custom CSS file for your HTML output:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[output.html]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;additional-css = [&amp;quot;open-in.css&amp;quot;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And in &lt;code&gt;open-in.css&lt;/code&gt; style the &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt; element or directly the CSS element id &lt;code&gt;open-on-gh&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;footer &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;font-size&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0.8&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;em&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;text-align&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: center;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;border-top&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;px &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;solid black;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;padding&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;px &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code block shrinks the text size, center-aligns it under the rest of the content
and adds a small horizontal bar above the text to separate it from the page content.&lt;/p&gt;
&lt;p&gt;Finally, build your book as normal:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;mdbook path/to/book
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</description>
      <guid>https://fnordig.de/2020/02/06/edit-this-file-on-github</guid>
      <pubDate>Thu, 06 Feb 2020 16:38:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Cargo features - an investigation</title>
      <link>https://fnordig.de/2020/02/03/this-week-in-glean</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean. You can find an &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;index of all TWiG posts online&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;The last blog post: &lt;a href=&quot;https://brizental.github.io/2020/01/10/this-week-in-glean-glossary.html&quot;&gt;This Week in Glean: Glossary&lt;/a&gt; by Bea.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;As :chutten outlined in the first &lt;a href=&quot;https://chuttenblog.wordpress.com/2019/10/17/this-week-in-glean-glean-on-desktop-project-fog/&quot;&gt;TWiG blog post&lt;/a&gt; we&#39;re currently prototyping Glean on Desktop.
After a couple rounds of review, some adjustements and some learnings from doing Rust on mozilla-central, we were ready to land the first working prototype code earlier this year (&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1591564#c25&quot;&gt;Bug 1591564&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Unfortunately the patch set was &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1591564#c27&quot;&gt;backed out nearly immediately&lt;/a&gt; &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; for 2 failures.
The first one was a &quot;leak&quot; (we missed cleaning up memory in a way to satisfy the rigorous Firefox test suite, that was fixed in &lt;a href=&quot;https://phabricator.services.mozilla.com/D59531&quot;&gt;another patch&lt;/a&gt;).
The second one was a build failure on a Windows platform.&lt;/p&gt;
&lt;p&gt;This is what the log had to say about it (shortened to the relevant parts here, &lt;a href=&quot;https://treeherder.mozilla.org/logviewer.html#/jobs?job_id=283842210&amp;amp;repo=autoland&amp;amp;lineNumber=93915&quot;&gt;see the full log output&lt;/a&gt;):&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;lld-link: error: undefined symbol: __rbt_backtrace_pcinfo
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; referenced by gkrust_gtest.lib(backtrace-5286ea09b9822175.backtrace.3kzojw1m-cgu.3.rcgu.o)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;lld-link: error: undefined symbol: __rbt_backtrace_create_state
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; referenced by gkrust_gtest.lib(backtrace-5286ea09b9822175.backtrace.3kzojw1m-cgu.3.rcgu.o)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;lld-link: error: undefined symbol: __rbt_backtrace_syminfo
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; referenced by gkrust_gtest.lib(backtrace-5286ea09b9822175.backtrace.3kzojw1m-cgu.3.rcgu.o)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;clang-9: error: linker command failed with exit code 1 (use -v to see invocation)
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;/builds/worker/workspace/build/src/config/rules.mk:608: recipe for target &amp;#39;xul.dll&amp;#39; failed]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I set out to investigate this error.
While I had not seen that particular error before, I knew about the &lt;a href=&quot;https://docs.rs/backtrace/0.3.43/backtrace/&quot;&gt;&lt;code&gt;backtrace&lt;/code&gt;&lt;/a&gt; crate. It caused me some trouble before (it depends on a C library, and won&#39;t work on all targets easily).
I knew that the Glean SDK doesn&#39;t really depend on its functionality&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and thus removing it from our dependency graph would probably solve the issue.
But first I had to find out why we depend on it somewhere and why it is causing these linker errors to begin with.&lt;/p&gt;
&lt;p&gt;The first thing I noticed is that we didn&#39;t include anything new in the patch set that was now rejected.
Through some experimentation and use &lt;a href=&quot;https://crates.io/crates/cargo-tree&quot;&gt;&lt;code&gt;cargo-tree&lt;/code&gt;&lt;/a&gt; I could tell that &lt;code&gt;backtrace&lt;/code&gt; was included in the build before our Glean patch&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, as a transitive dependency of another crate: &lt;a href=&quot;https://docs.rs/failure/0.1.6/failure/&quot;&gt;&lt;code&gt;failure&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So why didn&#39;t it fail the build before?
As per the errors above, the build failed only during linking, not compilation, which makes me believe those functions were never linked in previously, because no one passed around any errors that would cause these functions to be used.&lt;/p&gt;
&lt;p&gt;As said before, the Glean SDK doesn&#39;t really need failure&#39;s backtrace feature, so I tried disabling its default features.
Due to how cargo currently works, this needs to be done across all transitive dependencies (the final feature set a crate is compiled with is the union across everything).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mozilla/application-services/pull/2448&quot;&gt;Disabling it in ffi-support in application-services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mozilla/glean/commit/eed8f16f6afdbf8599301bf1a95d745c1eeab4b9&quot;&gt;Disabling it in Glean (and depending on that changed ffi-support&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I then changed mozilla-central to use the crates from git directly for testing.&lt;/p&gt;
&lt;p&gt;Turns out that still fails with the same issue on the Windows target.
Something was re-enabling the &quot;std&quot; feature of &lt;code&gt;failure&lt;/code&gt; in tree.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/cargo-feature-set&quot;&gt;&lt;code&gt;cargo-feature-set&lt;/code&gt;&lt;/a&gt; was able to show me all enabled features for all dependencies I tracked it down further&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Turns out the &lt;code&gt;quantum_render&lt;/code&gt; feature enables the &lt;a href=&quot;https://searchfox.org/mozilla-central/source/gfx/webrender_bindings/&quot;&gt;webrender_bindings&lt;/a&gt; crate,
which then somehow pulls in &lt;code&gt;failure&lt;/code&gt; through transitive dependencies again.
More trial-and-error revealed its a dependency of &lt;a href=&quot;https://searchfox.org/mozilla-central/rev/a92ed79b0bc746159fc31af1586adbfa9e45e264/gfx/webrender_bindings/Cargo.toml#31&quot;&gt;the dirs crate&lt;/a&gt;, only used on Windows.
Except dirs doesn&#39;t &lt;em&gt;need&lt;/em&gt; &lt;code&gt;failure&lt;/code&gt; for the target we&#39;re building for (&lt;code&gt;x86_64-pc-windows-gnu&lt;/code&gt; or Mac or Linux).
It&#39;s again a transitive dependency for a crate called &lt;code&gt;redox_users&lt;/code&gt;, which is &lt;a href=&quot;https://github.com/soc/dirs-rs/blob/3c3b61ff9611762bece3fc66fd6612b125819e3f/Cargo.toml#L15-L16&quot;&gt;only pulled in when compiled for Redox&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Except that&#39;s not how Cargo works.
Cargo always pulls in all dependencies, merges all features and only later ignores the crates it doesn&#39;t actually need.
That&#39;s a long standing issue:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rust-lang/cargo/issues/1796&quot;&gt;cargo#1796&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rust-lang/cargo/issues/2589&quot;&gt;cargo#2589&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rust-lang/cargo/issues/4361&quot;&gt;cargo#4361&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So now we identified who&#39;s pulling in the backtrace crate and maybe even identified why it was not a problem before.
How do we fix this?&lt;/p&gt;
&lt;p&gt;As shown before, just disabling the backtrace feature in crates we use directly doesn&#39;t solve it, so one quick workaround was to force &lt;code&gt;failure&lt;/code&gt; itself to not have that feature ever.
Easily done:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#ffecec;font-weight:bold;font-style:italic;color:#bd2c00;&quot;&gt;---&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt; Cargo.toml
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;font-style:italic;color:#55a532;&quot;&gt;+++&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt; Cargo.toml
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;font-style:italic;color:#969896;&quot;&gt;@@ -23,5 +23,5 @@&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; members = [&amp;quot;.&amp;quot;, &amp;quot;failure_derive&amp;quot;]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; [features]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; default = [&amp;quot;std&amp;quot;, &amp;quot;derive&amp;quot;]
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; #small-error = [&amp;quot;std&amp;quot;]
&lt;/span&gt;&lt;span style=&quot;background-color:#ffecec;color:#323232;&quot;&gt;-std = [&amp;quot;backtrace&amp;quot;]
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;std = []
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; derive = [&amp;quot;failure_derive&amp;quot;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I &lt;a href=&quot;https://github.com/badboy/failure/commit/64af847bc5fdcb6d2438bec8a6030812a80519a5&quot;&gt;forked failure and commited that patch&lt;/a&gt;, then made mozilla-central use &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1608157&quot;&gt;my forked version&lt;/a&gt; instead.
Later I also removed &lt;code&gt;failure&lt;/code&gt; from both Glean and application-services&#39; &lt;code&gt;ffi-support&lt;/code&gt;, as the small functionality we got from it was easily reimplemented manually.&lt;/p&gt;
&lt;p&gt;Both approaches are short-term fixes for getting Glean into Firefox and it&#39;s clear that this issue might easily come up in some form soon again for either us or another team.
It&#39;s also a major hassle for lots of people outside of Mozilla, for example people working on embedded Rust frequently run into problems with &lt;code&gt;no_std&lt;/code&gt; libraries suddenly linking in &lt;code&gt;libstd&lt;/code&gt; again.&lt;/p&gt;
&lt;p&gt;Initially I also planned to figure out a way forward for Cargo and come up with a fix for it, but as it turns out: Someone is already doing that!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ehuss&quot;&gt;@ehuss&lt;/a&gt; started working on &lt;a href=&quot;https://github.com/rust-lang/cargo/pull/7820&quot;&gt;adding a new feature resolver&lt;/a&gt;.
While not yet final, it will bring a new &lt;code&gt;-Zfeatures&lt;/code&gt; flag initially:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;itarget&lt;/code&gt; — Ignores features for target-specific dependencies for targets that don&#39;t match the current compile target.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;build_dep&lt;/code&gt; — Prevents features enabled on build dependencies from being enabled for normal dependencies.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dev_dep&lt;/code&gt; — Prevents features enabled on dev dependencies from being enabled for normal dependencies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;m excited to see this being worked on and can&#39;t wait to try it out.
It will take longer for mozilla-central to rely on this of course, but I hope this will eventually solve one of the long standing issues with cargo.&lt;/p&gt;
&lt;br&gt;
&lt;hr /&gt;
&lt;br&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;cargo tree --features bitsdownload,cranelift_x86,cubeb-remoting,fogotype,gecko_debug,gecko_profiler,gecko_refcount_logging,moz_memory,moz_places,new_cert_storage,new_xulstore,quantum_render
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;When patches are merged, a full set of tests are run on the Mozilla CI servers. If these tests fail the patch is reverted (&quot;backed out&quot;) and the initial committer informed. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Glean&#39;s error handling is pretty simplistic. We mostly only log errors on the FFI boundary and don&#39;t propagate them over this boundary. So far we didn&#39;t need a backtrace for errors there. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;The exact command enabling all the same features as the build I run in &lt;code&gt;toolkit/library/rust/shared&lt;/code&gt; was (on the parent commit of my later patch to fix it: &lt;a href=&quot;https://hg.mozilla.org/integration/autoland/rev/7a3be2bbce032721ec01a9b75d88cc7c6b089825&quot;&gt;7a3be2bbc&lt;/a&gt;): &lt;a href=&quot;#fr-3-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;Same feature set as above, just running &lt;code&gt;cargo feature-set&lt;/code&gt; this time. &lt;a href=&quot;#fr-4-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;&quot;&lt;a href=&quot;https://www.redox-os.org/&quot;&gt;Redox&lt;/a&gt; is a Unix-like Operating System written in Rust, aiming to bring the innovations of Rust to a modern microkernel and full set of applications&quot;. Firefox doesn&#39;t build on Redox. &lt;a href=&quot;#fr-5-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2020/02/03/this-week-in-glean</guid>
      <pubDate>Mon, 03 Feb 2020 15:00:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: Differences</title>
      <link>https://fnordig.de/2019/11/29/this-week-in-glean</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean. You can find an &lt;a href=&quot;https://mozilla.github.io/glean/book/appendix/twig.html&quot;&gt;index of all TWiG posts online&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;Last week&#39;s blog post: &lt;a href=&quot;https://chuttenblog.wordpress.com/2019/11/22/this-week-in-glean-glean-in-private/&quot;&gt;This Week in Glean: Glean in Private&lt;/a&gt; by chutten.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Currently my team is responsible for the Telemetry framework inside Firefox on Desktop and also &lt;a href=&quot;https://github.com/mozilla/glean&quot;&gt;the Glean SDK&lt;/a&gt;, targeting our mobile products.
We&#39;re working on bringing the Glean experience to Firefox on Desktop, but in the meantime &lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/index.html&quot;&gt;Telemetry&lt;/a&gt; is what we have,
need to support and sometimes implement new features on.&lt;/p&gt;
&lt;p&gt;One of these features is a new ping (or, better, a change in a ping), that we now want to support across all our products.
I&#39;m speaking of the &lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/deletion-request-ping.html&quot;&gt;&lt;code&gt;deletion-request&lt;/code&gt; ping&lt;/a&gt; here.
When a user opts out of Telemetry we take this as a signal to also delete associated data from our pipeline.&lt;/p&gt;
&lt;p&gt;Implementation in Firefox Desktop was merely renaming &lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/obsolete/optout-ping.html&quot;&gt;an existing ping&lt;/a&gt; that is triggered when the user disables &quot;Data Collection and Use&quot; (&lt;code&gt;about:preferences&lt;/code&gt; -&amp;gt; Privacy &amp;amp; Security). It contains no additional data.
Implementation in Glean was not much harder either. Glean already supports &lt;a href=&quot;https://mozilla.github.io/glean/book/user/pings/custom.html&quot;&gt;custom pings&lt;/a&gt;: Pings that can be defined and send by the application using Glean.
Glean&#39;s internal pings follow the same pattern, they are just pre-defined.
The biggest difference?&lt;/p&gt;
&lt;p&gt;It&#39;s called &lt;code&gt;deletion_request&lt;/code&gt; ping instead.&lt;/p&gt;
&lt;p&gt;On ingestion data from a ping is decoded from its JSON form and put into tables on BigQuery
(in our documentation you can find &lt;a href=&quot;https://docs.telemetry.mozilla.org/concepts/pipeline/gcp_data_pipeline.html#an-overview-of-mozillas-data-pipeline&quot;&gt;an overview of the data pipeline&lt;/a&gt; if you are interested).
BigQuery table names can only contain alphanumeric characters and underscores (see &lt;a href=&quot;https://cloud.google.com/bigquery/docs/tables#table_naming&quot;&gt;&quot;Table naming&quot;&lt;/a&gt; in the BigQuery documentation).
We avoid any translation in the pipeline by just enforcing this directly on ping names.&lt;/p&gt;
&lt;p&gt;Glean also enforces the payload schema of pings.
Glean itself controls portion of the data, including a sequence number, date field
and a bit of metadata about the application its running in (see &lt;a href=&quot;https://mozilla.github.io/glean/book/user/pings/index.html#ping-sections&quot;&gt;the ping sections&lt;/a&gt;).
The rest of the payload consists of &lt;a href=&quot;https://mozilla.github.io/glean/book/user/metrics/index.html&quot;&gt;metrics&lt;/a&gt; as defined by users of Glean.
While implementing the new ping I stumbled upon another small detail of Glean: Pings won&#39;t be sent out if they would not contain any metrics.
And our new ping, by design, should not contain any metrics!&lt;/p&gt;
&lt;p&gt;We don&#39;t want to change this for other pings, so I had to introduce a new flag now:
&lt;code&gt;sendIfEmpty&lt;/code&gt; (&lt;a href=&quot;https://github.com/mozilla/glean_parser/pull/139&quot;&gt;PR #139&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;That way we can allow the &lt;code&gt;deletion_request&lt;/code&gt; ping to be sent without any metrics in there, only containing the basic information.&lt;/p&gt;
&lt;p&gt;The implementation of the new ping is now done and currently waiting for data review (&lt;a href=&quot;https://github.com/mozilla/glean/pull/526&quot;&gt;PR #526&lt;/a&gt;).
I hope to land this early next week.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2019/11/29/this-week-in-glean</guid>
      <pubDate>Fri, 29 Nov 2019 11:37:00 +0100</pubDate>
    </item>
    <item>
      <title>This Week in Glean: A Release</title>
      <link>https://fnordig.de/2019/10/24/this-week-in-glean</link>
      <description>&lt;p&gt;(“This Week in Glean” is a series of blog posts that the Glean Team at Mozilla is using to try to communicate better about our work. They could be release notes, documentation, hopes, dreams, or whatever: so long as it is inspired by Glean.)&lt;/p&gt;
&lt;p&gt;Last week&#39;s blog post: &lt;a href=&quot;https://chuttenblog.wordpress.com/2019/10/17/this-week-in-glean-glean-on-desktop-project-fog/&quot;&gt;This Week in Glean: Glean on Desktop (Project FOG)&lt;/a&gt; by chutten.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Back in June when &lt;a href=&quot;https://blog.mozilla.org/futurereleases/2019/06/27/reinventing-firefox-for-android-a-preview/&quot;&gt;Firefox Preview shipped&lt;/a&gt;, it also shipped with Glean, our new Telemetry library, initially targeting mobile platforms.
Georg recently blogged about the design principles of Glean in &lt;a href=&quot;https://medium.com/georg-fritzsche/introducing-glean-telemetry-for-humans-4e8b4788b8ad&quot;&gt;Introducing Glean — Telemetry for humans&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Plans for improving mobile telemetry for Mozilla go back as as far as December 2017.
The first implementation of the Glean SDK was started around August 2018, all written in Kotlin (though back then it was mostly ideas in a bunch of text documents).
This implementation shipped in &lt;a href=&quot;https://github.com/mozilla-mobile/fenix/&quot;&gt;Firefox Preview&lt;/a&gt; and was used up until now.&lt;/p&gt;
&lt;p&gt;On March 18th I &lt;a href=&quot;https://github.com/mozilla/glean/commit/95b6bcc03616c8d7c3e3e64e99ee9953aa06a474&quot;&gt;created an initial Rust workspace&lt;/a&gt;.
This kicked of a rewrite of Glean using Rust to become a cross-platform telemetry SDK to be used on Android, iOS and eventually coming back to desktop platforms again.&lt;/p&gt;
&lt;p&gt;1382 commits later&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; I tagged &lt;a href=&quot;https://github.com/mozilla/glean/commit/1ac00bf63daea97f6e2d6fa36980279eecf5a800&quot;&gt;v19.0.0&lt;/a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Obviously that doesn&#39;t make people use it right away, but given all consumers of Glean right now are Mozilla products, it&#39;s up on us to get them to use it.
So &lt;a href=&quot;https://github.com/mozilla-mobile/android-components/pull/4620&quot;&gt;Alessio did just that&lt;/a&gt; by upgrading Android Components, a collection of Android libraries to build browsers or browser-like applications, to this new version.&lt;/p&gt;
&lt;p&gt;This will soon roll out to nightly releases of Firefox Preview and, given we don&#39;t hit any larger bugs, hit the release channel in about 2 weeks.
Additionally, that finally unblocks the Glean team to work on new features, ironing out some sharp edges and bringing Glean to Firefox on Desktop.
Oh, and of course we still need to actually release it for iOS.&lt;/p&gt;
&lt;h2&gt;Thanks&lt;/h2&gt;
&lt;p&gt;Glean in Rust is the project I&#39;ve been constantly working on since March.
But getting it to a release was a team effort with help from a multitude of people and teams.&lt;/p&gt;
&lt;p&gt;Thanks to everyone on the Glean SDK team:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dexterp37/&quot;&gt;Alessio Placitelli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mdboom/&quot;&gt;Michael Droettboom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/travis79/&quot;&gt;Travis Long&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/georgf/&quot;&gt;Georg Fritzsche&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/chutten&quot;&gt;Chris Hutten-Czapski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/brizental&quot;&gt;Beatriz Rizental&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://github.com/fbertsch&quot;&gt;Frank Bertsch&lt;/a&gt; for a ton of backend work as well as the larger Glean pipeline team led by &lt;a href=&quot;https://github.com/mreid-moz&quot;&gt;Mark Reid&lt;/a&gt;, to ensure we can handle the incoming telemetry data and also reliably analyse it.
Thanks to the Data Engineering team led by Katie Parlante.
Thanks to &lt;a href=&quot;https://github.com/MihaiTabara&quot;&gt;Mihai Tabara&lt;/a&gt;, the Release Engineering team and the Cloud Operations team, to help us with the release on short notice.
Thanks to the &lt;a href=&quot;https://github.com/mozilla/application-services&quot;&gt;Application Services&lt;/a&gt; team for paving the way of developing mobile libraries with Rust and to the &lt;a href=&quot;https://github.com/mozilla/application-services&quot;&gt;Android Components&lt;/a&gt; team for constant help with Android development.&lt;/p&gt;
&lt;hr /&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Not all of which are just code for the Android version. There&#39;s &lt;a href=&quot;https://mozilla.github.io/glean/docs/glean_core/index.html&quot;&gt;a&lt;/a&gt; &lt;a href=&quot;https://mozilla.github.io/glean/javadoc/glean/&quot;&gt;lot&lt;/a&gt; &lt;a href=&quot;https://mozilla.github.io/glean/swift/&quot;&gt;of&lt;/a&gt; &lt;a href=&quot;https://mozilla.github.io/glean/book/index.html&quot;&gt;documentation&lt;/a&gt; too. &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;This is the first released version. This is just the version number that follows after the Kotlin implementation. Version numbers are cheap. &lt;a href=&quot;#fr-2-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2019/10/24/this-week-in-glean</guid>
      <pubDate>Thu, 24 Oct 2019 17:30:00 +0200</pubDate>
    </item>
    <item>
      <title>One-year Moziversary</title>
      <link>https://fnordig.de/2019/03/01/one-year-moziversary</link>
      <description>&lt;p&gt;At this day last year I walked into the &lt;a href=&quot;https://blog.mozilla.org/berlin/&quot;&gt;Mozilla Berlin&lt;/a&gt; office to start my first day of work.
365 days later, today is my very first &lt;a href=&quot;https://twitter.com/search?f=tweets&amp;amp;vertical=default&amp;amp;q=moziversary&quot;&gt;#moziversary&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I joined the Firefox Telemetry Team, now consisting of &lt;a href=&quot;https://chuttenblog.wordpress.com/&quot;&gt;:chutten&lt;/a&gt;, :Dexter, :gfritzsche, :travis_ (he joined us in November) and me.&lt;/p&gt;
&lt;p&gt;Since I joined I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;visited 5 of the Mozilla Offices (Berlin, Paris, London, Mountain View, San Francisco)&lt;/li&gt;
&lt;li&gt;hosted 2 Rust All-Hands in the Berlin office&lt;/li&gt;
&lt;li&gt;attended 2 Mozilla All-Hands&lt;/li&gt;
&lt;li&gt;had a work week with my team&lt;/li&gt;
&lt;li&gt;hosted regular &lt;a href=&quot;https://berline.rs/2019/03/06/rust-hack-and-learn.html&quot;&gt;Rust Hack&#39;n&#39;Learns&lt;/a&gt; in the office&#39;s Community Space (every second Wednesday!)&lt;/li&gt;
&lt;li&gt;commented on over 250 Bugzilla bugs (about 800 comments apparently)&lt;/li&gt;
&lt;li&gt;were assigned to and closed over 100 bugs&lt;/li&gt;
&lt;li&gt;became a &lt;a href=&quot;https://wiki.mozilla.org/Modules/Toolkit#Telemetry&quot;&gt;Telemetry peer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;broke Firefox and Firefox for Android once or twice&lt;/li&gt;
&lt;li&gt;read a dozen or so internal project proposals&lt;/li&gt;
&lt;li&gt;had an uncountable number of meetings (yes, meetings &lt;em&gt;can&lt;/em&gt; be fun &amp;amp; useful)&lt;/li&gt;
&lt;li&gt;delivered &lt;a href=&quot;/2019/01/22/multi-store-custom-telemetry-with-shared-data/&quot;&gt;crucial new features for Telemetry in Firefox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;wrote far more SQL than I thought this job would involve&lt;/li&gt;
&lt;li&gt;move twice inside Berlin&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... and probably lots of other stuff I forgot.&lt;/p&gt;
&lt;p&gt;The next projects for Firefox Telemetry are already in progress or about to start,
&lt;a href=&quot;https://github.com/mozilla-mobile/android-components/tree/master/components/service/glean&quot;&gt;mobile Telemetry&lt;/a&gt; is progressing quickly
and, while I haven&#39;t written code for the current implementation, I hope to talk more about that soon.&lt;/p&gt;
&lt;p&gt;To the next year and beyond!&lt;/p&gt;
&lt;h2&gt;Thank you&lt;/h2&gt;
&lt;p&gt;First and foremost of course a big &lt;strong&gt;THANK YOU&lt;/strong&gt; to my team.
It&#39;s been &lt;em&gt;fun&lt;/em&gt; working along you.&lt;br /&gt;
Another big thank you to everyone in the Mozilla Berlin office, it&#39;s always a pleasure to come to the office.
And of course thank you for everyone I worked with so far at Mozilla.&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2019/03/01/one-year-moziversary</guid>
      <pubDate>Fri, 01 Mar 2019 12:00:00 +0100</pubDate>
    </item>
    <item>
      <title>multi-store - Custom Telemetry with shared data</title>
      <link>https://fnordig.de/2019/01/22/multi-store-custom-telemetry-with-shared-data</link>
      <description>&lt;p&gt;Last year I implemented a new feature for Firefox Telemetry that changes how we can collect and analyze data with different requirements in regard to user privacy &amp;amp; frequency.
This post will shine some light on the (rather simple) implementation and usage.&lt;/p&gt;
&lt;h3&gt;Intro: What is Firefox Telemetry?&lt;/h3&gt;
&lt;p&gt;In order to understand how Firefox performs in the wild, it can collect a bunch of performance metrics and other information.
How and why we do this and what data we collect is explained in more detail in a blog post by Rebecca Weiss, Director of Data Science here at Mozilla:
&lt;a href=&quot;https://blog.mozilla.org/futurereleases/2017/09/06/data-just-living/&quot;&gt;It’s your data, we’re just living in it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I work on the &lt;a href=&quot;https://searchfox.org/mozilla-central/source/toolkit/components/telemetry/&quot;&gt;Telemetry component&lt;/a&gt; inside Firefox.
It provides APIs that are used by the various other parts of the browser to gather data
and is responsible for storing, collecting and sending this data in what we call &quot;pings&quot;, a periodic collection of measurements.
Telemetry data is only ever sent out if the user agreed to it (see &quot;Data Collection and Use&quot; in the &quot;Privacy &amp;amp; Security&quot; preferences of your Firefox).&lt;/p&gt;
&lt;p&gt;Most data is collected in one of 3 different formats: histograms, scalars &amp;amp; events (see &lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/index.html&quot;&gt;our collection overview&lt;/a&gt;).
Firefox sends this data in the &lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/data/main-ping.html&quot;&gt;&quot;main&quot; ping&lt;/a&gt; once in a while (usually roughly daily) and clears out the stored data locally.
A &quot;main&quot; ping always corresponds to a subsession, which itself is part of a session. This is further explained &lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/concepts/sessions.html&quot;&gt;in our Session concepts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;People working with the data can therefore make certain assumptions on how to interpret the data from multiple pings across sessions and subsessions.&lt;/p&gt;
&lt;h3&gt;The problem&lt;/h3&gt;
&lt;p&gt;Some data should not be correlated with other data due to privacy concerns.
So far we had to push Telemetry users to create custom pings and keep track of their own data.
If they rely on scalars or histograms as recorded by Telemetry, but send a custom ping in different intervals, they can&#39;t make valid assumptions about the metrics, as they might have been reset in between.
This leads to weird hacks or unnecessary code duplication. Additionally we can&#39;t provide any help or support for custom data and our tools can&#39;t handle it automatically (e.g. to generate dashboards).&lt;/p&gt;
&lt;h3&gt;A solution&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Multi-Store&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Every metric was always tied to the schedule of the &quot;main&quot; ping (read: subsession/session).
Our &lt;strong&gt;multi-store&lt;/strong&gt; solution now enables metrics to be associated with multiple stores at once, defaulting to be in the &quot;main&quot; ping only.
Any user with custom requirements can now select metrics to be included in their custom store (which is still subject to &lt;a href=&quot;https://wiki.mozilla.org/Firefox/Data_Collection&quot;&gt;Data Collection Review&lt;/a&gt;).
Telemetry is still responsible for actual data storage and the APIs, but now the custom ping is responsible for collecting, clearing and periodically sending this data.&lt;/p&gt;
&lt;h3&gt;An example&lt;/h3&gt;
&lt;p&gt;To demonstrate how this is used, let&#39;s create a custom ping, which will include one metric of its own and one that&#39;s also available in the &quot;main&quot; store (and thus the &quot;main&quot; ping).&lt;/p&gt;
&lt;p&gt;We start by adding a new metric to &lt;a href=&quot;https://searchfox.org/mozilla-central/source/toolkit/components/telemetry/Scalars.yaml&quot;&gt;Scalars.yaml&lt;/a&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;tick_times_rand&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;bug_numbers&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;0
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;description&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;A random value at every tick&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;expires&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;#39;71&amp;#39;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;uint
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;notification_emails&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;janerik@fnordig.de
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;release_channel_collection&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;opt-out
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;record_in_processes&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;main&amp;quot;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#63a35c;&quot;&gt;record_into_store&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;custom-store&amp;quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This defines a scalar named &lt;code&gt;tick_times_rand&lt;/code&gt; in the &lt;code&gt;browser.engagement&lt;/code&gt; category. The exact details are not important as we will record random values anyway.
The important bit is setting the store using &lt;code&gt;record_into_store&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We also include &lt;code&gt;browser.engagement.tab_open_event_count&lt;/code&gt; into our store by just adding our custom store name to &lt;code&gt;record_into_store&lt;/code&gt; (don&#39;t forget to also include &quot;main&quot; there).&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#ffecec;font-weight:bold;font-style:italic;color:#bd2c00;&quot;&gt;---&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt; c/toolkit/components/telemetry/Scalars.yaml
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;font-style:italic;color:#55a532;&quot;&gt;+++&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt; i/toolkit/components/telemetry/Scalars.yaml
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;font-style:italic;color:#969896;&quot;&gt;@@ -66,6 +66,9 @@&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; browser.engagement:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;     release_channel_collection: opt-out
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;     record_in_processes:
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;       - &amp;#39;main&amp;#39;
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;    record_into_store:
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;      - &amp;quot;main&amp;quot;
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;      - &amp;quot;custom-store&amp;quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we define our new custom ping in a new file in &lt;code&gt;toolkit/components/telemetry/pings/CustomPing.jsm&lt;/code&gt;.
We only define a very simple interface: A way to start the custom ping, which itself sets up a (persistent) timer (firing every 24 hours).
When fired, &lt;code&gt;notify()&lt;/code&gt; will be called, which then collects the payload from &lt;code&gt;custom-store&lt;/code&gt; and schedule the ping for sending.
Telemetry will take care of actually sending the ping (and retrying, storing it in the archive, etc.).
For test reasons only we also send this ping when &lt;code&gt;start()&lt;/code&gt; is called (so we don&#39;t actually have to wait 24 hours to see something).&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;EXPORTED_SYMBOLS &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;TelemetryCustomPing&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;];
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;TelemetryCustomPing &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.freeze({
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;start&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    UpdateTimerManager.registerTimer(
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;telemetry_custom_ping&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color:#ed6a43;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;24 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;* &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;60 &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;* &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;60&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;/* 1 day */
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    );
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#ed6a43;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.sendPing();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;notify&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#ed6a43;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.sendPing();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  },
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#795da3;&quot;&gt;sendPing&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;() {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;// Let&amp;#39;s record just one more value, so _something_ is included.
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;randValue &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.floor(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.random() &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;* &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.floor(&lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;));
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Services&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.telemetry.scalarSet(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;browser.engagement.tick_times_rand&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, randValue);
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;// We only include the scalars, as that&amp;#39;s all we are recording for this ping.
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;payload &lt;/span&gt;&lt;span style=&quot;font-weight:bold;color:#a71d5d;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      custom: &lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;This is custom data&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      scalars: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;Services&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;.telemetry.getSnapshotForScalars(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;custom-store&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt;/* clear */ &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;),
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    };
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    TelemetryController.submitExternalPing(&lt;/span&gt;&lt;span style=&quot;color:#183691;&quot;&gt;&amp;quot;custom&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;, payload,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        addClientId: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;        addEnvironment: &lt;/span&gt;&lt;span style=&quot;color:#0086b3;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;      }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;    );
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;  }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;});
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we need to actually start the ping timer. This should be done in the initialization phase of &lt;code&gt;TelemetryController&lt;/code&gt;:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;background-color:#ffecec;font-weight:bold;font-style:italic;color:#bd2c00;&quot;&gt;---&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt; c/toolkit/components/telemetry/app/TelemetryController.jsm
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;font-style:italic;color:#55a532;&quot;&gt;+++&lt;/span&gt;&lt;span style=&quot;font-style:italic;color:#969896;&quot;&gt; i/toolkit/components/telemetry/app/TelemetryController.jsm
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;font-style:italic;color:#969896;&quot;&gt;@@ -62,6 +62,7 @@&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; XPCOMUtils.defineLazyModuleGetters(this, {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   TelemetryReportingPolicy: &amp;quot;resource://gre/modules/TelemetryReportingPolicy.jsm&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   TelemetryModules: &amp;quot;resource://gre/modules/ModulesPing.jsm&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   TelemetryUntrustedModulesPing: &amp;quot;resource://gre/modules/UntrustedModulesPing.jsm&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;  TelemetryCustomPing: &amp;quot;resource://gre/modules/CustomPing.jsm&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   UpdatePing: &amp;quot;resource://gre/modules/UpdatePing.jsm&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   TelemetryHealthPing: &amp;quot;resource://gre/modules/HealthPing.jsm&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;   TelemetryEventPing: &amp;quot;resource://gre/modules/EventPing.jsm&amp;quot;,
&lt;/span&gt;&lt;span style=&quot;font-weight:bold;font-style:italic;color:#969896;&quot;&gt;@@ -720,6 +721,9 @@&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt; var Impl = {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;           if (AppConstants.NIGHTLY_BUILD &amp;amp;&amp;amp; AppConstants.platform == &amp;quot;win&amp;quot;) {
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;             TelemetryUntrustedModulesPing.start();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;           }
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;          // Start the custom ping, which reports minimal information.
&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;font-weight:bold;color:#55a532;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color:#eaffea;color:#323232;&quot;&gt;          TelemetryCustomPing.start();
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;         }
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color:#323232;&quot;&gt;         TelemetryEventPing.startup();
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;But it&#39;s not measuring anything!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That is right, but for now we only record one value when sending the ping.&lt;/p&gt;
&lt;p&gt;And that&#39;s it! Our custom ping, with data sourced from a custom store and a release-shipped metric is ready&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
Let&#39;s build Firefox (this is the part where you have time to grab a cup of coffee if you haven&#39;t compiled Firefox before):&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;./mach build
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2 - 40 minutes later.&lt;/em&gt; Still with me?&lt;/p&gt;
&lt;p&gt;Now run the freshly built Firefox:&lt;/p&gt;
&lt;pre style=&quot;background-color:#ffffff;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#323232;&quot;&gt;./mach run
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once Telemetry is initialized (should take 60 seconds), you should be able to see the freshly generated custom ping (in a development build this ping is never actually send out).
To see it, go to &lt;code&gt;about:telemetry&lt;/code&gt;, click on &lt;code&gt;Current Ping&lt;/code&gt; in the upper-left corner, select &lt;code&gt;Archived ping data&lt;/code&gt; and then the &lt;code&gt;custom&lt;/code&gt; ping type. There you have it!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2019/about-telemetry-customping.png&quot; alt=&quot;Raw payload ouf the custom ping&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The full changeset is available &lt;a href=&quot;https://github.com/badboy/gecko-dev/commit/a872a3fa06be30667c0ac5fc47007780e8a9f6b0&quot;&gt;in this commit on the gecko-dev mirror&lt;/a&gt; (don&#39;t worry, this is not landing in Firefox).&lt;/p&gt;
&lt;h3&gt;What&#39;s next?&lt;/h3&gt;
&lt;p&gt;Currently there&#39;s no user of the multi-store feature, mainly because it was only finished in early December and is currently lacking some documentation (which this post should change a bit).
We expect some usage of this soon though.&lt;/p&gt;
&lt;hr /&gt;
&lt;hr&gt;&lt;p&gt;&lt;em&gt;Footnotes:&lt;/em&gt;&lt;/p&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;em&gt;Not entirely true. This needs some small changes to the build system.&lt;/em&gt; &lt;a href=&quot;#fr-1-1&quot; class=&quot;footnotes-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <guid>https://fnordig.de/2019/01/22/multi-store-custom-telemetry-with-shared-data</guid>
      <pubDate>Tue, 22 Jan 2019 10:00:00 +0100</pubDate>
    </item>
    <item>
      <title>What Rust is it?</title>
      <link>https://fnordig.de/2018/11/28/what-rust-is-it</link>
      <description>&lt;p&gt;A while ago (sometime in August) I built a small service called &lt;a href=&quot;http://www.whatrustisit.com/&quot;&gt;What Rust is it?&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://tmp.fnordig.de/blog/2018-11-28-what-rust-is-it.png&quot; alt=&quot;What Rust is it? - Screenshot of the website&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Based on what &lt;a href=&quot;http://whattrainisitnow.com/&quot;&gt;What Train is it now?&lt;/a&gt; is for Firefox, this small service lists the three trains of Rust: release, beta &amp;amp; nightly as well as their respective versions.
It&#39;s updated every day and actually checks what &lt;code&gt;rustup&lt;/code&gt; installed.
Additionally it shows the (planned) date of the next release.&lt;/p&gt;
&lt;p&gt;Similar information is available on the &lt;a href=&quot;https://forge.rust-lang.org/&quot;&gt;Rust Lang Forge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See it live:&lt;/p&gt;
&lt;center&gt;
## [www.whatrustisit.com](http://www.whatrustisit.com)
&lt;/center&gt;
</description>
      <guid>https://fnordig.de/2018/11/28/what-rust-is-it</guid>
      <pubDate>Wed, 28 Nov 2018 20:09:00 +0100</pubDate>
    </item>
    <item>
      <title>MozFest 2018: An inside perspective</title>
      <link>https://fnordig.de/2018/11/07/mozfest-2018-an-inside-perspective</link>
      <description>&lt;p&gt;It was the first time for me to attend MozFest, after I heard only good things about it from last year.
When I walked into the venue on Saturday morning, I immediately knew that this conference was a bit different than others I attended:
Spread over 9 floors, separated into different topic areas people from all sorts of backgrounds presented their work, project &amp;amp; ideas.
Fully unprepared and a bit overwhelmed I jumped into sessions discussing interplanetary communication tools, data journalism using satellite imagery or how and if we should preserve all digital content as historic artifacts in an ever-changing world.&lt;/p&gt;
&lt;p&gt;The one thing I enjoyed in all these sessions: Technology by itself was not considered as the solution to problems.
It might inform what solutions we built, what features we add or what data we track, but we also need to be critical of its implementations.
I definitely want to come back next year.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.mozilla.org/berlin/en/mozfest-2018-an-inside-perspective/&quot;&gt;MozFest 2018: An inside perspective on the Mozilla Berlin Blog&lt;/a&gt; (English article)&lt;br /&gt;
&lt;a href=&quot;https://blog.mozilla.org/berlin/so-wars-beim-mozfest-2018/&quot;&gt;So war&#39;s beim MozFest 2018&lt;/a&gt; (German version of the article)&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2018/11/07/mozfest-2018-an-inside-perspective</guid>
      <pubDate>Wed, 07 Nov 2018 14:34:00 +0100</pubDate>
    </item>
    <item>
      <title>How I made a useless tool and the reactions made my sunday better</title>
      <link>https://fnordig.de/2018/09/30/how-i-made-a-useless-tool-and-the-reactions-made-my-sunday-better</link>
      <description>&lt;p&gt;Last night I had an idea, which made me stay up two hours longer than I wanted.
I built a useless tool: &lt;a href=&quot;https://github.com/badboy/lysbilder/&quot;&gt;lysbilder&lt;/a&gt;, the slide system no one needed.&lt;/p&gt;
&lt;p&gt;Today I tweeted about it and then went out to enjoy the day a bit:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/badboy_/status/1046378708527976449&quot;&gt;@badboy_&lt;/a&gt;:
I might have built a very useless slideshow tool on top of rustdoc, generated from code documentation, linked by trait implementations.&lt;/p&gt;
&lt;p&gt;Please don’t use it¹.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://badboy.github.io/lysbilder/&quot;&gt;https://badboy.github.io/lysbilder/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;¹: however, I will use it once.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Quickly I got some responses:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/myriamjessier/status/1046382236013129729&quot;&gt;@myriamjessier&lt;/a&gt;:
I laughed. It was good enough to retweet just because of that.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/QuietMisdreavus/status/1046411069529477121&quot;&gt;@QuietMisdreavus&lt;/a&gt;:
i love this so much&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Those made me smile and made my sunday a bit better. :)&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2018/09/30/how-i-made-a-useless-tool-and-the-reactions-made-my-sunday-better</guid>
      <pubDate>Sun, 30 Sep 2018 23:00:00 +0200</pubDate>
    </item>
    <item>
      <title>A new job</title>
      <link>https://fnordig.de/2018/02/18/a-new-job</link>
      <description>&lt;p&gt;In September 2012 I was hired by &lt;a href=&quot;https://www.rrbone.net/&quot;&gt;rrbone&lt;/a&gt; to work as a software developer alongside my studies.
Over the last 5 years I worked on multiple projects, some internal tools, some external work with and for clients
and was also allowed to consult customers on-site or give Rust trainings.
In addition, rrbone covered some of my conference visits, became the &lt;a href=&quot;https://otsconf.com/#sponsors&quot;&gt;main sponsor&lt;/a&gt; of otsconf, the first conference I organized,
and allowed me to attend other events under sponsorships.
Together we built networks for &lt;a href=&quot;http://juicybeats.net/de&quot;&gt;large festivals&lt;/a&gt;, &lt;a href=&quot;http://2014.railscamp.de/sponsors/&quot;&gt;small unconferences&lt;/a&gt; and &lt;a href=&quot;https://ruhrjs.de/&quot;&gt;other community conferences&lt;/a&gt;.
I was allowed to write Rust code for an opera play and &lt;a href=&quot;https://github.com/rrbone/midioscar&quot;&gt;open-source it&lt;/a&gt;,
attended &lt;a href=&quot;https://www.instagram.com/p/vM70WwStE1/&quot;&gt;IETF 91 in Honolulu, Hawaii&lt;/a&gt;, and learned a ton about networks and how the internet works (sometimes it doesn&#39;t).
All of that while I was still studying.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For all of this I am very grateful.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thanks &lt;a href=&quot;https://twitter.com/dominikbay&quot;&gt;Dominik&lt;/a&gt;, for being my boss and friend for such a long time and for all the things I could learn.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;But now after five years it is time for new challenges.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I will join Mozilla as a Firefox Telemetry Engineer, starting next Month.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Back in 2015 I met &lt;a href=&quot;https://twitter.com/slsoftworks&quot;&gt;Flaki&lt;/a&gt;,
who later pushed me to &lt;a href=&quot;https://www.youtube.com/watch?v=L9sTIi7wFPo&quot;&gt;give my very first conference talk&lt;/a&gt;.
Shortly after that he introduced me to the &lt;a href=&quot;https://wiki.mozilla.org/TechSpeakers&quot;&gt;Mozilla Tech Speaker&lt;/a&gt; program.
Not soon after I became a Tech Speaker, attended conferences and meetups as a speaker and worked closer with Mozilla.
Since then I met a lot of people working at or with Mozilla, some of who I consider friends by now.&lt;/p&gt;
&lt;p&gt;When I finished university last year some of the same people pushed me to apply at Mozilla,
especially &lt;a href=&quot;https://twitter.com/misprintedtype&quot;&gt;Ola&lt;/a&gt;.
I did and today I can announce that it paid off and they hired me.
Taking this new job also means I will move to Berlin soon.&lt;/p&gt;
&lt;p&gt;As a Telemetry Engineer I will work on improving the quality of Firefox and help different teams to instrument new features in Firefox.
I&#39;m incredibly excited to work on this project together with folks from whom I can learn a thing or two (probably a lot more).&lt;/p&gt;
</description>
      <guid>https://fnordig.de/2018/02/18/a-new-job</guid>
      <pubDate>Sun, 18 Feb 2018 16:00:00 +0100</pubDate>
    </item>
    
  </channel>
</rss>
