<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/atom-style.xml"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>Hauleth&#x27;s blog</title>
    <subtitle>Blog about BEAM, Rust, fantasy &amp; stuff</subtitle>
  <link href="https://hauleth.dev/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="https://hauleth.dev/" rel="related"/>
  <generator uri="https://www.getzola.org/">Zola</generator>
  <updated>2025-07-28T00:00:00+00:00</updated>
  <id>https://hauleth.dev/atom.xml</id>
    <entry xml:lang="en">
      <title>Jeopardy! world</title>
      <published>2025-07-28T00:00:00+00:00</published>
      <updated>2025-07-28T00:00:00+00:00</updated>
      <link href="https://hauleth.dev/post/jeopardy-world/" type="text/html"/>
      <id>https://hauleth.dev/post/jeopardy-world/</id>
      <summary><p>Some time ago, there was an anime available on Netflix — <em>Godzilla Singular
Point</em>. It wasn't a spectacular success, but it featured a plot device that I
think reflects something increasingly common today: you need to know the answer
to your question before you can ask it.</p>
<p>This is something I see all the time in the current wave of AI hype. You need to
know what the answer <em>should</em> be before you can write a useful prompt.</p></summary>
      <content type="html">&lt;p&gt;Some time ago, there was an anime available on Netflix — &lt;em&gt;Godzilla Singular
Point&lt;&#x2F;em&gt;. It wasn&#x27;t a spectacular success, but it featured a plot device that I
think reflects something increasingly common today: you need to know the answer
to your question before you can ask it.&lt;&#x2F;p&gt;
&lt;p&gt;This is something I see all the time in the current wave of AI hype. You need to
know what the answer &lt;em&gt;should&lt;&#x2F;em&gt; be before you can write a useful prompt.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;The issue I have with many AI use cases is this: unless you have specialized
knowledge about the topic you&#x27;re asking about, you can&#x27;t reliably tell the
difference between a solid AI answer and complete nonsense.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve had a few discussions about this on various Discord servers. The example I
often use is this simple question posed to an AI:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Does 6 character long identification number, that contains digits and upper
case letters (with exception to 0, O, 1, I, and L) is enough to randomly
assign unique identification numbers for 10 million records?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;You can see for your self answer from ChatGPT &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;chatgpt.com&#x2F;share&#x2F;68879fe7-d4e0-8007-9a30-3a9e2ace791d&quot;&gt;there&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;At first glance, the answer looks valid and sensible. The math checks out. It
calculates the number of available combinations correctly. Everything seems
&lt;em&gt;fine&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;BUT…&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There is huge issue there, and probably most of the people who have been working
with basic statistic or cryptography will notice it. ChatGPT (and any other AI
that I have tested out) fail to notice very important word there&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;[…] randomly […]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This single word invalidates the entire reasoning, despite the correct
calculations. Because of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Birthday_problem&quot;&gt;birthday problem&lt;&#x2F;a&gt;, the answer isn&#x27;t feasible.
While it&#x27;s technically possible to assign a unique ID to every record, doing so
randomly introduces a high probability of collisions.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;At around 35,000 generated IDs, there&#x27;s already a 50% chance of a collision&lt;&#x2F;li&gt;
&lt;li&gt;At around 90,000, the chance of at least one duplicate reaches 99%&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So even though the math is correct, the logic fails under the randomness constraint.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jeopardy-world&quot;&gt;&lt;em&gt;Jeopardy!&lt;&#x2F;em&gt; world&lt;a class=&quot;zola-anchor&quot; href=&quot;#jeopardy-world&quot; aria-label=&quot;Anchor link for: jeopardy-world&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This is my main issue with AI tools: if you already have knowledge about the
subject, you don’t really need to ask the AI. But if you don’t have that
knowledge, you have no reliable way of knowing whether the answer makes sense or
not. It’s like playing &lt;em&gt;Jeopardy!&lt;&#x2F;em&gt; — you need to know the answer before you can
phrase the right question.&lt;&#x2F;p&gt;
&lt;p&gt;In my view, AI is most useful in areas where the results can be quickly reviewed
and discarded if needed. That’s why the whole “vibe coding” (aka slop
generation) approach falls short. If you don’t have a good sense of what the
output should look like, you probably don’t have the expertise to verify it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.businessinsider.com&#x2F;replit-ceo-apologizes-ai-coding-tool-delete-company-database-2025-7?op=1&quot;&gt;And gods forbid you from allowing AI to do anything on production&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>Who Watches Watchmen? - Part 2</title>
      <published>2023-11-14T00:00:00+00:00</published>
      <updated>2023-11-14T00:00:00+00:00</updated>
      <link href="https://hauleth.dev/post/who-watches-watchmen-ii/" type="text/html"/>
      <id>https://hauleth.dev/post/who-watches-watchmen-ii/</id>
      <summary>Continuation of travel into making systemd to work for us, not against us. This
time we will talk about socket activation and how to make our application run
only when we need it to run.
</summary>
      <content type="html">&lt;p&gt;This is continuation of &lt;a href=&quot;https:&#x2F;&#x2F;hauleth.dev&#x2F;post&#x2F;who-watches-watchmen-i&#x2F;&quot;&gt;Part I&lt;&#x2F;a&gt; where I described the basics of the
supervising BEAM applications with systemd and how to create basic, secure
service for your Elixir application with it. In this article I will assume that
you have read &lt;a href=&quot;https:&#x2F;&#x2F;hauleth.dev&#x2F;post&#x2F;who-watches-watchmen-i&#x2F;&quot;&gt;the previous one&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;We already have our super simple service description. Just to refresh your
memory, it is the &lt;code&gt;hello.service&lt;&#x2F;code&gt; file once again:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Hello World service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Requires&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;network.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;notify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;opt&#x2F;hello&#x2F;bin&#x2F;hello start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WatchdogSec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;1min&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# We need to add capability to be able to bind on port 80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CapabilityBoundingSet&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;CAP_NET_BIND_SERVICE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# Hardening&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DynamicUser&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;PrivateDevices&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ERL_CRASH_DUMP_SECONDS&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However there is one small problem. It allows our service to listen on &lt;strong&gt;any&lt;&#x2F;strong&gt;
restricted port, not just &lt;code&gt;80&lt;&#x2F;code&gt; that we want to listen on. This can be
troublesome as an attacker that gains RCE on our server can then capture any
traffic on any port that we do not want to open (for example exposing port 22
using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;man&#x2F;ssh.html&quot;&gt;&lt;code&gt;ssh&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; module).&lt;&#x2F;p&gt;
&lt;p&gt;It would be nice if we could somehow inject sockets for only the ports we want
to listen to into our application.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;socket-passing&quot;&gt;Socket passing&lt;a class=&quot;zola-anchor&quot; href=&quot;#socket-passing&quot; aria-label=&quot;Anchor link for: socket-passing&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Thanks to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freedesktop.org&#x2F;software&#x2F;systemd&#x2F;man&#x2F;systemd.socket.html&quot;&gt;&lt;code&gt;systemd.socket&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; feature we can achieve that
with a little work on our side.&lt;&#x2F;p&gt;
&lt;p&gt;First we need to create new unit named &lt;code&gt;hello.socket&lt;&#x2F;code&gt; next to our
&lt;code&gt;hello.service&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Listening socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Requires&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;sockets.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Socket&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ListenStream&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BindIPv6Only&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;both&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ReusePort&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;NoDelay&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It will create a socket connected to TCP 80 (because we used &lt;code&gt;ListenStream=&lt;&#x2F;code&gt;,
and TCP is the stream protocol). By default it will bind that socket to a
service named the same as our socket, so now we need to edit our &lt;code&gt;hello.service&lt;&#x2F;code&gt;
a little bit:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Hello World service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Requires&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;network.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;notify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;opt&#x2F;hello&#x2F;bin&#x2F;hello start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WatchdogSec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;1min&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# See, we no longer need to insecurely allow binding to any port&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# CapabilityBoundingSet=CAP_NET_BIND_SERVICE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# Hardening&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DynamicUser&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;PrivateDevices&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ERL_CRASH_DUMP_SECONDS&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And we need to modify our &lt;code&gt;Hello.Application.cowboy_opts&#x2F;0&lt;&#x2F;code&gt; to handle the socket
which is passed to us a file descriptor:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# hello&#x2F;application.ex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Application&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Application&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    fds &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt; :systemd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;listen_fds&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    children &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, [&lt;&#x2F;span&gt;&lt;span&gt;scheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;http&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fds&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;)},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Drainer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; refs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;    Supervisor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;start_link&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;children&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; strategy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;one_for_one&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  # If there are no sockets passed to the application, then start listening on&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  # the port specified by the `PORT` environment variable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;([])&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    [&lt;&#x2F;span&gt;&lt;span&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;System&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get_env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;5000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;))]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  # If there are any socket passed, then use first one&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;([&lt;&#x2F;span&gt;&lt;span&gt;socket &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;])&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    fd &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;      case&lt;&#x2F;span&gt;&lt;span&gt; socket &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        # Sockets can be named, which will be passed as the second element in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        # a tuple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;        {&lt;&#x2F;span&gt;&lt;span&gt;fd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; fd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        # Or unnamed, and then it will be just the file descriptor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        fd &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; fd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;      end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      net&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;inet6&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; # (1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;     # (2)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      fd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; fd       &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# (3)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;Systemd sockets are IPv6 enabled (we explicitly said that we want to listen
on both). That means, that we need to mark our connection as an INET6
connection. This will not affect IPv4 (INET) connections.&lt;&#x2F;li&gt;
&lt;li&gt;We are required to pass &lt;code&gt;:port&lt;&#x2F;code&gt; key, but its value will be ignored, so we
just pass &lt;code&gt;0&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We pass the file descriptor that will be then passed to the Cowboy listener.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Now when we will start our service:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# systemctl start hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It will be available at &lt;code&gt;https:&#x2F;&#x2F;localhost&#x2F;&lt;&#x2F;code&gt; while still running as an
unprivileged user.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;multiple-ports&quot;&gt;Multiple ports&lt;a class=&quot;zola-anchor&quot; href=&quot;#multiple-ports&quot; aria-label=&quot;Anchor link for: multiple-ports&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The question may arise - how to allow our service to listen on more than one
port, for example you want to have your website available as HTTPS alongside
&quot;regular&quot; HTTP. This means that our application needs to listen on two
restricted ports:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;80 - for HTTP&lt;&#x2F;li&gt;
&lt;li&gt;443 - for HTTPS&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now we need to slightly modify a little our socket service and add another one.
First rename our &lt;code&gt;hello.socket&lt;&#x2F;code&gt; to &lt;code&gt;hello-http.socket&lt;&#x2F;code&gt; and add a line
&lt;code&gt;Service=hello.service&lt;&#x2F;code&gt; and &lt;code&gt;FileDescriptorName=http&lt;&#x2F;code&gt; to &lt;code&gt;[Socket]&lt;&#x2F;code&gt; section, so
we end with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;HTTP Socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Requires&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;sockets.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Socket&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# We declare the name of the file descriptor here to simplify extraction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# in the application afterwards. By default it will be the socket name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# (so `hello-http` in our case), but `http` is much cleaner.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FileDescriptorName&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;http&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ListenStream&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BindIPv6Only&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;both&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ReusePort&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;NoDelay&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next we create a similar file, but for HTTPS named &lt;code&gt;hello-https.socket&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;HTTPS Socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Requires&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;sockets.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Socket&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FileDescriptorName&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;https&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ListenStream&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;443&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BindIPv6Only&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;both&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ReusePort&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;NoDelay&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And we add the dependency on both of our sockets to the &lt;code&gt;hello.service&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Hello World service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;After&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hello-http.socket hello-https.socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;BindTo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;hello-http.socket hello-https.socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;opt&#x2F;hello&#x2F;bin&#x2F;hello start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# Hardening&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DynamicUser&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;PrivateDevices&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ERL_CRASH_DUMB_SECONDS&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we need to somehow differentiate between our sockets in the
&lt;code&gt;Hello.Application&lt;&#x2F;code&gt;, so we will be able to pass the proper FD to each of the
listeners. The &lt;code&gt;:systemd.listen_fds&#x2F;0&lt;&#x2F;code&gt; will return a list of file descriptors,
and if they are named, the format will be a 2-tuple where the first element is
the file descriptor and the second is the name as a string:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# hello&#x2F;application.ex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Application&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Application&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    fds &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt; :systemd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;listen_fds&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    router &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Router&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    children &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        scheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;http&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; router&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      ]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fds&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;http&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;)},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        scheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;https&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; router&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        keyfile&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;path&#x2F;to&#x2F;keyfile.pem&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        certfile&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;path&#x2F;to&#x2F;certfile.pem&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        dhfile&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;path&#x2F;to&#x2F;dhfile.pem&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      ]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fds&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;)},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Drainer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; refs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;    Supervisor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;start_link&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;children&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; strategy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;one_for_one&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fds&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    case&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; List&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;keyfind&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;fds&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      # If there is socket passed for given protocol, then use that one&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span&gt;fd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ^protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;        [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          net&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;inet6&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          fd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; fd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;        ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      # If there are no sockets passed to the application that match&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      # the protocol, then start listening on the port specified by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      # `PORT_{protocol}` environment variable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;      _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;        [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;System&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get_env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;PORT_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded z-begin&quot;&gt;#{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded z-end&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;5000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;        ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now our application will listen on both - HTTP and HTTPS, despite running as
unprivileged user.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;socket-activation&quot;&gt;Socket activation&lt;a class=&quot;zola-anchor&quot; href=&quot;#socket-activation&quot; aria-label=&quot;Anchor link for: socket-activation&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Now, that we can inject sockets to our application with ease we can achieve even
more fascinating feature - socket activation.&lt;&#x2F;p&gt;
&lt;p&gt;Some of you may used &lt;code&gt;inetd&lt;&#x2F;code&gt; in the past, that allows you to dynamically start
processes on network requests. It is quite an interesting tool that detects
traffic on certain ports, then spawns a new process to handle it, passing data
to and from that process via &lt;code&gt;STDIN&lt;&#x2F;code&gt; and &lt;code&gt;STDOUT&lt;&#x2F;code&gt;. There was a quirk though, it
required the spawned process to shutdown after it handled the request and it was
starting a new instance for each request. That works poorly with VMs like BEAM
that have substantial startup time and are expected to be long-running systems.
BEAM is capable of handling network requests on it&#x27;s own.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately for us, the way that we have implemented our systemd service is all
that we need to have our application dynamically activated. To observe that we
just need to shutdown everything:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# systemctl stop hello-http.socket hello-https.socket hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And now relaunch &lt;strong&gt;only the sockets&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# systemctl start hello-http.socket hello-https.socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can check, that our service is not running:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ systemctl status hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;● hello.service - Hello World service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Loaded: loaded (&#x2F;usr&#x2F;local&#x2F;lib&#x2F;systemd&#x2F;system&#x2F;hello.service; static; vendor preset: enabled)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Active: inactive (dead)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;TriggeredBy: ● hello-http.socket ● hello-https.socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can see the &lt;code&gt;TriggeredBy&lt;&#x2F;code&gt; section that tells us, that this service will be
started by one of the sockets listed there. Let see what will happen when we
will try to request anything from our application:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ curl http:&#x2F;&#x2F;localhost&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Hello World!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can see that we got a response from our application. This mean that our
application must have started, and indeed when we check:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ systemctl status hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;● hello.service - Hello&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Loaded: loaded (&#x2F;usr&#x2F;local&#x2F;lib&#x2F;systemd&#x2F;system&#x2F;hello.service; static; vendor preset: enabled)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Active: active (running) since Thu 2022-02-03 13:20:27 CET; 4s ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;TriggeredBy: ● hello-http.socket ● hello-https.socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   Main PID: 1106 (beam.smp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      Tasks: 19 (limit: 1136)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Memory: 116.7M&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     CGroup: &#x2F;system.slice&#x2F;hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             ├─1106 &#x2F;opt&#x2F;hello&#x2F;erts-12.2&#x2F;bin&#x2F;beam.smp -- -root &#x2F;opt&#x2F;hello -progname erl -- -home &#x2F;run&#x2F;hello -- -noshell -s elixir start_cli -mode embedded -setcookie CR63SVI6L5JAMJSDL3H4XPNMOPHEWSV2FPHCHCAN65CY6ASHMXBA==== -sname hello -c&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             └─1138 erl_child_setup 1024&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It seems to be running, and if we stop it, then we will get information that it
still can be activated by our sockets:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# systemctl stop hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Warning: Stopping hello.service, but it can still be activated by:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  hello-http.socket hello-https.socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That means, that systemd is still listening on the sockets that we defined, even
when our application is down, and will start our application again as soon as
there are any incoming requests.&lt;&#x2F;p&gt;
&lt;p&gt;Let test that out again:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ curl http:&#x2F;&#x2F;localhost&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Hello World!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ systemctl status hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;● hello.service - Hello&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Loaded: loaded (&#x2F;usr&#x2F;local&#x2F;lib&#x2F;systemd&#x2F;system&#x2F;hello.service; static; vendor preset: enabled)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Active: active (running) since Thu 2022-02-03 13:22:27 CET; 4s ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;TriggeredBy: ● hello-http.socket ● hello-https.socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   Main PID: 3452 (beam.smp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      Tasks: 19 (limit: 1136)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Memory: 116.7M&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     CGroup: &#x2F;system.slice&#x2F;hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             ├─3452 &#x2F;opt&#x2F;hello&#x2F;erts-12.2&#x2F;bin&#x2F;beam.smp -- -root &#x2F;opt&#x2F;hello -progname erl -- -home &#x2F;run&#x2F;hello -- -noshell -s elixir start_cli -mode embedded -setcookie CR63SVI6L5JAMJSDL3H4XPNMOPHEWSV2FPHCHCAN65CY6ASHMXBA==== -sname hello -c&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             └─3453 erl_child_setup 1024&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our application got launched again, automatically, just by the fact that
there was incoming TCP connection.&lt;&#x2F;p&gt;
&lt;p&gt;Does it work for HTTPS connection as well?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# systemctl stop hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ curl -k https:&#x2F;&#x2F;localhost&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Hello World!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It seems so. Independently of which port we try to reach our application on, it
will be automatically launched for us and the connection will be properly
handled. Do note that systemd will not shut down our process after serving the
request. It will continue to run from that point forward.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;I know that it took quite while since the last post (ca. 1.5 years), but I hope
that I will be able to write the final part much sooner than this.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hauleth.dev&#x2F;post&#x2F;who-watches-watchmen-i&#x2F;&quot;&gt;Part 1 - Basics, security, and FD passing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hauleth.dev&#x2F;post&#x2F;who-watches-watchmen-ii&#x2F;.&#x2F;#top&quot;&gt;Part 2 - Socket activation (this one)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Part 3 - Logging&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>How much memory is needed to run 1M Erlang processes?</title>
      <published>2023-06-10T00:00:00+00:00</published>
      <updated>2023-06-10T00:00:00+00:00</updated>
      <link href="https://hauleth.dev/post/beam-process-memory-usage/" type="text/html"/>
      <id>https://hauleth.dev/post/beam-process-memory-usage/</id>
      <summary>How to not write benchmarks</summary>
      <content type="html">&lt;p&gt;Recently &lt;a rel=&quot;external&quot; title=&quot;How Much Memory Do You Need to Run 1 Million Concurrent Tasks?&quot; href=&quot;https:&#x2F;&#x2F;pkolaczk.github.io&#x2F;memory-consumption-of-async&#x2F;&quot;&gt;benchmark for concurrency implementation in different
languages&lt;&#x2F;a&gt;. In this article &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pkolaczk&quot;&gt;Piotr Kołaczkowski&lt;&#x2F;a&gt; used Chat GPT to
generate the examples in the different languages and benchmarked them. This was
poor choice as I have found this article and read the Elixir example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tasks &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;num_tasks &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;        Task&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;fn -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;            :timer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Task&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;await_many&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;infinity&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And, well, it&#x27;s pretty poor example of BEAM&#x27;s process memory usage, and I am
not talking about the fact that it uses 4 spaces for indentation.&lt;&#x2F;p&gt;
&lt;p&gt;For 1 million processes this code reported 3.94 GiB of memory used by the process
in Piotr&#x27;s benchmark, but with little work I managed to reduce it about 4 times
to around 0.93 GiB of RAM usage. In this article I will describe:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;how I did that&lt;&#x2F;li&gt;
&lt;li&gt;why the original code was consuming so much memory&lt;&#x2F;li&gt;
&lt;li&gt;why in the real world you probably should not optimise like I did here&lt;&#x2F;li&gt;
&lt;li&gt;why using ChatGPT to write benchmarking code sucks (TL;DR because that will
nerd snipe people like me)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;what-are-erlang-processes&quot;&gt;What are Erlang processes?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-are-erlang-processes&quot; aria-label=&quot;Anchor link for: what-are-erlang-processes&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Erlang is &lt;del&gt;well&lt;&#x2F;del&gt; known of being language which support for concurrency is
superb, and Erlang processes are the main reason for that. But what are these?&lt;&#x2F;p&gt;
&lt;p&gt;In Erlang &lt;em&gt;process&lt;&#x2F;em&gt; is the common name for what other languages call &lt;em&gt;virtual
threads&lt;&#x2F;em&gt; or &lt;em&gt;green threads&lt;&#x2F;em&gt;, but in Erlang these have small neat twist - each of
the process is isolated from the rest and these processes can communicate only
via message passing. That gives Erlang processes 2 features that are rarely
spotted in other implementations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Failure isolation - bug, unhandled case, or other issue in single process will
not directly affect any other process in the system. VM can send some messages
due to process shutdown, and other processes may be killed because of that,
but by itself shutting down single process will not cause problems in any
process not related to that.&lt;&#x2F;li&gt;
&lt;li&gt;Location transparency - process can be spawned locally or on different
machine, but from the viewpoint of the programmer, there is no difference.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The above features and requirements results in some design choices, but for our
purpose only one is truly needed today - each process have separate and (almost)
independent memory stack from any other process.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;process-dictionary&quot;&gt;Process dictionary&lt;a class=&quot;zola-anchor&quot; href=&quot;#process-dictionary&quot; aria-label=&quot;Anchor link for: process-dictionary&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Each process in Erlang VM has dedicated &lt;em&gt;mutable&lt;&#x2F;em&gt; memory space for their
internal uses. Most people do not use it for anything because in general it
should not be used unless you know exactly what you are doing (in my case, a bad
carpenter could count cases when I needed it, on single hand). In general it&#x27;s
&lt;em&gt;here be dragons&lt;&#x2F;em&gt; area.&lt;&#x2F;p&gt;
&lt;p&gt;How it&#x27;s relevant to us?&lt;&#x2F;p&gt;
&lt;p&gt;Well, OTP internally uses process dictionary (&lt;code&gt;pdict&lt;&#x2F;code&gt; for short) to store
metadata about given process that can be later used for debugging purposes. Some
data that it store are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Initial function that was run by the given process&lt;&#x2F;li&gt;
&lt;li&gt;PIDs to all ancestors of the given process&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Different processes abstractions (like &lt;code&gt;gen_server&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;GenServer&lt;&#x2F;code&gt;, Elixir&#x27;s
&lt;code&gt;Task&lt;&#x2F;code&gt;, etc.) can store even more metadata there, &lt;code&gt;logger&lt;&#x2F;code&gt; store process
metadata in process dictionary, &lt;code&gt;rand&lt;&#x2F;code&gt; store state of the PRNGs in the process
dictionary. it&#x27;s used quite extensively by some OTP features.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;well-behaved-otp-process&quot;&gt;&quot;Well behaved&quot; OTP process&lt;a class=&quot;zola-anchor&quot; href=&quot;#well-behaved-otp-process&quot; aria-label=&quot;Anchor link for: well-behaved-otp-process&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;In addition to the above metadata if the process is meant to be &quot;well behaved&quot;
process in OTP system, i.e. process that can be observed and debugged using OTP
facilities, it must respond to some additional messages defined by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;man&#x2F;sys.html&quot;&gt;&lt;code&gt;sys&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
module. Without that the features like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;man&#x2F;observer.html&quot;&gt;&lt;code&gt;observer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; would not be able to &quot;see&quot;
the content of the process state.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;process-memory-usage&quot;&gt;Process memory usage&lt;a class=&quot;zola-anchor&quot; href=&quot;#process-memory-usage&quot; aria-label=&quot;Anchor link for: process-memory-usage&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;As we have seen above, the &lt;code&gt;Task.async&#x2F;1&lt;&#x2F;code&gt; function form Elixir &lt;strong&gt;must&lt;&#x2F;strong&gt; do
much more than just simple &quot;start process and live with it&quot;. That was one of the
most important problems with the original process, it was using system, that was
allocating quite substantial memory alongside of the process itself, just to
operate this process. In general, that would be desirable approach (as you
&lt;strong&gt;really, really, want the debugging facilities&lt;&#x2F;strong&gt;), but in synthetic benchmarks,
it reduce the feasibility of such benchmark.&lt;&#x2F;p&gt;
&lt;p&gt;If we want to avoid that additional memory overhead in our spawned processes we
need to go back to more primitive functions in Erlang, namely &lt;code&gt;erlang:spawn&#x2F;1&lt;&#x2F;code&gt;
(&lt;code&gt;Kernel.spawn&#x2F;1&lt;&#x2F;code&gt; in Elixir). But that mean that we cannot use
&lt;code&gt;Task.await_many&#x2F;2&lt;&#x2F;code&gt; anymore, so we need to workaround it by using custom
function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; when&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; is_pid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    # Monitor is internal feature of Erlang that will inform you (by sending&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    # message) when process you monitor die. The returned value is type called&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    # &amp;quot;reference&amp;quot; which is just simply unique value returned by the VM.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    # If the process is already dead, then message will be delivered&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    # immediately.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ref &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;monitor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    receive do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;DOWN&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ^ref&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;ok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await_many&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pids&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;    Enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;each&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pids&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; &amp;amp;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tasks &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;num_tasks &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    # `Kernel` module is imported by default, so no need for `Kernel.` prefix&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    spawn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;fn -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;      :timer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;await_many&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We already removed one problem (well, two in fact, but we will go into
details in next section).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;all-your-lists-are-belongs-to-us-now&quot;&gt;All your lists are belongs to us now&lt;a class=&quot;zola-anchor&quot; href=&quot;#all-your-lists-are-belongs-to-us-now&quot; aria-label=&quot;Anchor link for: all-your-lists-are-belongs-to-us-now&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Erlang, like most of the functional programming languages, have 2 built-in
sequence types:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Tuples - which are non-growable product type of the values, so you can access
any field quite fast, but adding more values is performance no-no&lt;&#x2F;li&gt;
&lt;li&gt;(Singly) linked lists - growable type (in most case it will have single type
values in it, but in Erlang that is not always the case), which is fast to
prepend or pop data from the beginning, but do not try to do anything else if
you care about performance.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In this case we will focus on the 2nd one, as there tuples aren&#x27;t important at
all.&lt;&#x2F;p&gt;
&lt;p&gt;Singly linked list is simple data structure. It&#x27;s either special value &lt;code&gt;[]&lt;&#x2F;code&gt;
(an empty list) or it&#x27;s something called &quot;cons-cell&quot;. Cons-cells are also
simple structures - it&#x27;s 2ary tuple (tuple with 2 elements) where first value
is head - the value in the list cell, and another one is the &quot;tail&quot; of the list (aka
rest of the list). In Elixir the cons-cell is denoted like that &lt;code&gt;[head | tail]&lt;&#x2F;code&gt;.
Super simple structure as you can see, and perfect for the functional
programming as you can add new values to the list without modifying existing
values, so you can be immutable and fast. However if you need to construct the
sequence of a lot of values (like our list of all tasks) then we have problem.
Because Elixir promises that list returned from the &lt;code&gt;for&lt;&#x2F;code&gt; will be &lt;strong&gt;in-order&lt;&#x2F;strong&gt;
of the values passed to it. That mean that we either need to process our data
like that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;([],&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; do:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; []&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;([&lt;&#x2F;span&gt;&lt;span&gt;head &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; tail&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; func&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;  [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;.(&lt;&#x2F;span&gt;&lt;span&gt;head&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tail&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; func&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where we build call stack (as we cannot have tail call optimisation there, of
course sans compiler optimisations). Or we need to build our list in reverse
order, and then reverse it before returning (so we can have TCO):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;list&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; func&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; do:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; do_map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;list&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; func&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, [])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;([],&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _func&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; do:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt; :lists&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;reverse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;([&lt;&#x2F;span&gt;&lt;span&gt;head &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; tail&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; func&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tail&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; func&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;.(&lt;&#x2F;span&gt;&lt;span&gt;head&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which one of these approaches is more performant is irrelevant&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#erlang-perf&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,
what is relevant is that we need either build call stack or construct our list
&lt;em&gt;twice&lt;&#x2F;em&gt; to be able to conform to the Elixir promises (even if in this case we do
not care about order of the list returned by the &lt;code&gt;for&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;erlang-perf&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Sometimes body recursion will be faster, sometimes TCO will be
faster. it&#x27;s impossible to tell without more benchmarking. For more info check
out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ferd.ca&#x2F;erlang-s-tail-recursion-is-not-a-silver-bullet.html&quot;&gt;superb article by Ferd Herbert&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Of course we could mitigate our problem by using &lt;code&gt;Enum.reduce&#x2F;3&lt;&#x2F;code&gt; function (or
writing it on our own) and end with code like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; when&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; is_pid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ref &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;monitor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    receive do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;DOWN&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ^ref&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;ok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await_many&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pids&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;    Enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;each&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pids&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; &amp;amp;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tasks &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;  Enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;reduce&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;num_tasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, [],&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; agg &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    # `Kernel` module is imported by default, so no need for `Kernel.` prefix&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    pid &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;      spawn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;fn -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt; :timer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    [&lt;&#x2F;span&gt;&lt;span&gt;pid &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;await_many&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Even then we build list of all PIDs.&lt;&#x2F;p&gt;
&lt;p&gt;Here I can also go back to the &quot;second problem* I have mentioned above.
&lt;code&gt;Task.await_many&#x2F;1&lt;&#x2F;code&gt; &lt;em&gt;also construct a list&lt;&#x2F;em&gt;. it&#x27;s list of return value from all
the processes in the list, so not only we constructed list for the tasks&#x27; PIDs,
we also constructed list of return values (which will be &lt;code&gt;:ok&lt;&#x2F;code&gt; for all processes
as it&#x27;s what &lt;code&gt;:timer.sleep&#x2F;1&lt;&#x2F;code&gt; returns), and immediately discarded all of that.&lt;&#x2F;p&gt;
&lt;p&gt;How we can better? See that &lt;strong&gt;all&lt;&#x2F;strong&gt; we care is that all &lt;code&gt;num_task&lt;&#x2F;code&gt; processes
have gone down. We do not care about any of the return values, all what we want
is to know that all processes that we started went down. For that we can just
send messages from the spawned processes and count the received messages count:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; worker&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;parent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;    :timer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    send&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;parent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; do:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;ok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; when&lt;&#x2F;span&gt;&lt;span&gt; n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    this &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    spawn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;fn -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; worker&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; do:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;ok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; when&lt;&#x2F;span&gt;&lt;span&gt; n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    receive do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;      :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;num_tasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;num_tasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we do not have any lists involved and we still do what the original task
meant to do - spawn &lt;code&gt;num_tasks&lt;&#x2F;code&gt; processes and wait till all go down.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;arguments-copying&quot;&gt;Arguments copying&lt;a class=&quot;zola-anchor&quot; href=&quot;#arguments-copying&quot; aria-label=&quot;Anchor link for: arguments-copying&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;One another thing that we can account there - lambda context and data passing
between processes.&lt;&#x2F;p&gt;
&lt;p&gt;You see, we need to pass &lt;code&gt;this&lt;&#x2F;code&gt; (which is PID of the parent) to our newly
spawned process. That is suboptimal, as we are looking for the way to reduce
amount of the memory (and ignore all other metrics at the same time). As Erlang
processes are meant to be &quot;share nothing&quot; type of processes there is problem -
we need to copy that PID to all processes. it&#x27;s just 1 word (which mean 8 bytes
on 64-bit architectures, 4 bytes on 32-bit), but hey, we are microbenchmarking,
so we cut whatever we can (with 1M processes, this adds up to 8 MiBs).&lt;&#x2F;p&gt;
&lt;p&gt;Hey, we can avoid that by using yet another feature of Erlang, called
&lt;em&gt;registry&lt;&#x2F;em&gt;. This is yet another simple feature that allows us to assign PID of
the process to the atom, which allows us then to send messages to that process
using just name, we have given. While atoms are also 1 word that wouldn&#x27;t make
sense to send it as well, but instead we can do what any reasonable
microbenchmarker would do - &lt;em&gt;hardcode stuff&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; worker&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;    :timer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    send&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;parent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; do:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;ok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; when&lt;&#x2F;span&gt;&lt;span&gt; n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    spawn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;fn -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; worker&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;()&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; do:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;ok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; when&lt;&#x2F;span&gt;&lt;span&gt; n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    receive do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;      :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;register&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;parent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;num_tasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;num_tasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we do not pass any arguments, and instead rely on the registry to dispatch
our messages to respective processes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;one-more-thing&quot;&gt;One more thing&lt;a class=&quot;zola-anchor&quot; href=&quot;#one-more-thing&quot; aria-label=&quot;Anchor link for: one-more-thing&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;As you may have already noticed we are passing lambda to the &lt;code&gt;spawn&#x2F;1&lt;&#x2F;code&gt;. That is
also quite suboptimal, because of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.erlang.org&#x2F;doc&#x2F;reference_manual&#x2F;code_loading.html#code-replacement&quot;&gt;difference between remote and local call&lt;&#x2F;a&gt;.
This mean that we are paying slight memory cost for these processes to keep the
old module in memory. Instead we can use either fully qualified function capture
or &lt;code&gt;spawn&#x2F;3&lt;&#x2F;code&gt; function that accepts MFA (module, function name, arguments list)
argument. We end with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; worker&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;    :timer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    send&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;parent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; do:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;ok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; when&lt;&#x2F;span&gt;&lt;span&gt; n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    spawn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;__MODULE__&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;worker&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; do:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;ok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; when&lt;&#x2F;span&gt;&lt;span&gt; n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    receive do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;      :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;register&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;parent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;num_tasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Bench&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;num_tasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;results&quot;&gt;Results&lt;a class=&quot;zola-anchor&quot; href=&quot;#results&quot; aria-label=&quot;Anchor link for: results&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;With given Erlang compilation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Erlang&#x2F;OTP 25 [erts-13.2.2.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Elixir 1.14.5 (compiled with Erlang&#x2F;OTP 25)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Note no JIT as Nix on macOS currently&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#currently&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; disable it and I didn&#x27;t
bother to enable it in the derivation (it was disabled because there were some
issues, but IIRC these are resolved now).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;currently&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Nixpkgs rev &lt;code&gt;bc3ec5ea&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The results are as follow (in bytes of peak memory footprint returned by
&lt;code&gt;&#x2F;usr&#x2F;bin&#x2F;time&lt;&#x2F;code&gt; on macOS):&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Implementation&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;1k&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;100k&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;1M&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Original&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;45047808&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;452837376&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;4227715072&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Spawn&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;43728896&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;318230528&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2869723136&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Reduce&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;43552768&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;314798080&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2849304576&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Count&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;43732992&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;313507840&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2780540928&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Registry&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;44453888&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;311988224&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2787237888&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;RemoteCall&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;43597824&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;310595584&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2771525632&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;As we can see we have reduced the memory use by about 30% by just changing
from &lt;code&gt;Task.async&#x2F;1&lt;&#x2F;code&gt; to &lt;code&gt;spawn&#x2F;1&lt;&#x2F;code&gt;. Further optimisations reduced memory usage
slightly, but with no such drastic changes.&lt;&#x2F;p&gt;
&lt;p&gt;Can we do better?&lt;&#x2F;p&gt;
&lt;p&gt;Well, with some VM flags tinkering - of course.&lt;&#x2F;p&gt;
&lt;p&gt;You see, by default Erlang VM will not only create some data required for
handling process itself&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#word&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;word&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Again, word here mean 8 bytes on 64-bit and 4 bytes on 32-bit architectures.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;blockquote&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Data Type&lt;&#x2F;th&gt;&lt;th&gt;Memory Size&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;…&lt;&#x2F;td&gt;&lt;td&gt;…&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Erlang process&lt;&#x2F;td&gt;&lt;td&gt;338 words when spawned, including a heap of 233 words.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;-- &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;efficiency_guide&#x2F;advanced.html#Advanced&quot;&gt;Erlang Efficiency Guide: 11. Advanced&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;As we can see, there are 105 words that are required and 233 words which are
used for preallocated heap. But this is microbenchmarking, so as we do not need
that much of memory (because our processes basically does nothing), we can
reduce it. We do not care about time performance anyway. For that we can use
&lt;code&gt;+hms&lt;&#x2F;code&gt; flag and set it to some small value, for example &lt;code&gt;1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to heap size Erlang by default load some additional data from the
BEAM files. That data is used for debugging and error reporting, but again, we
are microbenchmarking, and who need debugging support anyway (answer: everyone,
so &lt;strong&gt;do not&lt;&#x2F;strong&gt; do it in production). Luckily for us, the VM has yet another flag
for that purpose &lt;code&gt;+L&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Erlang also uses some &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;man&#x2F;ets.html&quot;&gt;ETS&lt;&#x2F;a&gt; (Erlang Term Storage) tables by default (for
example to support process registry we have mentioned above). ETS tables can be
compressed, but by default it&#x27;s not done, as it can slow down some kinds of
operations on such tables. Fortunately there is, another, flag &lt;code&gt;+ec&lt;&#x2F;code&gt; that has
description:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Forces option compressed on all ETS tables. Only intended for test and
evaluation.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Sounds good enough for me.&lt;&#x2F;p&gt;
&lt;p&gt;With all these flags enabled we get peak memory footprint at 996257792 bytes.&lt;&#x2F;p&gt;
&lt;p&gt;Compare it in more human readable units.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;Peak Memory Footprint for 1M processes&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Original code&lt;&#x2F;td&gt;&lt;td&gt;3.94 GiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Improved code&lt;&#x2F;td&gt;&lt;td&gt;2.58 GiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Improved code with flags&lt;&#x2F;td&gt;&lt;td&gt;0.93 GiB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Result - about 76% of the peak memory usage reduction. Not bad.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;First of all:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Please, do not use ChatGPT for writing code for microbenchmarks.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The thing about &lt;em&gt;micro&lt;&#x2F;em&gt;benchmarking is that we write code that does as little as
possible to show (mostly) meaningless features of the given technology in
abstract environment. ChatGPT cannot do that, not out of malice or incompetence,
but because it used (mostly) &lt;em&gt;good&lt;&#x2F;em&gt; and idiomatic code to teach itself,
microbenchmarks rarely are something that people will consider to have these
qualities. It also cannot consider other features that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Wetware_(brain)&quot;&gt;wetware&lt;&#x2F;a&gt; can take into
account (like our &quot;we do not need lists there&quot; thing).&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>Who Watches Watchmen? - Part 1</title>
      <published>2022-01-17T21:22:18+01:00</published>
      <updated>2022-01-17T21:22:18+01:00</updated>
      <link href="https://hauleth.dev/post/who-watches-watchmen-i/" type="text/html"/>
      <id>https://hauleth.dev/post/who-watches-watchmen-i/</id>
      <summary>A lot of application use systems like Kubernetes for their deployment. In my
humble opinion it is often overkill as system, that offers most of the stuff such
thing provide, is already present in your OS. In this article I will try to
present how to utilise the most popular system supervisor from Elixir
applications.
</summary>
      <content type="html">&lt;p&gt;I gave talk about this topic on CODE Beam V Americas, but I wasn&#x27;t really
satisfied with it. In this post I will try to describe what my presentation was
meant to be about.&lt;&#x2F;p&gt;
&lt;p&gt;If you are wondering about the presentation, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;speakerdeck.com&#x2F;hauleth&#x2F;who-supervises-supervisors&quot;&gt;the slides are on SpeakerDeck&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;a class=&quot;zola-anchor&quot; href=&quot;#abstract&quot; aria-label=&quot;Anchor link for: abstract&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Most of the operating systems are multi-process and multi-user operating
systems. This has a lot of positive aspects, like to be able to do more than one
thing at the time at our devices, but it introduces a lot of complexities that
in most cases are hidden from the users and developers. These things still need
to be handled in one or another way. The most basic problems are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;some processes need to be started before user can interact with the OS
in meaningful (for them) way (for example mounting filesystems, logging,
etc.)&lt;&#x2F;li&gt;
&lt;li&gt;some processes require strict startup ordering, for example you may need
logging to be started before starting HTTP server&lt;&#x2F;li&gt;
&lt;li&gt;system operator somehow need to know when the process is ready to do their
work, which is often some time after process start&lt;&#x2F;li&gt;
&lt;li&gt;system operator should be able to check process state in case when debugging
is needed, most commonly via logs&lt;&#x2F;li&gt;
&lt;li&gt;shutdown of the processes should be handled in a way, that will allow other
processes to be shut down cleanly (for example application that uses DB should
be down before DB itself)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;why-we-need-system-supervisor&quot;&gt;Why we need system supervisor?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-we-need-system-supervisor&quot; aria-label=&quot;Anchor link for: why-we-need-system-supervisor&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;System supervisor is a process started early in the OS boot, that should handle
starting and managing all other processes that will be run on our system. It is
often the init process (first process started by the OS that is running with PID
1) or it is first (and sometimes only) process started by the init process.
Popular examples of such supervisors (often integrated with init systems):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;SysV which is &quot;traditional&quot; implementation that originates at UNIX System
V (hence the name)&lt;&#x2F;li&gt;
&lt;li&gt;BSD init that with some variations is used in BSD-based OSes (NetBSD,
FreeBSD), it shares some similarities to SysV init and services description is
provided by shell scripts&lt;&#x2F;li&gt;
&lt;li&gt;OpenRC that also uses shell-based scripts for service description, used by
Linux distributions like Gentoo or Alpine&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;launchd&lt;&#x2F;code&gt; that is used on Darwin (macOS, iPadOS, iOS, watchOS) systems that uses
XML-based &lt;code&gt;plists&lt;&#x2F;code&gt; for services description&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;runit&lt;&#x2F;code&gt; which is small init and supervisor, but quite capable, for example
used by Void Linux&lt;&#x2F;li&gt;
&lt;li&gt;Upstart created by Canonical Ltd. as a replacement for SysV-like init system
in Ubuntu (no longer in use in Ubuntu), still used in some distributions like
ChromeOS or Synology NAS&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;systemd&lt;&#x2F;code&gt; (this is the name, not &quot;SystemD&quot;) that was created by Red Hat
employee, (in)famous Lennart Poettering, and later was adopted by almost all
major Linux distributions which spawned some heated discussion about it&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In this article I will focus on systemd, and its approach to &quot;new-style system
daemons&quot;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;DISCLAIMER&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Each of the solutions mentioned above has its strong and weak points. I do not
want to start another flame war whether it is good or not. It has some good in
it, and it has some bad in it, but we can say that it &quot;won&quot; over the most used
distributions, and despite our love or hate towards it, we need to learn how to
live with that.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;why-systemd&quot;&gt;Why &lt;code&gt;systemd&lt;&#x2F;code&gt;?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-systemd&quot; aria-label=&quot;Anchor link for: why-systemd&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;systemd&lt;&#x2F;code&gt; became a thing because SysV approach to ordering services&#x27; startup was
mildly irritating and non-parallelizable. In short, SysV is starting processes
exactly in lexicographical order of files in given directory. This meant, that
even if your service didn&#x27;t need the DB at all, but it somehow ended further in
the directory listing, you ended in waiting for the DB startup. Additionally,
SysV wasn&#x27;t really monitoring services, it just assumed that when process forked
itself to the background, then it is &quot;done&quot; with the startup, and we can
continue. This is obviously not true in many cases, for example, if your
previous shutdown wasn&#x27;t clean because of power shortage or other issue, then
your DB probably need a bit of time to rebuild state from journal. This causes
even more slowdown for the processes further in the list. This is highly
undesired in modern, cloud-based, environment, where you can often start the
machines on-demand during autoscaling actions. When there is a spike in the
traffic that need autoscaling, then the sooner new machine is in usable state
the sooner it can take load from other machines.&lt;&#x2F;p&gt;
&lt;p&gt;Different tools take different approach to solve that issue there. &lt;code&gt;systemd&lt;&#x2F;code&gt;
take approach that is derived from &lt;code&gt;launchd&lt;&#x2F;code&gt; - do not do stuff, that is not
needed. We can trigger on action of other services (obviously), but also on
stuff like socket activity, path creation&#x2F;modification, mounts, connection or
disconnection of device, time events, etc.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;DIGRESSION&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is exactly the reason why &lt;code&gt;systemd&lt;&#x2F;code&gt; has its infamous &quot;feature creep&quot;, it
doesn&#x27;t &quot;digest&quot; all services like Cron or &lt;code&gt;udev&lt;&#x2F;code&gt;. It is not that these are
&quot;tightly&quot; intertwined into &lt;code&gt;systemd&lt;&#x2F;code&gt;. You can still replace them with their
older counterparts, you will just lose all the features these bring with them.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Such lazy approach sometimes require changes into the service itself. For
example to let supervisor know, that you are ready (not just started), you need
some way to communicate with supervisor. In &lt;code&gt;systemd&lt;&#x2F;code&gt; you can do so via UNIX
socket pointed by &lt;code&gt;NOTIFY_SOCKET&lt;&#x2F;code&gt; environment variable passed to your
application. With the same socket you can implement another useful feature
- watchdog&#x2F;heartbeat process. This mean that if for any reason your process
became non-responsive (but it will refuse to die), then supervisor will
forcefully bring process down and restart it, assuming that the error was
accidental.&lt;&#x2F;p&gt;
&lt;p&gt;About restarting, we can define behaviour of service after main process die. It
can be restarted regardless of the exit code, it can be restarted on abnormal
exit, it can remain shut, etc. Does this ring a bell? This works similarly to
OTP supervisors, but &quot;one level above&quot;. If your service utilize system
supervisor right, you can make your application almost ultimately self-healing
(by restarts).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;basic-setup&quot;&gt;Basic setup&lt;a class=&quot;zola-anchor&quot; href=&quot;#basic-setup&quot; aria-label=&quot;Anchor link for: basic-setup&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Now, when we know a little about how and why &lt;code&gt;systemd&lt;&#x2F;code&gt; works as it works, we
now can go to details on how to utilize that with services in Elixir.&lt;&#x2F;p&gt;
&lt;p&gt;As a base we will implement super simple Plug application:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# hello&#x2F;application.ex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Application&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Application&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    children &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, [&lt;&#x2F;span&gt;&lt;span&gt;scheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;http&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;()},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Drainer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; refs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;    Supervisor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;start_link&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;children&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; strategy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;one_for_one&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;System&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get_env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;4000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# hello&#x2F;router.ex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Router&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  plug &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;match&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  plug &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;dispatch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  get &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    send_resp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;conn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello World!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I will also assume that we are using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;mix&#x2F;Mix.Tasks.Release.html&quot;&gt;Mix release&lt;&#x2F;a&gt; named &lt;code&gt;hello&lt;&#x2F;code&gt;
that we later copy to &lt;code&gt;&#x2F;opt&#x2F;hello&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;systemd-unit-file&quot;&gt;systemd unit file&lt;a class=&quot;zola-anchor&quot; href=&quot;#systemd-unit-file&quot; aria-label=&quot;Anchor link for: systemd-unit-file&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;We have only one thing left, we need to define our &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freedesktop.org&#x2F;software&#x2F;systemd&#x2F;man&#x2F;systemd.service.html#&quot;&gt;&lt;code&gt;hello.service&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Hello World service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;opt&#x2F;hello&#x2F;bin&#x2F;hello start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now you can create file with that content in
&lt;code&gt;&#x2F;usr&#x2F;local&#x2F;lib&#x2F;systemd&#x2F;system&#x2F;hello.service&lt;&#x2F;code&gt; and then start it with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# systemctl start hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the simplest service imaginable, however from the start we have few
issues there:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It will run service as user running supervisor, so if it is run using global
supervisor, then it will run as &lt;code&gt;root&lt;&#x2F;code&gt;. You do not want to run anything as
&lt;code&gt;root&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;On error it will produce (BEAM) core dump, which may contain sensitive data.&lt;&#x2F;li&gt;
&lt;li&gt;It can read (and, due to being run as &lt;code&gt;root&lt;&#x2F;code&gt;, write) everything in the system,
like private data of other processes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;service-readiness&quot;&gt;Service readiness&lt;a class=&quot;zola-anchor&quot; href=&quot;#service-readiness&quot; aria-label=&quot;Anchor link for: service-readiness&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Erlang VM isn&#x27;t really the best tool out there wrt the startup times. In
addition to that our application may need some preparation steps before it can
be marked as &quot;ready&quot;. This is problem that I sometimes encounter in Docker,
where some containers do not really have any health check, and then I need to
have loop with check in some of the containers that depend on another one. This
&quot;workaround&quot; is frustrating, error prone, and can cause nasty Heisenbugs when
the timing will be wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Two possible solutions for this problem are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Readiness probe - another program that is ran after the main process is
started, that checks whether our application is ready to work.&lt;&#x2F;li&gt;
&lt;li&gt;Notification system where our application uses some common protocol to inform
the supervisor that it finished setup and is ready for work.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;systemd supports the second approach via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freedesktop.org&#x2F;software&#x2F;systemd&#x2F;man&#x2F;sd_notify.html&quot;&gt;&lt;code&gt;sd_notify&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. The approach
there is simple - we have &lt;code&gt;NOTIFY_SOCKET&lt;&#x2F;code&gt; environment variable that contain path
to the Unix datagram socket, that we can use to send information about state of
our application. This socket accept set of different messages, but right now,
for our purposes, we will focus only on few of them:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;READY=1&lt;&#x2F;code&gt; - marks our service as ready, aka it is ready to do its work (for
example accept incoming HTTP connections in our example). It need to be sent
within given timespan after start of the VM, otherwise the process will be
killed and possibly restarted&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;STATUS=name&lt;&#x2F;code&gt; - sets status of our application that can be checked via
&lt;code&gt;systemctl status hello.service&lt;&#x2F;code&gt;, this allows us to have better insight into
what is the high level state without manually traversing through logs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;RELOADING=1&lt;&#x2F;code&gt; - marks, that our application is reloading, which in general may
mean a lot of things, but there it will be used to mark &lt;code&gt;:init.restart&#x2F;0&lt;&#x2F;code&gt;-like
behaviour (due to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;erlang&#x2F;otp&#x2F;issues&#x2F;4698&quot;&gt;erlang&#x2F;otp#4698&lt;&#x2F;a&gt; there is wrapper for that function in
&lt;code&gt;systemd&lt;&#x2F;code&gt; library). The process need then to send &lt;code&gt;READY=1&lt;&#x2F;code&gt; within given
timespan, or the process will be marked as a malfunctioning, and will be
forcefully killed and possibly restarted&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;STOPPING=1&lt;&#x2F;code&gt; - marks, that our application began shutting down process, and
will be closing soon. If the process will not close within given timespan, it
will be forcefully killed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These messages provide us enough power to not only mark the service as ready,
but also provides additional information about system state, so even operator,
who knows a little about Erlang or our application runtime, will be able to
understand what is going on.&lt;&#x2F;p&gt;
&lt;p&gt;The main thing is that systemd will wait with activation of the dependants of
our system as well as the &lt;code&gt;systemctl start&lt;&#x2F;code&gt; and &lt;code&gt;systemctl restart&lt;&#x2F;code&gt; commands
will wait until our service declare that it is ready.&lt;&#x2F;p&gt;
&lt;p&gt;Usage of such feature is quite simple:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Hello World service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# Define `Type=` to `notify`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;notify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;opt&#x2F;hello&#x2F;bin&#x2F;hello start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WatchdogSec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;1min&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then in our supervisor tree we need add &lt;code&gt;:systemd.ready()&lt;&#x2F;code&gt; &lt;strong&gt;after&lt;&#x2F;strong&gt; last
process needed for proper functioning of our application, in our simple example
it is after &lt;code&gt;Plug.Cowboy&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# hello&#x2F;application.ex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Application&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Application&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    children &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, [&lt;&#x2F;span&gt;&lt;span&gt;scheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;http&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;()},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;      :systemd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;ready&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; # &amp;lt;-- it is function call, as it returns proper&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                        # `child_spec&#x2F;0`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Drainer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; refs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;    Supervisor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;start_link&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;children&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; strategy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;one_for_one&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;System&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get_env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;4000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now restarting our service will not finish immediately, but will wait until our
service will declare that it is ready.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# systemctl restart hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;About &lt;code&gt;STOPPING=1&lt;&#x2F;code&gt; - the magic thing is that the &lt;code&gt;systemd&lt;&#x2F;code&gt; library takes care of
it for you. As soon as the system will be scheduled to shutdown this message
will be automatically sent, and the operator will be notified about this fact.&lt;&#x2F;p&gt;
&lt;p&gt;We can also provide more information about state of our application. As you may
have already noticed, we have &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;plug_cowboy&#x2F;2.5.2&#x2F;Plug.Cowboy.Drainer.html&quot;&gt;&lt;code&gt;Plug.Cowboy.Drainer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; there. It is process that
will delay shutdown of our application while there are still open connections.
This can take some time, so it would be handy if the operator would see that the
draining is in progress. We can easily achieve that by again changing our
supervision tree to:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# hello&#x2F;application.ex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Application&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Application&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    children &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, [&lt;&#x2F;span&gt;&lt;span&gt;scheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;http&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;()},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;      :systemd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;ready&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;      :systemd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;set_status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;down&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: [&lt;&#x2F;span&gt;&lt;span&gt;status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;drained&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;]),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Drainer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; refs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; shutdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 10_000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;      :systemd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;set_status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;down&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: [&lt;&#x2F;span&gt;&lt;span&gt;status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;draining&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;    Supervisor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;start_link&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;children&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; strategy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;one_for_one&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cowboy_opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;System&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get_env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;4000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now when we will shutdown our application by:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# systemctl stop hello.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And we have some connections open to our service (you can simulate that with
&lt;code&gt;wrk&lt;&#x2F;code&gt;) then when we ran &lt;code&gt;systemctl status hello.service&lt;&#x2F;code&gt; in separate terminal
(previous will be blocked until our service shuts down) then you will be able to
see something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;● hello.service - Example Plug application&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Loaded: loaded (&#x2F;usr&#x2F;local&#x2F;lib&#x2F;systemd&#x2F;system&#x2F;hello.service; static; vendor preset: enabled)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          Active: deactivating (stop-sigterm) since Sat 2022-01-15 17:46:30 CET;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          1s ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          Main PID: 1327 (beam.smp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          Status: &amp;quot;draining&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          Tasks: 19 (limit: 1136)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          Memory: 106.5M&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can notice that the &lt;code&gt;Status&lt;&#x2F;code&gt; is set to &lt;code&gt;&quot;draining&quot;&lt;&#x2F;code&gt;. As soon as all
connections will be drained it will change to &lt;code&gt;&quot;drained&quot;&lt;&#x2F;code&gt; and then the
application will shut down and service will be marked as &lt;code&gt;inactive&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;watchdog&quot;&gt;Watchdog&lt;a class=&quot;zola-anchor&quot; href=&quot;#watchdog&quot; aria-label=&quot;Anchor link for: watchdog&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Watchdog allows us to monitor our application for responsiveness (as mentioned
above). It is simple feature that requires our application to ping systemd
within specified interval, otherwise the application will be forcibly shut down
as malfunctioning. Fortunately for us, the &lt;code&gt;systemd&lt;&#x2F;code&gt; library that provides our
integration, have that feature out of the box, so all we need to do to achieve
expected result is set &lt;code&gt;WatchdogSec=&lt;&#x2F;code&gt; option in our &lt;code&gt;systemd.service&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Hello World service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;notify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;opt&#x2F;hello&#x2F;bin&#x2F;hello start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WatchdogSec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;1min&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This configuration says that if the VM will not send healthy message each 1
minute interval, then the service will be marked as malfunctioning. From the
application side we can manage state of the watchdog in several ways:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;By setting &lt;code&gt;systemd.watchdog_check&lt;&#x2F;code&gt; configuration option we can configure the
function that will be called on each check, if that function return &lt;code&gt;true&lt;&#x2F;code&gt;
then it mean that application is healthy and the systemd should be notified
with ping, if it returns &lt;code&gt;false&lt;&#x2F;code&gt; or fail, then the check will be omitted.&lt;&#x2F;li&gt;
&lt;li&gt;Manually sending trigger message in case of detected problems via
&lt;code&gt;:systemd.watchdog(trigger)&lt;&#x2F;code&gt;, it will immediately mark service as
malfunctioning and will trigger action defined in service unit file (by
default it will restart application)&lt;&#x2F;li&gt;
&lt;li&gt;Disabling built in watchdog process via &lt;code&gt;:systemd.watchdog(:disable)&lt;&#x2F;code&gt; and then
manually sending &lt;code&gt;:systemd.watchdog(:ping)&lt;&#x2F;code&gt; within expected intervals
(discouraged)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;security&quot;&gt;Security&lt;a class=&quot;zola-anchor&quot; href=&quot;#security&quot; aria-label=&quot;Anchor link for: security&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;We should start with changing default user and group which is assigned to our
process. We can do so in 2 different ways:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Use some existing user and group by defining &lt;code&gt;User=&lt;&#x2F;code&gt; and &lt;code&gt;Group=&lt;&#x2F;code&gt; directives
in our service definition; or&lt;&#x2F;li&gt;
&lt;li&gt;Create ephemeral user on-demand before our service starts, by using directive
&lt;code&gt;DynamicUser=true&lt;&#x2F;code&gt; in service definition.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I prefer second option, as it additionally provides a lot of other security
related options, like creating private &lt;code&gt;&#x2F;tmp&lt;&#x2F;code&gt; directory, making system
read-only, etc. This has also some disadvantages, like removing all of given
data on service shutdown, however there are options to keep some data between
launches.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to that we can add &lt;code&gt;PrivateDevices=true&lt;&#x2F;code&gt; that will hide all
physical devices from &lt;code&gt;&#x2F;dev&lt;&#x2F;code&gt; leaving only pseudo devices like &lt;code&gt;&#x2F;dev&#x2F;null&lt;&#x2F;code&gt; or
&lt;code&gt;&#x2F;dev&#x2F;urandom&lt;&#x2F;code&gt; (so you will be able to use &lt;code&gt;:crypto&lt;&#x2F;code&gt; and &lt;code&gt;:ssl&lt;&#x2F;code&gt; modules without
problems).&lt;&#x2F;p&gt;
&lt;p&gt;Next thing is that we can do, is to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;erlef.github.io&#x2F;security-wg&#x2F;secure_coding_and_deployment_hardening&#x2F;crash_dumps&quot;&gt;disable crash dumps generated by BEAM&lt;&#x2F;a&gt;.
While not strictly needed in this case, it is worth remembering, that it isn&#x27;t
hard to achieve, just use &lt;code&gt;Environment=ERL_CRASH_DUMP_SECONDS=0&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Our new, more secure, &lt;code&gt;hello.service&lt;&#x2F;code&gt; will look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Hello World service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Requires&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;network.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;notify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;opt&#x2F;hello&#x2F;bin&#x2F;hello start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WatchdogSec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;1min&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# We need to add capability to be able to bind on port 80&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CapabilityBoundingSet&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;CAP_NET_BIND_SERVICE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# Hardening&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DynamicUser&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;PrivateDevices&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ERL_CRASH_DUMP_SECONDS&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The problem with that configuration is that our service is now capable on
binding &lt;strong&gt;any&lt;&#x2F;strong&gt; port under 1024, so for example, if there is some security
issue, then the malicious party can open any of the restricted ports and then
serve whatever data they want there. This can be quite problematic, and the
solution for that problem will be covered in Part 2, where we will cover socket
passing and socket activation for our service.&lt;&#x2F;p&gt;
&lt;p&gt;With that we achieved quite basic level of isolation to what Docker (or other
container runtime) is providing, but it do not require &lt;code&gt;overlayfs&lt;&#x2F;code&gt; or anything
more, than what you already have on your machine. That means, updates done by
your system package manager will be applied to all running services. With that
you do not need to rebuild all your containers when there is security patch
issued for any of your dependencies.&lt;&#x2F;p&gt;
&lt;p&gt;Of course it only scratches the surface of what is possible with systemd wrt
the hardening of the services. More information can be found in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.redhat.com&#x2F;sysadmin&#x2F;mastering-systemd&quot;&gt;RedHat
article&lt;&#x2F;a&gt; and in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freedesktop.org&#x2F;software&#x2F;systemd&#x2F;man&#x2F;systemd-analyze.html#systemd-analyze%20security%20%5BUNIT...%5D&quot;&gt;&lt;code&gt;systemd-analyze security&lt;&#x2F;code&gt; command
output&lt;&#x2F;a&gt;. Possible features are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;creation of the private networks for your services&lt;&#x2F;li&gt;
&lt;li&gt;disallowing creation of socket connections that are outside of the specified
set of families&lt;&#x2F;li&gt;
&lt;li&gt;make only some paths readable&lt;&#x2F;li&gt;
&lt;li&gt;hide some paths from the process&lt;&#x2F;li&gt;
&lt;li&gt;etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Coverage of just that topic is a little bit out of scope for this blog post, so
I encourage you to read the documentation of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freedesktop.org&#x2F;software&#x2F;systemd&#x2F;man&#x2F;systemd.exec.html&quot;&gt;&lt;code&gt;systemd.exec&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
articles mentioned above for more details.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This blog post is already quite lengthy, so I will split it into separate parts.
There probably will be 3 of them:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hauleth.dev&#x2F;post&#x2F;who-watches-watchmen-i&#x2F;.&#x2F;#top&quot;&gt;Part 1 - Basics, security, and FD passing (this one)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hauleth.dev&#x2F;post&#x2F;who-watches-watchmen-ii&#x2F;&quot;&gt;Part 2 - Socket activation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Part 3 - Logging&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>Log all the things</title>
      <published>2022-01-02T00:00:00+00:00</published>
      <updated>2022-01-02T00:00:00+00:00</updated>
      <link href="https://hauleth.dev/post/log-all-the-things/" type="text/html"/>
      <id>https://hauleth.dev/post/log-all-the-things/</id>
      <summary><p>In Elixir 1.11 landed set of new features that allows for more powerful logging
by utilising Erlang's <a rel="external" href="https://erlang.org/doc/man/logger.html"><code>logger</code></a> features. Here I will try to describe
new possibilities and how You can use them to improve your logs.</p></summary>
      <content type="html">&lt;p&gt;In Elixir 1.11 landed set of new features that allows for more powerful logging
by utilising Erlang&#x27;s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;man&#x2F;logger.html&quot;&gt;&lt;code&gt;logger&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; features. Here I will try to describe
new possibilities and how You can use them to improve your logs.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;levels&quot;&gt;New log levels&lt;a class=&quot;zola-anchor&quot; href=&quot;#levels&quot; aria-label=&quot;Anchor link for: levels&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Elixir gained 4 new log levels to total 8 (from most verbose to least verbose):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;debug&lt;&#x2F;li&gt;
&lt;li&gt;info&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;notice&lt;&#x2F;strong&gt; *&lt;&#x2F;li&gt;
&lt;li&gt;warning (renamed from warn)&lt;&#x2F;li&gt;
&lt;li&gt;error&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;critical&lt;&#x2F;strong&gt; *&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;alert&lt;&#x2F;strong&gt; *&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;emergency&lt;&#x2F;strong&gt; *&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;small&gt;* new levels&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This allow to provide finer graded verbosity control, due to compatibility
reasons, in Elixir backends we need to translate these levels back to &quot;old&quot; set
of 4. The current table looks like:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Call level&lt;&#x2F;th&gt;&lt;th&gt;What Elixir backend will see&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;debug&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;debug&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;info&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;info&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;notice&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;&lt;code&gt;info&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; *&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;warning&lt;&#x2F;code&gt; (or &lt;code&gt;warn&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;warn&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;error&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;error&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;critical&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;&lt;code&gt;error&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; *&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;alert&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;&lt;code&gt;error&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; *&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;emergency&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;&lt;code&gt;error&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; *&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;small&gt;* &quot;translated&quot; messages&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We can set verbosity to all levels. This may be confusing during the transition
period, but we cannot change the behaviour until Elixir 2 (which is not
happening any time soon).&lt;&#x2F;p&gt;
&lt;p&gt;Usage of the new levels is &quot;obvious&quot;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;notice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Will produce message with &lt;code&gt;notice&lt;&#x2F;code&gt; level of verbosity.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally the &lt;code&gt;logger.level&lt;&#x2F;code&gt; option in configuration supports 2 additional
verbosity levels that you can use in your config:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:all&lt;&#x2F;code&gt; - all messages will be logged, logically exactly the same as &lt;code&gt;:debug&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:none&lt;&#x2F;code&gt; - no messages will be logged&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;per-module-level&quot;&gt;Per module log level&lt;a class=&quot;zola-anchor&quot; href=&quot;#per-module-level&quot; aria-label=&quot;Anchor link for: per-module-level&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This is change that can be quite handy during debugging sessions. With this
change we have 4 new functions in &lt;code&gt;Logger&lt;&#x2F;code&gt; module:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;logger&#x2F;Logger.html#get_module_level&#x2F;1&quot;&gt;&lt;code&gt;get_module_level&#x2F;1&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;logger&#x2F;Logger.html#put_module_level&#x2F;2&quot;&gt;&lt;code&gt;put_module_level&#x2F;2&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;logger&#x2F;Logger.html#delete_module_level&#x2F;1&quot;&gt;&lt;code&gt;delete_module_level&#x2F;1&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;logger&#x2F;Logger.html#delete_all_module_level&#x2F;0&quot;&gt;&lt;code&gt;delete_all_module_level&#x2F;0&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These allow us to manipulate verbosity level on per-module basis. What is
non-obvious and is super handy is that it allows both lowering &lt;strong&gt;and raising&lt;&#x2F;strong&gt;
verbosity for given module. This mean that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;require&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Logger&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;configure&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;level&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;    Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;debug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;I am still there&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;run&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;()&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; # Does not log anything&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# Set `debug` level for `Foo` module only&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;put_module_level&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;debug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Foo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;run&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# `I am still there` is logged&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;debug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;I will not be printed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# Nothing got logged as top-level verbositi is still set to `:error`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course it will not work if you decide to use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;logger&#x2F;Logger.html#module-application-configuration&quot;&gt;compile time purging&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;handlers&quot;&gt;Logger handlers&lt;a class=&quot;zola-anchor&quot; href=&quot;#handlers&quot; aria-label=&quot;Anchor link for: handlers&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;Warning!&lt;&#x2F;strong&gt; This is not fully implemented in both - Erlang and Elixir. Writing
your own handlers without additional knowledge can cause overload problems.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Erlang together with their logging implementation needed to provide a way to
ingest these logs somehow. This is done via Erlang logger handlers (in this
article called &lt;em&gt;handlers&lt;&#x2F;em&gt; in contrast to Elixir backends called &lt;em&gt;backends&lt;&#x2F;em&gt;
there).&lt;&#x2F;p&gt;
&lt;p&gt;Handlers are modules that export at least 1 function &lt;code&gt;log&#x2F;2&lt;&#x2F;code&gt; that takes 2
arguments:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;log_event&lt;&#x2F;code&gt; which is a map with 3 fields:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:level&lt;&#x2F;code&gt; - verbosity level&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:msg&lt;&#x2F;code&gt; - tuple describing message:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{:io.format(), [term()]}&lt;&#x2F;code&gt; - format string and list of terms that should
be passed to &lt;code&gt;:io_lib.format&#x2F;2&lt;&#x2F;code&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;{:report, map() | keyword()}&lt;&#x2F;code&gt; - report that can be formatted into string
by &lt;code&gt;report_cb&#x2F;{1,2}&lt;&#x2F;code&gt; set in metadata map (see below)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;{:string, :unicode.chardata()}&lt;&#x2F;code&gt; - raw string that should be printed as
a message&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:meta&lt;&#x2F;code&gt; - map containing all metadata for given event. All keys should be
atoms and values can be anything. Some keys have special meaning, and some
of them will be populated automatically by the &lt;code&gt;Logger&lt;&#x2F;code&gt; macros and functions.
These are:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:pid&lt;&#x2F;code&gt; - PID of the process that fired log event&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:gl&lt;&#x2F;code&gt; - group leader of the process that fired log event&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:mfa&lt;&#x2F;code&gt; - tuple in form of &lt;code&gt;{module(), name :: atom(), arity :: non_neg_integer()}&lt;&#x2F;code&gt;
that describe function that fired log event&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:file&lt;&#x2F;code&gt; - filename of file that defines the code that fired log event&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:line&lt;&#x2F;code&gt; - line in the given file where the log event was fired&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:domain&lt;&#x2F;code&gt; - list of atoms that can be used to describe log events
hierarchy which then can be used for filtering. All events fired using
&lt;code&gt;Logger&lt;&#x2F;code&gt; macros and functions will have &lt;code&gt;:elixir&lt;&#x2F;code&gt; prepended to their
domain list.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:report_cb&lt;&#x2F;code&gt; - function that will be used to format &lt;code&gt;{:report, map() | keyword()}&lt;&#x2F;code&gt; messages. This can be either 1-ary function, that takes report
and returns &lt;code&gt;{:io.format(), [term()]}&lt;&#x2F;code&gt; leaving truncation and further
formatting up to the main formatter, or 2-ary function that takes report
and configuration map &lt;code&gt;%{depth: pos_integer() | :unlimited, chars_limit: pos_integer() | :unlimited, single_line: boolean()}&lt;&#x2F;code&gt; and returns already
formatted &lt;code&gt;:unicode.chardata()&lt;&#x2F;code&gt;. More about it can be found in &lt;a href=&quot;https:&#x2F;&#x2F;hauleth.dev&#x2F;post&#x2F;log-all-the-things&#x2F;#structured-logging&quot;&gt;separate
section&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Return value of this function is ignored. If there will be any exception raised
when calling this function, then it will be captured and failing handler will be
removed. This is important, as if such handler is the only one, then you can be
left without any logging handler and miss logs.&lt;&#x2F;p&gt;
&lt;p&gt;The important thing about Erlang handlers and Elixir backends is that Erlang
handlers functions are called &lt;strong&gt;within caller process&lt;&#x2F;strong&gt; while Elixir backends
are called in separate process. This mean that wrongly written Erlang handler
can cause quite substantial load on application.&lt;&#x2F;p&gt;
&lt;p&gt;To read on other, optional, callbacks that can be defined by Erlang handler, that
will not be covered there, I suggest looking into &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;man&#x2F;logger.html#formatter-callback-functions&quot;&gt;Erlang documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;structured-logging&quot;&gt;Structured logging&lt;a class=&quot;zola-anchor&quot; href=&quot;#structured-logging&quot; aria-label=&quot;Anchor link for: structured-logging&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;One of the biggest new features in the Elixir 1.11 is support for structured
logging. This mean that the log message do not need to be free-form string, but
instead we can pass structure, that can provide more machine-readable data for
processing in log aggregators. In Elixir 1.11 is simple as passing map as a
first argument to the &lt;code&gt;Logger&lt;&#x2F;code&gt; macros:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;info&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;completed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  response&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;ok&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will produce message that looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;log&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;14:08:46.849&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt; [info]&lt;&#x2F;span&gt;&lt;span&gt;  [response: :ok, status: :completed]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As we can see, the map (called &lt;em&gt;report&lt;&#x2F;em&gt;) is formatted as a keyword list. This is
default way to present the report data. Unfortunately we cannot access the
metadata from the Elixir backends, but we have 2 ways to make these messages
more readable for the human operator:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Utilise &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;logger&#x2F;Logger.Translator.html&quot;&gt;&lt;code&gt;Logger&lt;&#x2F;code&gt;&#x27;s translators&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Using &lt;code&gt;:report_cb&lt;&#x2F;code&gt; field in metadata&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;1st option is described quite good in Elixir documentation and is available
since Elixir 1.0 as it was used to translate &lt;code&gt;error_logger&lt;&#x2F;code&gt; messages in old
Erlang versions. Here I will describe the 2nd option which provide way for
&lt;strong&gt;caller&lt;&#x2F;strong&gt; to define how report should be formatted into human-readable string.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;:report_cb&lt;&#x2F;code&gt; accepts 2 kind of functions as an argument:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;1-ary function, that takes report as an argument and should return tuple
in form of &lt;code&gt;{:io.format(), [term()]}&lt;&#x2F;code&gt; that will be later formatted
respectively by the formatters.&lt;&#x2F;li&gt;
&lt;li&gt;2-ary function that takes report and configuration map as an arguments and
should return formatted string.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;1st option is much easier for most use cases, as it do not force you to worry
about handling width, depth, and multiline logs, as it will all be handled for
you.&lt;&#x2F;p&gt;
&lt;p&gt;For example, instead of doing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;info&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Started HTTP server on http:&#x2F;&#x2F;localhost:8080&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can do:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;info&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  %&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;http&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8080&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    address&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;localhost&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    endpoint&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; MyEndpoint&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    handler&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Cowboy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  report_cb&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;__MODULE__&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;report_cb&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# …&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; report_cb&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; address&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; address&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;})&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;  {&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Started ~s server on ~s:&#x2F;&#x2F;~s:~B&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;, [&lt;&#x2F;span&gt;&lt;span&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; address&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While the second entry seems much more verbose, with proper handler, it can
provide much more detailed output. Just imagine that we would have handler that
output JSON data and what information we could contain in such message:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Started HTTP server on http:&#x2F;&#x2F;localhost:8080&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;mfa&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;MyMod.start&#x2F;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;file&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;foo.ex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;line&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 42&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now our log aggregation service need to parse &lt;code&gt;msg&lt;&#x2F;code&gt; field to extract all
information that is contained there, like port, address, and protocol. With
structured logging we can have that message available already there while
presenting the &quot;human readable&quot; form as well:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Started HTTP server on http:&#x2F;&#x2F;localhost:8080&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;address&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;localhost&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8080&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;http&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;MyEndpoint&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;handler&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Plug.Cowboy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;mfa&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;MyMod.start&#x2F;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;file&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;foo.ex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;line&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 42&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can see there that we can have more information available in the structured
log that would otherwise needed to be crammed somewhere into the text message,
even if it is not important in &quot;regular&quot; Ops observability.&lt;&#x2F;p&gt;
&lt;p&gt;This can raise a question - why not use metadata for such functionality, like it
is available in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Nebo15&#x2F;logger_json&quot;&gt;&lt;code&gt;LoggerJSON&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hex.pm&#x2F;packages&#x2F;ink&quot;&gt;&lt;code&gt;Ink&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;? The reason is that their reason
existence is different. Metadata meant for &quot;meta&quot; stuff like location, tracing
ID, but not for the information about the message itself. It is best shown on
example. For this use Elixir&#x27;s implementation of &lt;code&gt;GenServer&lt;&#x2F;code&gt; wrapper that
produces error log entry on unknown message handled by default &lt;code&gt;handle_info&#x2F;2&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  # Report&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  %&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    label&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;GenServer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;no_handle_info&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    report&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      module&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; __MODULE__&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; proc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  # Metadata&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  %&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    error_logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;tag&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;error_msg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    report_cb&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;GenServer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;format_report&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As we can see there, the report contains information like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:label&lt;&#x2F;code&gt; - that describes type of the event&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:report&lt;&#x2F;code&gt; - content of the &quot;main&quot; event
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:module&lt;&#x2F;code&gt; - module that created the event, it is important to notice, that
it is also present in metadata (as part of &lt;code&gt;:mfa&lt;&#x2F;code&gt; key), but their meaning is
different. Module name here is meant for the operator to know the name of
the implementor that failed to handle message, while &lt;code&gt;:mfa&lt;&#x2F;code&gt; is meant to
describe the location of the code that fired the event.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:message&lt;&#x2F;code&gt; - the message itself that hasn&#x27;t been handled. Notice, that it is
not stringified in any way there, it is simply passed &quot;as is&quot; to the
report. It is meant to be stringified later by the &lt;code&gt;:report_cb&lt;&#x2F;code&gt; function.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:name&lt;&#x2F;code&gt; - name of the process. Remember, similarly to &lt;code&gt;:module&lt;&#x2F;code&gt;, the PID of
the current process is part of the metadata, so in theory we could use value
from there, but their meaning is different (additionally this one may be an
atom in case if the process is locally registered with name).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Metadata on the other hand contains information that will be useful for
filtering or formatting of the event.&lt;&#x2F;p&gt;
&lt;p&gt;The rule of thumb you can follow is:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;If it is thing that you will want to filter on, then it probably should be
part of the metadata. If you want to aggregate information or just display
them, it should be part of the message report.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;log-filtering&quot;&gt;Log filtering&lt;a class=&quot;zola-anchor&quot; href=&quot;#log-filtering&quot; aria-label=&quot;Anchor link for: log-filtering&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Finally we come to first feature that is not directly accessible from the Elixir
&lt;code&gt;Logger&lt;&#x2F;code&gt; API (yet). Erlang&#x27;s &lt;code&gt;logger&lt;&#x2F;code&gt; have powerful functionality for filtering
log messages which allows us to dynamically decide which message should, or
should not be logged. These even can alter messages on the fly.&lt;&#x2F;p&gt;
&lt;p&gt;Currently that functionality is available only via &lt;code&gt;:logger&lt;&#x2F;code&gt; module. It can be
used like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; MyFilter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;log_event&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    # …&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;:logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;add_primary_filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;my_filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;MyFilter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;# Or&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;:logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;add_handler_filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;handler_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;my_filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;, {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;MyFilter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Few important things that need to be remembered when writing such filters:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It is best practice to make such functions public and define filters using
remote function capture, like &lt;code&gt;&amp;amp;__MODULE__.process_disabled&#x2F;2&lt;&#x2F;code&gt; (so not
anonymous functions either). It will make such filter much easier for VM to
handle (it is bigger topic why it is that, I may to cover it in another post).&lt;&#x2F;li&gt;
&lt;li&gt;Filters are ran &lt;strong&gt;within the same process that fired log event&lt;&#x2F;strong&gt;, so it is
important to make such filters as fast as possible, and do not do any heavy
work there.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Filters can be used for 2 different things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;preventing some messages from being logged&lt;&#x2F;li&gt;
&lt;li&gt;modifying a message&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;While the former is much more common, I will try to describe both use cases
there, as the latter is also quite useful.&lt;&#x2F;p&gt;
&lt;p&gt;Filters are defined as 2-ary functions where 1st argument is log event, and
second argument is any term that can be used as a configuration for filter.
Filter should return one of these 3 values:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:stop&lt;&#x2F;code&gt; - which will immediately discard message and do not run any additional
filters.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:ignore&lt;&#x2F;code&gt; - which mean that given filter didn&#x27;t recognise the given message
and leaves it up to other filters to decide on the action. If all filters
return &lt;code&gt;:ignore&lt;&#x2F;code&gt; then &lt;code&gt;:filter_default&lt;&#x2F;code&gt; option for the handler will be taken.
By default it is &lt;code&gt;:log&lt;&#x2F;code&gt;, which mean that message will be logged, but default
handler has it set to &lt;code&gt;:stop&lt;&#x2F;code&gt; by default, which mean, that non-matching
messages will be discarded.&lt;&#x2F;li&gt;
&lt;li&gt;Just log event (possibly modified) that will cause next filter to be called
with altered message. The message returned by the last filter (or in case of
&lt;code&gt;:ignore&lt;&#x2F;code&gt; return, previous filters) will be the message passed to handler.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;preventing-some-messages-from-being-logged&quot;&gt;Preventing some messages from being logged&lt;a class=&quot;zola-anchor&quot; href=&quot;#preventing-some-messages-from-being-logged&quot; aria-label=&quot;Anchor link for: preventing-some-messages-from-being-logged&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Most common use-case for filters will probably be rejecting messages that aren&#x27;t
important for us. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;man&#x2F;logger_filters.html&quot;&gt;Erlang even prepared some useful filters&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;domain&lt;&#x2F;code&gt; - allow filtering by metadata &lt;code&gt;:domain&lt;&#x2F;code&gt; field (remember as I said
that metadata is for filtering?). It supports multiple possible relations
between the log domain and defined domain.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;level&lt;&#x2F;code&gt; - allow filtering (in or out) messages depending on their level, in
both directions. It will allow you to filter messages with higher level for
some handlers. Just remember, that it will not receive messages that will not
pass primary&#x2F;module level.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;progress&lt;&#x2F;code&gt; - filters all reports from &lt;code&gt;supervisor&lt;&#x2F;code&gt; and
&lt;code&gt;application_controller&lt;&#x2F;code&gt;. Simply, reduces startup&#x2F;process shutdown chatter
that often is meaningless for most time.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;remote_gl&lt;&#x2F;code&gt; - filters messages coming from group leader on another node.
Useful when you want to discard&#x2F;log messages coming from other nodes in
cluster.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;modifying-a-message&quot;&gt;Modifying a message&lt;a class=&quot;zola-anchor&quot; href=&quot;#modifying-a-message&quot; aria-label=&quot;Anchor link for: modifying-a-message&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Sometimes there is need to alter messages in the system. For example we may need
to prevent sensitive information from being logged. When using &quot;old&quot; Elixir
approach you could abuse translators, but that was error prone, as first
successful translator was breaking pipeline, so you couldn&#x27;t just smash one on
top and then keep rest working as is. With &quot;new&quot; approach and structured logging
you can just traverse the report and replace all occurrences of the unsafe data
with anonymised data. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; filter_out_password&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;msg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;report&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; report&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; event&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  %&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;event &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; msg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;report&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; replace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;report&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-module z-elixir&quot;&gt;filtered&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[FILTERED]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; replace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;password&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;map &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-variable&quot;&gt; @&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-module z-elixir&quot;&gt;filtered&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;},&lt;&#x2F;span&gt;&lt;span&gt; into&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    {&lt;&#x2F;span&gt;&lt;span&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; replace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; replace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;{&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;password&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;map &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;password&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-variable&quot;&gt; @&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-module z-elixir&quot;&gt;filtered&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;},&lt;&#x2F;span&gt;&lt;span&gt; into&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    {&lt;&#x2F;span&gt;&lt;span&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; replace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; replace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;list&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; when&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; is_list&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;list&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span&gt; elem &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; list &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    case&lt;&#x2F;span&gt;&lt;span&gt; elem &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;password&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;password&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-variable&quot;&gt; @&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-module z-elixir&quot;&gt;filtered&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;      {&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;password&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt; {&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;password&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-variable&quot;&gt; @&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-module z-elixir&quot;&gt;filtered&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; replace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      other &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; replace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;other&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; replace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;other&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span&gt; do: other&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This snippet will replace all occurrences of &lt;code&gt;:password&lt;&#x2F;code&gt; or &lt;code&gt;&quot;password&quot;&lt;&#x2F;code&gt; with
filtered out value.&lt;&#x2F;p&gt;
&lt;p&gt;The disadvantage of such approach - it will make all messages with such fields
allowed in case if your filter has &lt;code&gt;:filter_default&lt;&#x2F;code&gt; set to &lt;code&gt;:stop&lt;&#x2F;code&gt;. That mean,
that if you want to make some of them rejected anyway, then you will need to
manually add additional step to reject messages that do not fit into your
patterns. Alternatively you can use &lt;code&gt;filter_default: :log&lt;&#x2F;code&gt; and then use opt-out
logging. There currently is no way to alter the message and make other filters
decide whether log it or not (as of OTP 24).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;New features and possibilities with relation to logging in Elixir 1.11 can be
overwhelming. Fortunately all of the new features are optional and provided in
addition to &quot;good &#x27;ol &lt;code&gt;Logger.info(&quot;logging&quot;)&lt;&#x2F;code&gt;&quot;. But for the people who works on
the observability in BEAM (EEF Observability WG, Sentry, Logflare, etc.) it
brings a lot of new powerful capabilities.&lt;&#x2F;p&gt;
&lt;p&gt;I am thrilled to see what will people create using all that power.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>Treachery of Representation</title>
      <published>2020-04-27T00:00:00+00:00</published>
      <updated>2020-04-27T00:00:00+00:00</updated>
      <link href="https://hauleth.dev/post/treachery-of-representation/" type="text/html"/>
      <id>https://hauleth.dev/post/treachery-of-representation/</id>
      <summary>Representation is not data - something that developers (and not only them)
often forgot when working with different data.</summary>
      <content type="html">&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;treachery-of-images.jpg&quot; alt=&quot;Treachery of Images&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I had that discussion on different chats few times already, but it is always
troublesome for people (not just programmers):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Representation is not data&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And this concept is confused &lt;strong&gt;a lot&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Almost any of you know that you can do &lt;code&gt;ping 1.1.1.1&lt;&#x2F;code&gt;, however did you know that
you can also do &lt;code&gt;ping 16843009&lt;&#x2F;code&gt; and the result will be the same? Magic? Not
really. What we commonly treat as an IPv4 address &lt;code&gt;1.1.1.1&lt;&#x2F;code&gt; is only textual
representation of the IPv4 which in reality is single 32-bit number which is
represented as dot separated 8-bit values just out of convenience. The same
applies to SHA-1 hashes, UUIDs, etc.&lt;&#x2F;p&gt;
&lt;p&gt;We people are great in finding patterns and simplifications, so when one sees
something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-----BEGIN PGP PUBLIC KEY BLOCK-----&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mQINBFd1CwMBEADTJG+QszZ9JK6G+IZpvK&#x2F;g8mJicqKVTV1OmI1toIml5c&#x2F;5r&#x2F;70&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dBc1FuASTM58PPZYJoKkbIh489QIvTm+8UdYu9zNRkT33el7pW1lEe5A6sq2bvoY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;GE8DioHTewdoSDPf7KIaZQeRcIY4n93rUOwA6GEtNpyYGP6ss5Y7BGk4ltSioe7N&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;o+4ZmWoQZwZzRon3t1eWVVP9tRMG5nLzL3XA5FK8TqoYuuIOR0Kw9+yK&#x2F;CIJi6EV&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NGXidQEhRX&#x2F;e6cDcqmo6LQuQluuhpwKjD3rVIq5P55kDcyUXHkcr9&#x2F;RBIY1GCw0m&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;r03H053xYhPib4S3fkcGMz1zrvgPR8M6T8VYXERZDjKzQbkkjKx2umP+MQb57N&#x2F;m&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Ndr+vks5PoPOPTGS9DYPaWf0fTVWQz&#x2F;Wr6SuqKYWOObw2Ql1fOFS9dlQ26VHqtdP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;CjCS&#x2F;+kxTWP0SNIlvmICj68JNq0Elti8DNF+8K4U&#x2F;zjqphqLUOMYo+bfxF3Xudlx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;…&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;X5tXXRd2Jx3rkquLhlOaIfwx5ZKkc0jFvFq6L6iQ8M3w2osTTQ8wzLVrKcA&#x2F;1E37&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vzFw0eLlAHxqKKx8AGXhlG+bu4z9&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;=HbWE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-----END PGP PUBLIC KEY BLOCK-----&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then they will automatically say that this is PGP public key, however it is not!
This is only armored (textual) representation of such. We can find infinite
amount of ways to represent this in different formats that will suit our needs.
We can use binary format, we can post it as huge integer:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1657454081776872747238013876359322713234391537499703933766980145269184386317049&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8330933605635736383746482612365150874768089262930090931944711968773749521913699&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7027071169368463413472374786860753667060249108643195012586135134901393013828317&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1125513524511702912188470760919764295140961468869648430645347829208242125220011&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3151968877120814976862830922750002170809783899223077039784557147675345249970781&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5464553976008128226157133495317638249211710007765696991167161819945117066390428&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3919051957061561015867974004807638646034325543036054946820462087690124141551114&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9854678368254378572150652196681912690617688434615368858186497935662439355552496&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4729580502224487557084501045154245589928832642849687361389957940229955065758222&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6366651257907657297666835432894495612402178521246832570964915000759172307812244&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6160593540459285722105074344450899751799861113519463231780643100018160335021016&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1172711806124926227346822406879926575104066365513850591901167977031017773147553&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3494796072257580113875396010361380353105632085492892479603715336182682602428143&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5608690637230685977144014723666813959973503662453370415571851701179428151882882&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8889353256564968091064157105454996484998754991348566666564916601887263240881070&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4832198618558083182213501188928625277122728831796445123889707032846261305648630&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2527176048898518342591580941543224978208167594213111446673112848581061191825984&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1291021894031447958561527430552161385666081569185835507259834732917990092146589&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8117077934368522739843309368028814069423002395997449936891495583107309283509271&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1180077432800679370662483747523408021854844321836016009650358574989381886337852&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1722516883913145519094014205375128862340002341518180047810642843228568880540172&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3417922325879216322183112046755680152782225539937453280161300294135511699130848&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0976433759293246140554344092404212626999402181891603820290765820423321186458935&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1984485518225135337585187247603955326905920439923621172092130464391731498388744&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8750392578000721268878463072511675222925230106406594118598329633269324358794764&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4929066475821912729913815944439237132097525066761248367529760023296968812652711&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1354078624366444615698555226671150629567656072692570827367021777825853318746140&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2863318577339635525264674498700520998767957283494612638659115064541050609931927&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0626267703727694820552442716314957841578389580288169926927235290811137237887434&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4221841397313800123531757418475100660454200912589623058183943877051413097869194&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2339339754985429142461984170624136785051296102102697817632037910221364646864651&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9855796964298457614203439681372147302465919398126442059583983219983682993673878&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5195511144366725918343436684113783818943460018156359275075623210303933783990867&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1450770230403557029292899962005967013424432778295850913345133681904640414130225&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6074976712103846157531047532174675106877834562907257767751866399263004265826476&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2927779415738730155062074319337848630585696081256539500213340093725740025118088&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1549556332762444079547546812082703704589345493095057789148939194264110489919019&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4566170053142149254913384680974964028594308712215301647785051390937700375621904&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6850793920957951588471978130651986351908543266002688052663010508763853950782008&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2184664457189708083557342565742275344614046037371745586008320578024563750973078&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8918522749313602046891225282398255933496131418430638794803291508377033406843725&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5993318777198284973711860102116509775279126577240620025658230260626934855295524&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0163482197624118826096325983427230149324714688555788577159485966979794672252786&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2049579060682321390550407916111513505775215286804094663126348519235979240267931&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1393177415036576603095965158893137047832256486627193835346772464826381170364046&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9672727436992842647585191196834755720506018282532384722445185130057363544741494&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9620010167886013834746116804462363836560880757170533362435237472884909654085819&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2200315846789415790035979932125380804930427597237917426179754754825031469057587&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5408385218092192305802900158223031488228733997920493838052062060383233685427730&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2479303637471252558356068491271641497786414938837109276566129349124360527596986&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0939690673802611552820885948021359288569430897510414990828683956519429277901630&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3954037665434237643444138532861028612543250728043306643540240455527506302759025&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2547253114427400839942700506775082503198395916277602696346477632254520324291510&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7176423995375530679412205690580599798550778233049642580773735945645101772412041&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9770061447364487938863821369661007066965634140967634082532169232884947757170676&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4001778436464233464495522570739848976059303542657842980445747616892332657374307&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3505719849994753220744681385854225182109628156151628193674787620122409837550175&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0873904989000402627417710830371222663052469412680310145900108150056384479011904&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2835209300157229749112634620468892621559922849964862659975166458450846483410310&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9108533277021935459848755879666329563851612903497154909548344186653653532596030&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1909102262515819267424216040525600483418895125777391628629285735284199384249913&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4569616259150374342828948745370477195614375418738814522169402762983961841736104&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6795438095408475881223956725863549758305981513146677968273034768754628733774741&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5601175386054118189600876918455578756071642172440419960753296039010117418642333&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0700157761536698272554982837358908293635750455157297675798024638098958969267103&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6863406950021125691193872800648046146136177370993251603456335654259717488367827&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4221891453042458615303763101765455461453483141839094655158338636716818847773378&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3089958604524376415306549473187862340575705348685942443697841897636463859949926&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4444464568286807145435412305718175821967958934523535510530750957533464207224580&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2279373368828019548205439249352189164575083536583721094688224573324098240189090&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5336968277502282844656778779596324101840145138970262636945152077842421376473220&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7492641493346476621126619083363859115527821109445021807274717048079752479814069&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8489075707866445180273917549185493159488867602009975459154326516617446093785735&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7657409659738148136025968774346968795138906298743560267773358615395905430092434&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4090587183336112957335092481531071573600577415752552329335484584825448451281828&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8397267947223750920443272557916925997060835636847307503958963847413230458654999&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1510218368567378788057116023931994479266585942028846093606765504042151064449401&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7535053560571943565326163798733090077562063019270432774405336624206120162684878&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2795961016400131165092351347259003395336488326011264715606875560607985355101479&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1760498444803027184543196012361666512501664115266209446783611568980849759393366&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9004607206787763941830633066297736259437811557856982004496007136271945140295164&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1021123058841472126203195417354602182201593697351601555663719500088120144234523&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6489841188841869277921900098197497636848312736842577887524394082685476810652434&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4368023998666968889307055236194661569426524463555778731728379410827687126847841&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9767542567328134223554830928399001003746312827667717886760656045983730239481725&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0247192299979431368314503262526820359421826762698555934534502139292008724527340&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8566373287784944330515935635629564982235980178134875308234950470548865802766425&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3860142806266365958072884321048903006167833769100547151312160642686817573070175&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8517347856656124090595544002510378196552188147101332012713619529417880258338847&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9548595874229820385574539354556804227765871124740709294288382971201998678678558&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1135393032892116765181068789505132747404363007086649489491404624220840121961493&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9770980821410301887703418151100099801563662384204228166203260763728750184267283&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0131194615371938999731752172864595591147593535783229858980094812827904216900881&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0264484164635513605434976822336090709152508883040986176420243997392303278619543&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7132483818824284005791373572104029624554831023783619373272102143855002602772145&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1625555397693952027234647740913597061447733291018249879406776786602117249183252&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3028866932885668665387107476073897428999191152484269358567755332923524842064600&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3794929412192609471679420879441380627388660584277219132508113058600032222404868&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2912812185436951502936757180777020507704813293182422695970566889605944405493165&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1013050164683342445192514465075993459075480256309099680013258781889270979210377&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2978191200620386753171174166739274414356307635252359045515977252139725132495302&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4643451106675617568043015073444443099894159838269138387489278049925887086707284&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7829572513234800005657626866917894409850513692287942317924246061209211855433159&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9474862901923613493886199119281189221558415812534549155894713481042125093206748&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5327877884372067603958264162802943954426330867112852706462838411380034486572690&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0832825677844671600199639823373591008100835318576086939856769129801540454104086&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1677822021197754242364262145059312498290181267047980332959890135114462272477083&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2267001649763807453258389353505463199327476285470780889266423077199955133598911&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4228000626496272875548822896127419699372645929502724379809375313984715132685176&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4622127184084472238931211915326009413737074357833496656532089093339434182463301&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4308133856938907909683630708624133178764345576977957526210285792755588339502313&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8908965753207073692034844982785108219589789141504389489294521808974273153775683&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4710352841094853913320997396720648350856909009547717827126308937619267105900330&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5101845147776164022119091114165228791856934734405699522377750777712347632477472&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1009173135645423776920173241282009759190193451325534130721465706915799208352319&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7599436014849832502702741642253476812447287458898351283245611697635355626967353&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1666248190388798775893317097285333032144668959144551590316718826094121548655064&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7327190413743862383571166391385591854324294967408637687666499017919659934556270&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6341760473807628223322195796330107447627192021125501916257505545056806593020009&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7877518699192190569125611877551646125360935329152981694983591991442830972118425&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6024578420108611596786779391910078283535602332400676206290364979979566874130677&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6262721807685562884678614519635750114010818380727834704599313495363241399979019&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0070441245844791323697888362361156445150402411489057842369956860981561106349532&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0427329254749281230185541338204013332686802017845355478766281601177626930879718&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3924781109376832016663185405467845874107109473909888472781931298639743129405819&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9018728534014004893438844921156199392052668509822766055873031732621412819415997&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5106658073874599600482906898626458321908644717727705714148184312035554569461172&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2571014234210898150511238337764888383510750920318252617219954833323650772315822&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8694765635893382122506622111504457282650772215884112102663088591828929423478423&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4630228876316754232955789012778765153858505693804419173581459528959967049577393&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3203503330240909044864203529502068033769777504652970513017398216284525619584395&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7399576075789549294657904493999442658423657409794863027890740986637503143358200&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1934990177507763078658788020042351989886877390781804018450451154174423611071016&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3402098758156739497049080279046203857466871438452835345118677125325469128068133&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1366454054797295342986762057003055457075865166635455089017691661317421628642115&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4993805637263456481774330967345531754745117304815930559577694749501153002539548&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5404256140871044730263074060283878378820730250169561914787775689729320033889071&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6450665587233640719268830704525315924153018596256798187945369509492198616718735&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1727110697661735449130358956047142033543848955222885833760237898733698724067547&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8419101187420106748225373809326555034920972273032855852671672606413074751824780&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5154501659974029329400410688611596507780739224024571262805816781734162995302986&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6056046847929263719956354500493986529434154889061593903845247605955487265601755&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6043989537334852057279780609368927725387526205357590787648273036069019155497325&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7284579301234574132272242978804776467287642325689728908190752748762036032550553&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0297580281513471442798728664035839834832168788094160691038978903832691745390723&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8280774908923640913005731937007494753031663001263187085109076785504199996190411&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2645973159719700472616661742318567810513248327998862965177705803004760763074321&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2313603449759152065701241959565937761991117902298693865777609004090724789824238&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3972666226870968534310397976577839690259724502877323852210276007099716458281622&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0266833622323608118226700555948541874878778700732590694206338358355846043998302&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2076998169472117379362890485627714537422759747305703434242979589456473320420530&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3798100254154945537756689378818628238489975669085399495869198707118002332356201&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2860990261282434269797439143900692337984204234325905652408969984088094424603914&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1324281031601472803905094128246361871536795078781179969095901324385165589352908&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5570928042409387112284705341815718794836739937616493333506970623215543845017075&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9783614942442566404035374016694617857746139989520230332862060498894309587704609&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2307147218032013573247425767983972450327115251550658313094143782360088885333289&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5608157274415946459185147621933085094399365522400749862053761657227728398780469&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7624550738125029927864820017089079162293784666905532642099274666498693255031122&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2889026525933407361948759134200215183348933115884125348251449445229741605009136&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5213445919902677380093249284489832185317941999559970629694476644944502557922299&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4045467263054565580347599600913022630568314834909143526070011238471771326443583&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5999517514967645625805546197521789593944893957635299668589873242979729214565080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2261124045260532526154306748833731566597485067054072337617187788422439611692535&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6816154352988676611143089545607089006494597803681742408872009589972348314218354&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5885756829028538416517815718956811889863727858335798002033148984814372442071252&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2067544365025698588181983841271622441543580184070308095038169545529105805899001&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5825565028451412722300055213104773432923209992505613530612435181227942384006400&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6523874291660768676182135558923684054785558197662748591717032047925055385422584&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;8826587112169068650291428518318455696828296955217726852703371476729712500873714&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9472757285042561083989577043290348125840395005244750850424202067248954262318073&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3815815411200758900340511052777147951522351782525348580404031636340281256009099&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3622685663270098759448305092624146163465790024589793366278716865415624355235291&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3985878069536487297514629837101726802175517221106646456169044468305875210017956&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3762872046696988950422497705388225997904571624738961093738188347083184831994615&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5653340873908308859802165057177945265893576798033839250748977766722025452484918&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4969906442004769360577067228954632576483279588054785969942183381969384204862823&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5527295851917376805942967603231125591852023457112648669282453139677076502138626&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9831545895899997311194908866099892662200438185858903893802349550297108232343975&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7063807807&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Before you ask - yes, this is my PGP public key as a single decimal integer.&lt;&#x2F;p&gt;
&lt;p&gt;Next time you will see someone asking for &quot;shorter UUID&quot; you can point them
there and say - just pick shorter representation.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>Stop Spreading Crap at My `$HOME`</title>
      <published>2020-04-15T12:00:19+02:00</published>
      <updated>2020-04-15T12:00:19+02:00</updated>
      <link href="https://hauleth.dev/post/stop-spreading-crap-at-my-home/" type="text/html"/>
      <id>https://hauleth.dev/post/stop-spreading-crap-at-my-home/</id>
      <summary></summary>
      <content type="html">&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;&#x2F;strong&gt; Yes, this is a rant. Yes, I am displeased with state of
software. And yes, I can use some harsh words. You were warned.&lt;&#x2F;p&gt;
&lt;p&gt;For a some time now we have &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Filesystem_Hierarchy_Standard&quot;&gt;Filesystem Hierarchy Standard&lt;&#x2F;a&gt; which describes
which data goes where in your *nix installation. In fact we have that for 28
years, which is almost as long as I live. This is quite some time. But for
whatever reason we apply that only for the system hierarchy and we cannot have
the same for something much closer to our heart - our dear &lt;code&gt;$HOME&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Common practice for storing all the stuff for different applications is to use
dot files stored in &lt;code&gt;$HOME&lt;&#x2F;code&gt;. These are files or directories starting with dot in
their name which makes such files &quot;hidden&quot; on Unix systems. There is problem
though. First let me show you all the files starting with dot in my &lt;code&gt;$HOME&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-r--------  1 hauleth staff     9 Mar 30  2019 .CFUserTextEncoding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-r--r--  1 hauleth staff 16388 Apr  9 11:46 .DS_Store&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwx------  2 hauleth staff    64 Apr 13 20:54 .Trash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-------  1 hauleth staff 17835 Apr 10 21:17 .bash_history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwx------ 12 hauleth staff   384 Mar 30  2019 .bash_sessions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x 13 hauleth staff   416 Mar 26 14:02 .cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lrwxr-xr-x  1 hauleth staff    40 Aug 21  2019 .chunkwmrc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x 20 hauleth staff   640 Apr 15 21:59 .config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwx------  3 hauleth staff    96 Apr 20  2019 .cups&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lrwxr-xr-x  1 hauleth staff    39 Aug 21  2019 .curlrc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lrwxr-xr-x  1 hauleth staff    43 Aug 21  2019 .dir_colors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-r--r--  1 hauleth staff  2587 Sep 10  2019 .direnvrc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  6 hauleth staff   192 Apr 14 18:27 .docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwx------ 14 hauleth staff   448 Oct  1  2019 .dropbox&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-r--------  1 hauleth staff    20 Apr  1  2019 .erlang.cookie&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  3 hauleth staff    96 Jul  1  2019 .gem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-r--r--  1 hauleth staff   518 Mar 25 22:44 .gitconfig&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwx------ 14 hauleth staff   448 Apr 15 22:03 .gnupg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  4 hauleth staff   128 Apr  2  2019 .hammerspoon&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  5 hauleth staff   160 Apr 14 19:39 .hex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwx------  3 hauleth staff    96 Apr 26  2019 .httpie&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-r--r--  1 hauleth staff   165 Feb 22 13:50 .jlassetregistry.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  3 hauleth staff    96 Nov 29 22:13 .jssc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  9 hauleth staff   288 Feb 21 17:46 .julia&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwx------ 14 hauleth staff   448 Oct  2  2019 .keychain&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-x---  5 hauleth staff   160 Jan 24 12:20 .kube&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-------  1 hauleth staff   720 Apr 15 16:29 .lesshst&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-x---  3 root    staff    96 Apr  3  2019 .lldb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwx------  4 hauleth staff   128 Dec 18 14:16 .local&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  8 hauleth staff   256 Mar 20 12:29 .mitmproxy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x 18 hauleth staff   576 Apr 13 14:36 .mix&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-r--r--  1 hauleth staff   116 Apr 13 20:59 .nix-channels&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  4 hauleth staff   128 Apr 14 13:47 .nix-defexpr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lrwxr-xr-x  1 hauleth staff    46 Feb  1 22:13 .nix-profile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  3 hauleth staff    96 Sep 27  2019 .npm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  3 hauleth staff    96 Dec 19 14:05 .pex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-r--r--  1 hauleth staff   183 May  2  2019 .profile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  5 hauleth staff   160 Mar 20 16:27 .proxyman&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  2 hauleth staff    64 Feb 17 14:09 .proxyman-data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-------  1 hauleth staff  1391 Jan 22 11:46 .psql_history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-------  1 hauleth staff  1950 Feb 19 12:42 .python_history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lrwxr-xr-x  1 hauleth staff    37 Aug 21  2019 .skhdrc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwx------ 11 hauleth staff   352 Oct  2  2019 .ssh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  4 hauleth staff   128 May  8  2019 .terraform.d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  4 hauleth staff   128 Dec  1 21:52 .thumbnails&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x  9 hauleth staff   288 Mar  9 17:14 .vagrant.d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-------  1 hauleth staff 11124 Apr 13 20:21 .viminfo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lrwxr-xr-x  1 hauleth staff    37 Aug 21  2019 .vimrc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwx------  4 hauleth staff   128 Nov  8 16:51 .w3m&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x 37 hauleth staff  1184 Apr 13 21:21 .weechat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, there is bunch of them, some are linked to my dotfiles
repository, but most are not. What is the problem there?&lt;&#x2F;p&gt;
&lt;p&gt;The spread.&lt;&#x2F;p&gt;
&lt;p&gt;All of the data is smeared between gazillion of different filed with different
types of data. This causes headaches because:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I cannot easily backup all the configuration as I need to check each file
independently to check if this is configuration file or it is data&lt;&#x2F;li&gt;
&lt;li&gt;I cannot exclude data from my backups in a uniform way. I need to check each
file independently and exclude it, remembering to do that for each new tool
that I add. Alternatively I can use whitelist instead of blacklist of paths
that I want to backup, but that pretty much defies the idea of having
automatic backup.&lt;&#x2F;li&gt;
&lt;li&gt;Cleaning up the old caches and data is troublesome as user need to review all
the folders and know what data they see mean.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But what We can do? Well, the macOS and Windows got it somewhat right, these
OSes provide special paths for storing all configuration, caches, user-data,
etc. in special, dedicated, and well known locations within user directories. It
is like mentioned earlier FHS but for &lt;code&gt;$HOME&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately no other OS out there had:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Power to force developers to behave reasonably&lt;&#x2F;li&gt;
&lt;li&gt;Standard to which developers should adhere to&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Unfortunately the 1st point is still true, but the 2nd one is somewhat resolved
in form of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;specifications.freedesktop.org&#x2F;basedir-spec&#x2F;latest&#x2F;index.html&quot;&gt;XDG Base Directory Specification&lt;&#x2F;a&gt;. This is pretty short,
simple, and straightforward spec where which data should go.&lt;&#x2F;p&gt;
&lt;p&gt;This makes life so much easier:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Want to have backup your configuration? Just copy &lt;code&gt;$HOME&#x2F;.config&lt;&#x2F;code&gt; where you
want.&lt;&#x2F;li&gt;
&lt;li&gt;Want to reset your configuration to base one? Just delete &lt;code&gt;$HOME&#x2F;.config&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Want to cleanup caches? Remove &lt;code&gt;$HOME&#x2F;.cache&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It makes your &lt;code&gt;$HOME&lt;&#x2F;code&gt; much cleaner, much more manageable, much more like your
place, where you are the ruler, not as a manager of the bulletin board or the
storage house.&lt;&#x2F;p&gt;
&lt;p&gt;At one point I was even considering to have approach similar to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grahamc.com&#x2F;blog&#x2F;erase-your-darlings&quot;&gt;one taken by
Graham Christensen&lt;&#x2F;a&gt;, but that would make my life even more
miserable instead of forcing developers to fix their software.&lt;&#x2F;p&gt;
&lt;p&gt;Just in case, this is not only mine view on the state of configuration files,
just see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20180827160401&#x2F;plus.google.com&#x2F;+RobPikeTheHuman&#x2F;posts&#x2F;R58WgWwN9jp&quot;&gt;old Google+ post by Rob Pike&lt;&#x2F;a&gt; where he states exactly the same
thing that FreeDesktop team try to address. I may not agree on all the concepts
with Commander, but this one I vote all-fours.&lt;&#x2F;p&gt;
&lt;p&gt;For these who want to stop that madness and fix at least some software out there
that is broken, you can check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hauleth&#x2F;xdg-rlz&quot;&gt;my script&lt;&#x2F;a&gt; that tries to fix
(at least partially) non-conforming software.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Please, stop leaving your c**p in my &lt;code&gt;$HOME&lt;&#x2F;code&gt; and call it &quot;installation&quot;. If
you want that, then I think you should find nearest Modern Art Gallery.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;You can comment it on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;s&#x2F;va7gic&#x2F;stop_spreading_c_p_at_my_home&quot;&gt;Lobste.rs&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;programming&#x2F;comments&#x2F;g2210g&#x2F;stop_spreading_cp_at_my_home&#x2F;&quot;&gt;Reddit&lt;&#x2F;a&gt;
or @ me on Twitter.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>Writing Vim Plugin</title>
      <published>2019-11-04T18:21:18+01:00</published>
      <updated>2019-11-04T18:21:18+01:00</updated>
      <link href="https://hauleth.dev/post/writing-vim-plugin/" type="text/html"/>
      <id>https://hauleth.dev/post/writing-vim-plugin/</id>
      <summary>Article about writing Vim plugins, but not about writing Vim plugins. It is
how to conceive plugin, how to go from an idea to the full fledged plugin.</summary>
      <content type="html">&lt;p&gt;While there are many &quot;tutorials&quot; for writing plugins in Vim, I hope this one
will be a little bit different from what is out there, because it won&#x27;t be
about writing plugin &lt;em&gt;per se&lt;&#x2F;em&gt;. If you want to find information about that then
you should check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimhelp.org&#x2F;usr_41.txt.html#write-plugin&quot;&gt;&lt;code&gt;:h write-plugin&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. I want this article to be about how
plugins come to life, using my own experience on writing
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hauleth&#x2F;vim-backscratch&quot;&gt;&lt;code&gt;vim-backscratch&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; as an example.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;problem&quot;&gt;Problem&lt;a class=&quot;zola-anchor&quot; href=&quot;#problem&quot; aria-label=&quot;Anchor link for: problem&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;All plugins should start with a problem. If there is no problem, then there
should be no code, as there is no better code than &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kelseyhightower&#x2F;nocode&quot;&gt;no code&lt;&#x2F;a&gt;. In this
case, my problem was pretty trivial: I wanted a temporary buffer that would let
me perform quick edits and view SQL queries while optimising them (and run them
from there with Tim Pope&#x27;s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tpope&#x2F;vim-dadbod&quot;&gt;dadbod&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;simple-obvious-solution&quot;&gt;&quot;Simple obvious solution&quot;&lt;a class=&quot;zola-anchor&quot; href=&quot;#simple-obvious-solution&quot; aria-label=&quot;Anchor link for: simple-obvious-solution&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have defined the problem, we need to try the first possible solution.
In our case, it is opening a new buffer in a new window, edit it, and then close it
when no longer needed. It is simple in Vim:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&amp;quot; Edits&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:bd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unfortunately this has bunch of problems:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;if we forgot to close that buffer, then it will hang there indefinitely,&lt;&#x2F;li&gt;
&lt;li&gt;running &lt;code&gt;:bd!&lt;&#x2F;code&gt; in the wrong buffer, can have unpleasant consequences,&lt;&#x2F;li&gt;
&lt;li&gt;this buffer is still listed in &lt;code&gt;:ls&lt;&#x2F;code&gt;, which is unneeded (as it is only
temporary).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;systematic-solution-in-vim&quot;&gt;Systematic solution in Vim&lt;a class=&quot;zola-anchor&quot; href=&quot;#systematic-solution-in-vim&quot; aria-label=&quot;Anchor link for: systematic-solution-in-vim&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Fortunately Vim has solutions for all of our problems:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the &quot;scratch&quot; section in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimhelp.org&#x2F;windows.txt.html#special-buffers&quot;&gt;&lt;code&gt;:h special-buffers&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which
solves the first two problems,&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimhelp.org&#x2F;windows.txt.html#unlisted-buffer&quot;&gt;&lt;code&gt;:h unlisted-buffer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which solves the third problem.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So now our solution looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;setlocal&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; nobuflisted buftype&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;nofile &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;bufhidden&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;delete &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;noswapfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&amp;quot; Edits&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:bd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However that is a long chain of commands to write. Of course we could condense
the first two into a single one:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:new &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;++&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;nobuflisted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;buftype&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;nofile &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;++&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;bufhidden&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;delete &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;++&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;noswapfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But in reality this does not shorten anything.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-a-command&quot;&gt;Create a command&lt;a class=&quot;zola-anchor&quot; href=&quot;#create-a-command&quot; aria-label=&quot;Anchor link for: create-a-command&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Fortunately we can create our own commands in Vim, so we can shorten that to a
single, easy to remember command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;command!&lt;&#x2F;span&gt;&lt;span&gt; Scratch new &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;++&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;nobuflisted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;buftype&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;nofile &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;++&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;bufhidden&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;delete &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;noswap&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For better flexibility, I prefer it to be:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;command!&lt;&#x2F;span&gt;&lt;span&gt; Scratchify &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;setlocal&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; nobuflisted buftype&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;nofile &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;bufhidden&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;delete noswap&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;command!&lt;&#x2F;span&gt;&lt;span&gt; Scratch new &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;Scratchify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can also add a bunch of new commands to give us better control over our new
window&#x27;s location:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;command!&lt;&#x2F;span&gt;&lt;span&gt; VScratch vnew &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;Scratchify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;command!&lt;&#x2F;span&gt;&lt;span&gt; TScratch tabnew &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;Scratchify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Those commands will open a new scratch buffer in a new vertical window, and
a new scratch buffer in a new tab page, respectively.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;make-it-a-more-vimmy-citizen&quot;&gt;Make it a more &quot;vimmy&quot; citizen&lt;a class=&quot;zola-anchor&quot; href=&quot;#make-it-a-more-vimmy-citizen&quot; aria-label=&quot;Anchor link for: make-it-a-more-vimmy-citizen&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;While our commands &lt;code&gt;:Scratch&lt;&#x2F;code&gt;, &lt;code&gt;:VScratch&lt;&#x2F;code&gt;, and &lt;code&gt;:TScratch&lt;&#x2F;code&gt; are nice, they are
still not flexible enough. In Vim we can use modifiers like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimhelp.org&#x2F;windows.txt.html#%3Aaboveleft&quot;&gt;&lt;code&gt;:h :aboveleft&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to define exactly where we want new windows to appear
and our current commands do not respect that. To fix this problem, we can
simply squash all the commands into one:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;command!&lt;&#x2F;span&gt;&lt;span&gt; Scratch &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;mods&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;new &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;Scratchify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And we can remove &lt;code&gt;:VScratch&lt;&#x2F;code&gt; and &lt;code&gt;:TScratch&lt;&#x2F;code&gt; as these can be now done via
&lt;code&gt;:vert Scratch&lt;&#x2F;code&gt; and &lt;code&gt;:tab Scratch&lt;&#x2F;code&gt; (of course you can keep them if you like, I
just wanted the UX to be minimal).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;make-it-powerful&quot;&gt;Make it powerful&lt;a class=&quot;zola-anchor&quot; href=&quot;#make-it-powerful&quot; aria-label=&quot;Anchor link for: make-it-powerful&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This has been in my &lt;code&gt;$MYVIMRC&lt;&#x2F;code&gt; for some time in the form described above until
I found out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;romainl&#x2F;eae0a260ab9c135390c30cd370c20cd7&quot;&gt;Romain Lafourcade&#x27;s snippet&lt;&#x2F;a&gt; that provided one additional
feature: it allowed to open a scratch buffer with the output of a Vim or shell
command. My first thought was - hey, I know that, but I know I can make it
better! So we can write a simple VimL function (which is mostly copied from
romainl&#x27;s snippet, with a few improvements):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;function!&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; s:scratch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;mods&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; abort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; []&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    elseif&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:cmd[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;is&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;!&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =~&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39; %&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; substitute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39; %&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; . &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;expand&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;%:p&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; : &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; systemlist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;matchstr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;l:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;^!\zs.*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; split&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;\n&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    endif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    execute&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:mods&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; . &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39; new&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Scratchify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    call&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; setline&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;endfunction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;command!&lt;&#x2F;span&gt;&lt;span&gt; Scratchify &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;setlocal&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; nobuflisted noswapfile buftype&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;nofile &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;bufhidden&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;delete&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;command! -nargs=1 -complete=command&lt;&#x2F;span&gt;&lt;span&gt; Scratch &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;call&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;SID&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;scratch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&amp;lt;mods&amp;gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;, &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;q-args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The main differences are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;special case for empty command, it will just open an empty buffer,&lt;&#x2F;li&gt;
&lt;li&gt;use of &lt;code&gt;is#&lt;&#x2F;code&gt; instead of &lt;code&gt;==&lt;&#x2F;code&gt;,&lt;&#x2F;li&gt;
&lt;li&gt;use of &lt;code&gt;:h execute()&lt;&#x2F;code&gt; instead of &lt;code&gt;:redir&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As it is quite self-contained and (let&#x27;s be honest) too specific for &lt;code&gt;$MYVIMRC&lt;&#x2F;code&gt;
we can can extract it to its own location in &lt;code&gt;plugin&#x2F;scratch.vim&lt;&#x2F;code&gt;, but to do so properly we need
one additional thing, a command to prevent the script from being loaded twice:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; exists&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;g:loaded_scratch&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    finish&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;endif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; g:loaded_scratch&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;function!&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; s:scratch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;mods&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; abort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; []&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    elseif&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:cmd[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;is&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;!&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =~&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39; %&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; substitute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39; %&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; . &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;expand&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;%:p&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; : &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; systemlist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;matchstr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;l:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;^!\zs.*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; split&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;\n&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    endif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    execute&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:mods&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; . &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39; new&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Scratchify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    call&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; setline&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;endfunction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;command!&lt;&#x2F;span&gt;&lt;span&gt; Scratchify &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;setlocal&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; nobuflisted noswapfile buftype&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;nofile &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;bufhidden&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;delete&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;command! -nargs=1 -complete=command&lt;&#x2F;span&gt;&lt;span&gt; Scratch &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;call&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;SID&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;scratch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;q-mods&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;, &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;q-args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;to-boldly-go&quot;&gt;To boldly go…&lt;a class=&quot;zola-anchor&quot; href=&quot;#to-boldly-go&quot; aria-label=&quot;Anchor link for: to-boldly-go&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Now my idea was, hey, I use Vim macros from time to time, and these are just
simple lists of keystrokes stored in Vim registers. Maybe it would be nice to have
access to that as well in our command. So we will just add a new condition that
checks if &lt;code&gt;a:cmd&lt;&#x2F;code&gt; begins with the &lt;code&gt;@&lt;&#x2F;code&gt; sign and has a length of two. If so, then
set &lt;code&gt;l:output&lt;&#x2F;code&gt; to the spliced content of the register:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;function!&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; s:scratch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;mods&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; abort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    elseif&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:cmd[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;is&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;@&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; strlen&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getreg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            throw&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;Invalid register&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        endif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    elseif&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:cmd[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;is&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;!&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =~&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39; %&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; substitute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39; %&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; . &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;expand&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;%:p&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; : &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; systemlist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;matchstr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;l:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;^!\zs.*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; split&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;a:cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;\n&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    endif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    execute&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; a:mods&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; . &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39; new&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Scratchify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    call&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; setline&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:output&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;endfunction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This gives us a pretty powerful solution where we can use &lt;code&gt;:Scratch @a&lt;&#x2F;code&gt; to open
a new scratch buffer with the content of register &lt;code&gt;A&lt;&#x2F;code&gt;, edit it, and yank it
back via &lt;code&gt;&quot;ayy&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pluginize&quot;&gt;Pluginize&lt;a class=&quot;zola-anchor&quot; href=&quot;#pluginize&quot; aria-label=&quot;Anchor link for: pluginize&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Now, it would be a shame to keep such a useful tool for ourselves so
let&#x27;s share it with the big world. In this case we need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a proper project structure,&lt;&#x2F;li&gt;
&lt;li&gt;documentation,&lt;&#x2F;li&gt;
&lt;li&gt;a good catchy name.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can find help on the two first topics in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimhelp.org&#x2F;usr_41.txt.html#write-plugin&quot;&gt;&lt;code&gt;:h write-plugin&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimhelp.org&#x2F;usr_41.txt.html#write-local-help&quot;&gt;&lt;code&gt;:h write-local-help&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
or in any of the bazillion tutorials on the internet.&lt;&#x2F;p&gt;
&lt;p&gt;Finding a good name is something I can&#x27;t help you with. I have picked
&lt;code&gt;vim-backscratch&lt;&#x2F;code&gt;, because I like back scratches (everyone likes them) and, as
a nice coincidence, because it contains the word &quot;scratch&quot;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Creating plugins for Vim is easy, but not every functionality needs to be
a plugin from day one. Start easy and small. If something can be done with
a simple command&#x2F;mapping, then it should be done with a simple command&#x2F;mapping
at first. If you find your solution really useful, then, and only then, you
should think about turning it into a plugin. The whole process described in this
article didn&#x27;t happen in a week or two. It took me about a year to reach the step
&lt;em&gt;Make it a more &quot;vimmy&quot; citizen&lt;&#x2F;em&gt;, when I heard about romainl&#x27;s script on IRC.
I didn&#x27;t need anything more, so take your time.&lt;&#x2F;p&gt;
&lt;p&gt;Additional pro-tips:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;make it small, big plugins will require a lot of maintenance, small plugins
are much simpler to maintain,&lt;&#x2F;li&gt;
&lt;li&gt;if something can be done via a command then it should be made as a command,
do not force your mappings on users.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>Let&#x27;s talk about `application&#x2F;0`</title>
      <published>2019-07-26T00:00:00+00:00</published>
      <updated>2019-07-26T00:00:00+00:00</updated>
      <link href="https://hauleth.dev/post/elixir-application/" type="text/html"/>
      <id>https://hauleth.dev/post/elixir-application/</id>
      <summary>Have you ever thought about that one simple function in your `mix.exs`? It
comes out as quite powerful and useful place for storing configuration and
post-launch scripts.</summary>
      <content type="html">&lt;p&gt;When you start your new Elixir project via &lt;code&gt;mix new my_awesome_project&lt;&#x2F;code&gt; you will
end with something like this in &lt;code&gt;mix.exs&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; MyAwesomeProject&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Mixfile&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Mix&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Project&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;my_awesome_project&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      # …&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      deps&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; deps&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; application&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      extra_applications&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  defp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; deps&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      # …&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And in most cases you will focus on &lt;code&gt;deps&#x2F;0&lt;&#x2F;code&gt;, sometimes on &lt;code&gt;config&#x2F;0&lt;&#x2F;code&gt;, but the
&lt;code&gt;application&#x2F;0&lt;&#x2F;code&gt; you will almost never touch, and if you do, you probably will only
need it to add new entry in &lt;code&gt;:extra_applications&lt;&#x2F;code&gt; or sometimes
&lt;code&gt;:included_applications&lt;&#x2F;code&gt;. Except for, that this function interns are terra
incognita, a place where you never look unless you are forced to, like &quot;Read
it later&quot; list in Safari. This is sad, as it is quite powerful and useful
piece of code.&lt;&#x2F;p&gt;
&lt;p&gt;However first things first.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-application-0-is-for&quot;&gt;What &lt;code&gt;application&#x2F;0&lt;&#x2F;code&gt; is for?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-application-0-is-for&quot; aria-label=&quot;Anchor link for: what-application-0-is-for&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;In Erlang the running system is built from applications. Those applications are
like processes in your system managed by your system supervisor (SysV, systemd,
OpenRC, launchd, etc.). They are launched either during VM startup or on
direct user request via &lt;code&gt;Application.start&#x2F;1-2&lt;&#x2F;code&gt; and its family. Starting
this application is described in &lt;code&gt;my_awesome_app.app&lt;&#x2F;code&gt; file which is commonly
generated by the build system from the template. In Rebar3 projects this
template is &lt;code&gt;src&#x2F;appname.app.src&lt;&#x2F;code&gt; and in Elixir it&#x27;s the return value of the
named &lt;code&gt;application&#x2F;0&lt;&#x2F;code&gt; function. This generated file is known as &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.erlang.org&#x2F;doc&#x2F;design_principles&#x2F;applications.html#application-resource-file&quot;&gt;Application
Resource File&lt;&#x2F;a&gt;. It is just tuple in form of &lt;code&gt;{:application, :my_awesome_app, opts}&lt;&#x2F;code&gt; where &lt;code&gt;opts&lt;&#x2F;code&gt; is a keyword list of additional properties
(to be exact it&#x27;s output of the &lt;code&gt;application&#x2F;0&lt;&#x2F;code&gt; function).&lt;&#x2F;p&gt;
&lt;p&gt;Two of those optional fields are quite known in the Elixir community:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:mod&lt;&#x2F;code&gt; which is a tuple &lt;code&gt;{module(), term()}&lt;&#x2F;code&gt; containing the starting point
of our application; in most cases this is the module that will return main
supervisor of the application.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:applications&lt;&#x2F;code&gt; contains all applications required by our application; younger
Elixir developers possibly never seen that as since version 1.5 this field
is automatically filled by parsing &lt;code&gt;:deps&lt;&#x2F;code&gt;, though we still can add entries
there via &lt;code&gt;:extra_applications&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There are also few Elixir specific fields, sometimes used in larger projects:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:extra_applications&lt;&#x2F;code&gt; - those should be included in the release
and automatically started before running current application; but aren&#x27;t in the
dependencies list because, for example, are in default distribution, for
example &lt;code&gt;logger&lt;&#x2F;code&gt; or &lt;code&gt;inets&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:included_applications&lt;&#x2F;code&gt; - applications which should be included in the
release, but not automatically started on boot.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Wait, there is more!&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately not all of the highly useful keys are used&#x2F;known in the community.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;application-environment&quot;&gt;Application environment&lt;a class=&quot;zola-anchor&quot; href=&quot;#application-environment&quot; aria-label=&quot;Anchor link for: application-environment&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;For some reason everyone calls it configuration, so if you are familiar with
&lt;code&gt;config&#x2F;config.exs&lt;&#x2F;code&gt; and for some reason you decided to go &lt;a href=&quot;https:&#x2F;&#x2F;hauleth.dev&#x2F;post&#x2F;elixir-application&#x2F;guidelines&quot;&gt;against the &lt;em&gt;Library
Guidelines&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; and you have decided to use application environment for
configuring your code (there are reason to do so, even when you publish your
code as a &quot;library&quot;, see &lt;code&gt;lager&lt;&#x2F;code&gt; or &lt;code&gt;opencensus&lt;&#x2F;code&gt;) then you will soon find that
putting configuration in your&#x27;s library &lt;code&gt;config&#x2F;config.exs&lt;&#x2F;code&gt; do not matter much
in it&#x27;s dependants. You have 2 possibilities how to solve that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;Application.get_env&#x2F;3&lt;&#x2F;code&gt; and define your &quot;default&quot; as a 3rd argument.&lt;&#x2F;li&gt;
&lt;li&gt;Use &lt;code&gt;:env&lt;&#x2F;code&gt; to set data that should be loaded to application environment by
default.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Be wary that the second option works only  for current application, so you
cannot configure other applications (for example &lt;code&gt;logger&lt;&#x2F;code&gt;) there. &lt;em&gt;But what is
the point?&lt;&#x2F;em&gt; You may ask, and I found one. If you want to use default
&lt;code&gt;sys.config&lt;&#x2F;code&gt; file for configuring your application then sometimes few pointless
configuration option can land there, like &lt;code&gt;:ecto_repos&lt;&#x2F;code&gt; variable which truly
doesn&#x27;t matter much in production as it&#x27;s only used by Ecto&#x27;s Mix tasks. What
I do is to add new entry in &lt;code&gt;application&#x2F;0&lt;&#x2F;code&gt; with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ecto_repos&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;MyAwesomeApp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Repo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And call it a day. Now I can focus on keeping &lt;strong&gt;real&lt;&#x2F;strong&gt; configuration options in
&lt;code&gt;config&#x2F;config.exs&lt;&#x2F;code&gt; and remove unneeded fields from there. But remember that you
still can override these values by setting them in &lt;code&gt;sys.config&lt;&#x2F;code&gt; if needed, so
this is pure win for me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;start-phases&quot;&gt;Start phases&lt;a class=&quot;zola-anchor&quot; href=&quot;#start-phases&quot; aria-label=&quot;Anchor link for: start-phases&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Application configuration also allows you to define additional pieces of code to
be run after your application started. For example imagine situation when you
want to send Slack notification that given node started and is ready to work.
You can do it via temporary task in &lt;code&gt;Supervisor.init&#x2F;2&lt;&#x2F;code&gt; by defining child list
like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;  MyApp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Repo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;  MyApp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Worker&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;  {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Task&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; &amp;amp;send_slack_notification&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Alternatively you can use &lt;code&gt;:start_phases&lt;&#x2F;code&gt; in &lt;code&gt;application&#x2F;0&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;start_phases&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  notify&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: []&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then define in your &lt;code&gt;Application&lt;&#x2F;code&gt; module function &lt;code&gt;start_phase&#x2F;3&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; start_phase&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;notify&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;normal&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-symbol z-elixir&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; send_slack_notification&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where 1st argument will be the name of the phase, 2nd will be start type the
same as in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;elixir&#x2F;Application.html#c:start&#x2F;2&quot;&gt;&lt;code&gt;Application.start&#x2F;2&lt;&#x2F;code&gt; callback&lt;&#x2F;a&gt;,
and 3rd is the value passed in &lt;code&gt;:start_phases&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The awesome part there is that &lt;code&gt;start_phase&#x2F;3&lt;&#x2F;code&gt; is called not only for current
application, but all of it&#x27;s dependencies as well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;registered-names&quot;&gt;Registered names&lt;a class=&quot;zola-anchor&quot; href=&quot;#registered-names&quot; aria-label=&quot;Anchor link for: registered-names&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This is one of the things that had more sense in Erlang world than in Elixir,
but by being good citizen we should use it as well. This is a nice solution for
lack of namespacing in Erlang - it allowed release tools to detect collisions in
named processes. This is simple list of atoms that contain all names that are
globally registered by this application. Example form &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elixir-lang&#x2F;elixir&#x2F;blob&#x2F;ee9f38635e9a6c816adb575fc9431ded49be8032&#x2F;lib&#x2F;logger&#x2F;mix.exs#L14&quot;&gt;Elixir&#x27;s
Logger&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;registered&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;: [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;BackendSupervisor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Supervisor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; Logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Watcher&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unfortunately Phoenix do not use this field itself and do not suggest using one
in it&#x27;s default project generator. But in general it&#x27;s good practise.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;There is much more in application configuration to what most Elixir code is
using, it is worth sometimes to read how your application is defined and ran.
For more information about generating application description file you can check
out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;mix&#x2F;Mix.Tasks.Compile.App.html&quot;&gt;&lt;code&gt;mix help compile.app&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>Common Test for Elixir developers</title>
      <published>2019-07-15T00:00:00+00:00</published>
      <updated>2019-07-15T00:00:00+00:00</updated>
      <link href="https://hauleth.dev/post/common-test-for-elixir/" type="text/html"/>
      <id>https://hauleth.dev/post/common-test-for-elixir/</id>
      <summary></summary>
      <content type="html">&lt;p&gt;In my new job I have opportunity to work a little bit more with Erlang code and
Erlang related tools than earlier.  That forced me a little to learn and use
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;apps&#x2F;common_test&#x2F;basics_chapter.html&quot;&gt;Common Test&lt;&#x2F;a&gt; library which is &lt;strong&gt;the&lt;&#x2F;strong&gt; testing library in Erlang world.
When after that I needed to work back it hit me hard how much stuff I am
missing in Elixir.  In this article I will try to present Common Test library
from the viewpoint of long standing Elixir guy and present how it compares to
the ExUnit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unit-testing-vs-integration-testing&quot;&gt;Unit testing vs integration testing&lt;a class=&quot;zola-anchor&quot; href=&quot;#unit-testing-vs-integration-testing&quot; aria-label=&quot;Anchor link for: unit-testing-vs-integration-testing&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The main difference between these two is their intended usage.  In it&#x27;s core
ExUnit is intended as a library for unit testing (no surprise there, as it is
literally in it&#x27;s name), on the other hand Common Test is more about integration
testing and looking on the system as a whole.  So the discussion there would not
be fair, as it isn&#x27;t apples to apples, but for second let&#x27;s check what makes
each of them great for their intended uses:&lt;&#x2F;p&gt;
&lt;p&gt;ExUnit for unit testing:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Simple way to setup and teardown tests via &lt;code&gt;setup&lt;&#x2F;code&gt; and &lt;code&gt;setup_all&lt;&#x2F;code&gt; macros&lt;&#x2F;li&gt;
&lt;li&gt;Built in testing of documentation examples via &lt;code&gt;doctest&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Immutability of test environment (at least that is what you should try to
achieve)&lt;&#x2F;li&gt;
&lt;li&gt;Very simple way of running different test modules in parallel (tests within
single module are always sync)&lt;&#x2F;li&gt;
&lt;li&gt;Each test run in separate process, which prevents sharing data between
processes via process dictionary&lt;&#x2F;li&gt;
&lt;li&gt;Grouping tests into &lt;code&gt;describe&lt;&#x2F;code&gt; blocks&lt;&#x2F;li&gt;
&lt;li&gt;In overall simplicity of the library as a whole&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Common Test for integration testing:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Persistent test results - logs, results, &quot;generated garbage&quot; is stored between
runs in the Common Test, which allows to track what and when happened, and if
needed trace the bug in the logs&#x2F;leftovers&lt;&#x2F;li&gt;
&lt;li&gt;Generating &quot;private directory&quot; per suite&lt;&#x2F;li&gt;
&lt;li&gt;Grouping tests while allowing single test to be reused in different groups&lt;&#x2F;li&gt;
&lt;li&gt;Extensive control about order and parallelization of tests within groups&lt;&#x2F;li&gt;
&lt;li&gt;Built in very extensive and detailed reports (HTML and JUnit)&lt;&#x2F;li&gt;
&lt;li&gt;Distributed testing&lt;&#x2F;li&gt;
&lt;li&gt;Define dependencies between tests&lt;&#x2F;li&gt;
&lt;li&gt;Set of helpers for working with different network protocols (SSH, Telnet,
SNMP, FTP, Erlang RPC, netconf)&lt;&#x2F;li&gt;
&lt;li&gt;Built in support for data fixtures&lt;&#x2F;li&gt;
&lt;li&gt;Built in support for complex configuration of test runs via &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;apps&#x2F;common_test&#x2F;run_test_chapter.html#test-specifications&quot;&gt;test
specifications&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Built in logging (we will cover that later)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So as you can see, the Common Test is much broader and complex, but at the same
time it provides a lot of utilities that are really helpful while writing
integration tests, that can span multiple applications.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;writing-common-test-suite&quot;&gt;Writing Common Test suite&lt;a class=&quot;zola-anchor&quot; href=&quot;#writing-common-test-suite&quot; aria-label=&quot;Anchor link for: writing-common-test-suite&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;While CT provides enormous power in hand of the experienced tester&#x2F;developer
it&#x27;s API isn&#x27;t the top of the class (which happen a lot in Erlang tools, whoever
wanted to integrate them with anything then they will know what I mean).  But in
fact writing simple test suite in CT is fairly easy:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;erlang&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;module&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;example_SUITE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-punctuation z-section&quot;&gt;).&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; % The naming convention (with uppercase _SUITE) Erlang&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                        % convention which allow ct to find test suites.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                        % Something like ExUnit _test.exs naming convention&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-punctuation&quot;&gt;([&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-definition z-parameters z-punctuation z-section&quot;&gt;]).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-punctuation&quot;&gt;([&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;test_function_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-definition z-parameters z-punctuation z-section&quot;&gt;]).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;()&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    [&lt;&#x2F;span&gt;&lt;span&gt;test_function_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;test_function_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_Config&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;    2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is pretty easy and understandable format, but with due CT power it &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;erlang&#x2F;otp&#x2F;blob&#x2F;81d332cc693d2be8a5af16bfbcae0bfde6702479&#x2F;lib&#x2F;ssh&#x2F;test&#x2F;ssh_algorithms_SUITE.erl#L36&quot;&gt;quickly
can grow to be &quot;less&quot; readable&lt;&#x2F;a&gt;.
Taming that power can be problematic and can cause few headaches for newcomers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reporting&quot;&gt;Reporting&lt;a class=&quot;zola-anchor&quot; href=&quot;#reporting&quot; aria-label=&quot;Anchor link for: reporting&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Another part, and the one that I miss the most in ExUnit, is reporting in Common
Test.  This alone is in my humble opinion &lt;strong&gt;THE&lt;&#x2F;strong&gt; best part of the library.  To
present you how this work assume that we have above test suite which we will run
with &lt;code&gt;ct_run -dir .&lt;&#x2F;code&gt;. This will compile and run our tests (obviously), but in
addition to that it will generate hell lot of cruft files, some JQuery (yes,
this is still used in 2019), some CSS files, some HTML and other.&lt;&#x2F;p&gt;
&lt;p&gt;Just check &lt;a href=&quot;&#x2F;common-test-example&#x2F;simple&#x2F;index.html&quot;&gt;this out&lt;&#x2F;a&gt;. This is example report
generated by the Common Test. As you can see it contains a lot of information in
quite readable format. Not only it contains information about current run, but
all previous runs as well, which is really handy when tracking regressions.&lt;&#x2F;p&gt;
&lt;p&gt;But can we store even more information there? Yes, as CT includes simple
logging facility it is completely possible to log your own information during
tests, for example, lets modify our test to log some information:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;erlang&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;test_function_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_Config&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;    ct&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;log&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Example message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-definition z-parameters&quot;&gt;&amp;quot;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;    2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now when we run tests again, then we will see more information (even coloured)
in &lt;a href=&quot;&#x2F;common-test-example&#x2F;log&#x2F;ct_run.ct@NiunioBook.2019-07-16_11.03.21&#x2F;common-test-example.log.logs&#x2F;run.2019-07-16_11.03.22&#x2F;example_suite.test_function_name.html&quot;&gt;our test log&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;common-test&#x2F;log.png&quot; alt=&quot;Common Test log &amp;quot;Example message&amp;quot; on green background&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Additionally there is support Surefire XML output (commonly known as JUnit XML)
via &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;apps&#x2F;common_test&#x2F;ct_hooks_chapter.html#built-in-cths&quot;&gt;hook that is distributed with Common Test&lt;&#x2F;a&gt;.
This is very useful, as many CI services (for sure Jenkins, Circle CI, and
GitLab CI) support such files to provide better CI results than raw stdout.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comparison-to-exunit&quot;&gt;Comparison to ExUnit&lt;a class=&quot;zola-anchor&quot; href=&quot;#comparison-to-exunit&quot; aria-label=&quot;Anchor link for: comparison-to-exunit&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;ExUnit is great tool, which is very flexible while being relatively simple.
Unfortunately that simplicity makes it very lacking when comparing with &quot;more
established&quot; solutions like Common Test which shines when we &quot;grow out&quot; of the
ExUnit tests. It provides a lot great tools that really help with finding bugs
(for example when I was joining the project and I was trying to run tests
locally I have some issues due to misconfiguration, it was much easier to send
tarball of the test results instead of sending wall of text captured from
stdout).&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t get me wrong, ExUnit is great and powerful, and for sure you should use
it. It is great evolution over EUnit, but again, it would be worth of having
built in &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.erlang.org&#x2F;doc&#x2F;man&#x2F;eunit_surefire.html&quot;&gt;Surefire XML output&lt;&#x2F;a&gt;
due to it&#x27;s popularity and support in many CI services.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future&quot;&gt;Future&lt;a class=&quot;zola-anchor&quot; href=&quot;#future&quot; aria-label=&quot;Anchor link for: future&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;But is everything lost and we need to fall back to the Erlang code (which can be
problematic for many people) to use Common Test? Not exactly, Comcast (yes, that
Comcast) &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Comcast&#x2F;ctex&quot;&gt;created simple wrapper&lt;&#x2F;a&gt; for Elixir (unfortunately seems pretty
dead to me) and I have started &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hauleth&#x2F;commoner&quot;&gt;Commoner&lt;&#x2F;a&gt; library that is meant to
provide API more familiar and easier to use:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;elixir&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;defmodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; Commoner&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;ExampleSuite&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt; CommonTest&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;Suite&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  test &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;foo bar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  test &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;bar baz&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-class&quot;&gt;    CommonTest&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;log&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-punctuation&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section&quot;&gt;&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I am very interested about your feelings about Common Test usage in Elixir and
about proposed API for Commoner. You can ping me:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;On &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;elixirforum.com&#x2F;t&#x2F;commoner-elixir-wrapper-for-common-test-library&#x2F;23966?u=hauleth&quot;&gt;Elixir forum thread about Commoner&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;On Twitter via &lt;code&gt;@hauleth&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>Here be (owned) books</title>
      <published>2019-07-14T17:38:48+01:00</published>
      <updated>2019-07-14T17:38:48+01:00</updated>
      <link href="https://hauleth.dev/post/eli5-ownership/" type="text/html"/>
      <id>https://hauleth.dev/post/eli5-ownership/</id>
      <summary>Simple introduction to Rust&#x27;s ownership system</summary>
      <content type="html">&lt;p&gt;One of Rust&#x27;s biggest pros is its unique ownership system. Unfortunately, it is
also one of the hardest things to learn. In this article I will try to explain
it the same way I had learned it and how I introduce it to people.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer&lt;&#x2F;strong&gt;: If you do not find this article helpful try to search for another.
People are different and different things &lt;em&gt;zing&lt;&#x2F;em&gt; them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;let-s-have-a-book&quot;&gt;Let&#x27;s have a book&lt;a class=&quot;zola-anchor&quot; href=&quot;#let-s-have-a-book&quot; aria-label=&quot;Anchor link for: let-s-have-a-book&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Ownership becomes simple and natural if you just acknowledge it as an
application of real world relationships. For example, imagine types in Rust as
a kind of written note. We have different types of notes and based on that, each
of them will be handled differently.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;short ones, like phone no. of the hot waiter&#x2F;waitress&lt;&#x2F;li&gt;
&lt;li&gt;longer ones, like this article&lt;&#x2F;li&gt;
&lt;li&gt;longest ones, like a &lt;em&gt;Lord of the Rings&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Using this analogy let me try to introduce you, dear reader, to the amazing
world of Rust&#x27;s ownership.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;one-can-own-the-book&quot;&gt;One can own the book&lt;a class=&quot;zola-anchor&quot; href=&quot;#one-can-own-the-book&quot; aria-label=&quot;Anchor link for: one-can-own-the-book&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Each note, no matter what size it is, can have one owner. Me, you, anyone, it
doesn&#x27;t matter, but there will be only one owner. You can do whatever you want
with such note but with that power comes, not so great, responsibility: after
you are done with this book you will need to get rid of it. Since you are a law
abiding citizen you will recycle the note in the appropriate receptacle, but it
is your responsibility to do it. Of course this is not the only way to deal with
a note. You can also give it to someone and then it will be hers or his
responsibility.&lt;&#x2F;p&gt;
&lt;p&gt;To rephrase it in the Rust way, it would look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Note&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; john&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; book&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Note&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F; john creates the book and he owns it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; here he can do whatever he want with our `book`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F; at the end of his life john will destroy all his belongings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; steve&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; book&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Note&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F; new book&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; he can do whatever he wants to do with his book&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    sally&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;book&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; steve gives the book to `sally`,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; Sally has the responsibility to destroy it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; now steve cannot do anything with this book,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; as it is not his personal belonging anymore&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;one-can-borrow-the-book&quot;&gt;One can borrow the book&lt;a class=&quot;zola-anchor&quot; href=&quot;#one-can-borrow-the-book&quot; aria-label=&quot;Anchor link for: one-can-borrow-the-book&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;When we don&#x27;t want to give someone a book (we like that one), we can also lend
them one. And there are two ways to borrow one book:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We can edit that book (ex. it is our personal dairy) and we lend it to someone
to check our spelling. We trust that person and we explicitly allow her to
edit our notes in place. We call it &lt;strong&gt;mutable borrow&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We do not trust someone and we lend our beloved book with no permission to edit
it. Even more, that person knows, that writing something in that book will
make us go rampage and destroy the whole universe. It will be an &lt;strong&gt;immutable
borrow&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Of course if we borrow something from someone else, then we can lend it further
with the same rules that were applied to us.&lt;&#x2F;p&gt;
&lt;p&gt;Rust also ensures that &lt;strong&gt;mutable borrow&lt;&#x2F;strong&gt; is unique. There will never be more
than one person that will be allowed to edit the book. We can still create a chain
of trust - like when I find someone who is better at English than me, I would
allow this person to correct an article written by me or my friend who has
entrusted me with correcting his text.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Immutable borrows&lt;&#x2F;strong&gt; aren&#x27;t exclusive. I can lend my books as many times as I
want with one exception: I cannot lend a book that is still borrowed by someone
who can change its content.&lt;&#x2F;p&gt;
&lt;p&gt;In Rust it would look like that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; my&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; book&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Note&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    spelling_corrector&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-storage&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; book&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; we must explicitly mention that we lend the book&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; and we don&amp;#39;t give it away&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    reader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;book&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; spelling_corrector&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;book&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-storage&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Note&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; correct spelling in place&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; reader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;book&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Note&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; read a book&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;not-all-notes-are-worth-borrowing&quot;&gt;Not all notes are worth borrowing&lt;a class=&quot;zola-anchor&quot; href=&quot;#not-all-notes-are-worth-borrowing&quot; aria-label=&quot;Anchor link for: not-all-notes-are-worth-borrowing&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes this whole process of lending and then receiving a note back is much
more complicated then just cloning the whole note for someone else. Imagine that
you are in school and friend wants to copy your homework. What you do is lend
your homework to him, and with caution he can clone it on his own. This is what
Rust&#x27;s &lt;code&gt;Clone&lt;&#x2F;code&gt; trait provides - a method to clone content of struct without moving
its ownership.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-meta z-attribute&quot;&gt;#[derive(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Homework&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; my&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; homework&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Homework&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    friend&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;homework&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; friend&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;work&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Homework&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;) {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F; we lend it immutably&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; homework&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Homework&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; work&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; your friend now has his own modifiable copy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But some notes are even shorter than that. They are so short and easy to clone
that it is much easier to clone them every time, instead of explicitly
calling the method. Like when you give your phone number to a hot girl at the
bar, the &lt;code&gt;Copy&lt;&#x2F;code&gt; trait automatically clones your note so the other has their own copy.
Again, this is for small types that can be mechanically copied each time when needed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-meta z-attribute&quot;&gt;#[derive(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Copy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F; everything that is `Copy` must be also `Clone`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; PhoneNo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; my&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; no&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; PhoneNo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    hot_stuff&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;no&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; hot_stuff&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;no&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; PhoneNo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F; fingers crossed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;There is more to learn, but these are the basic laws of ownership in Rust.
Everything else is based on this. If you understand this, it will become much
easier for you to understand how other types behave and, more importantly, why
they work the way they do.&lt;&#x2F;p&gt;
</content>
    </entry>
    <entry xml:lang="en">
      <title>Dumb Elixir VIsual (and iMproved) editor</title>
      <published>2019-04-13T21:40:05+02:00</published>
      <updated>2019-04-13T21:40:05+02:00</updated>
      <link href="https://hauleth.dev/post/vim-for-elixir/" type="text/html"/>
      <id>https://hauleth.dev/post/vim-for-elixir/</id>
      <summary>How I have configured Vim for working with Elixir and Erlang projects</summary>
      <content type="html">&lt;blockquote&gt;
&lt;p&gt;Earlier published on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@hauleth&#x2F;dumb-elixir-visual-and-improved-editor-53c23a0800e4&quot;&gt;Medium&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;vim-session.png&quot; alt=&quot;My example session in NeoVim with QuickFix displaying Credo warnings&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I am quite orthodox Vim user and I like to know everything that is happening in
my editor configuration. By no means I am &quot;minimal&quot; Vim user, I currently have
48 plugins installed, I just very carefully pick my plugins (few of them I have
written myself) to use only plugins that I understand and I can fix on my own in
case of problems. This results with configuration I understand and control in
all means.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-this-article-is-not&quot;&gt;What this article is not&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-this-article-is-not&quot; aria-label=&quot;Anchor link for: what-this-article-is-not&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This isn&#x27;t &quot;introduction into Vim&quot; article neither &quot;how to configure Vim for
Elixir development&quot;. Here I will try to describe how I use Vim for Elixir and
Erlang development, you can find some nice ideas and tips that may help you, but
by any means I do not mean that this is configuration you should or should not
use. You should use whatever you like (even if I do not like what you use) as
long as you understand what you use and why you use that.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Any sufficiently complicated set of Vim plugins contains an ad hoc,
informally-specified, bug-ridden, slow implementation of half of Vim&#x27;s
features.&lt;&#x2F;em&gt;
-- robertmeta&#x27;s tenth rule.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Now we can start.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;basics&quot;&gt;Basics&lt;a class=&quot;zola-anchor&quot; href=&quot;#basics&quot; aria-label=&quot;Anchor link for: basics&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;I am using NeoVim 0.3.4, but almost everything I will describe there should work
in Vim 8.1+ as well. If you will encounter any problems, then please let me
know.&lt;&#x2F;p&gt;
&lt;p&gt;Vim doesn&#x27;t (as 13.04.2019) support Elixir out of the box, so what we
need is to install &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elixir-editors&#x2F;vim-elixir&quot;&gt;&lt;code&gt;vim-elixir&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin which will provide niceties like syntax
colouring and indentation. Even if syntax colouring isn&#x27;t your thing then I
would still recommend installing it as it provides other things that it provides
few other niceties that I will describe later.&lt;&#x2F;p&gt;
&lt;p&gt;But how to install it? In truly minimal setup you can just create
&lt;code&gt;pack&#x2F;elixir&#x2F;start&lt;&#x2F;code&gt; directory within your &lt;code&gt;~&#x2F;.vim&lt;&#x2F;code&gt; folder
(&lt;code&gt;$XDG_CONFIG_DIR&#x2F;nvim&lt;&#x2F;code&gt; in case of NeoVim) and clone given repository there,
however I am using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kristijanhusak&#x2F;vim-packager&quot;&gt;&lt;code&gt;vim-packager&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which is based on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;k-takata&#x2F;minpac&quot;&gt;&lt;code&gt;minpac&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and is
truly minimal package manager (it is important distinction from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;junegunn&#x2F;vim-plug&quot;&gt;&lt;code&gt;vim-plug&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
or others that also manages plugin loading, these plugins only manage fetching)
which even do not need to be loaded during &quot;normal&quot; runtime, only when you are
updating plugins.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;project-navigation&quot;&gt;Project navigation&lt;a class=&quot;zola-anchor&quot; href=&quot;#project-navigation&quot; aria-label=&quot;Anchor link for: project-navigation&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;A lot of people, when come from other editors, often install NERDTree to have
&quot;project drawer&quot; functionality within Vim, because this is what they are used
to. Unfortunately &quot;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;vimcasts.org&#x2F;blog&#x2F;2013&#x2F;01&#x2F;oil-and-vinegar-split-windows-and-project-drawer&#x2F;&quot;&gt;split windows and the project drawer go together like oil
and vinegar&lt;&#x2F;a&gt;&quot; and it can result in painful experience or, which
is even worse, avoiding built in functionalities, because these do not mix well.
Vim comes with built in NetRW plugin for working with remote files and directory
tries. However for me this plugin is bloated as well and I would love to get rid
of it (unfortunately it is not currently possible as few functionalities relies
on it, namely dictionaries) so I replaced everything with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;justinmk&#x2F;vim-dirvish&quot;&gt;&lt;code&gt;dirvish&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
Additionally I often use fuzzy finder, which in my case is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;srstevenson&#x2F;vim-picker&quot;&gt;&lt;code&gt;vim-picker&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; with
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jhawthorn&#x2F;fzy&quot;&gt;&lt;code&gt;fzy&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which for me is much faster and more precise than popular FZF.&lt;&#x2F;p&gt;
&lt;p&gt;These tools are great when we are navigating in tree that is new to us or do not
have explicit structure. When we are working on Elixir projects then we know
before hand that there will be some commonly shared structure, like
&lt;code&gt;lib&#x2F;&amp;lt;name&amp;gt;.ex&lt;&#x2F;code&gt; will contain source code, &lt;code&gt;test&#x2F;&amp;lt;name&amp;gt;_test.exs&lt;&#x2F;code&gt; will contain
test files, etc. What is more we know that &lt;code&gt;&amp;lt;name&amp;gt;&lt;&#x2F;code&gt; part will be shared between
file and its unit tests. This is very powerful assumption, as this allow us to
use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tpope&#x2F;vim-projectionist&quot;&gt;&lt;code&gt;vim-projectionist&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; with ease. This plugin provide 3 main
functionalities (for me):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Jumping to the files basing on their path, so for example I can use &lt;code&gt;:Elib foo&lt;&#x2F;code&gt; to automatically jump to file &lt;code&gt;lib&#x2F;foo.ex&lt;&#x2F;code&gt;. It doesn&#x27;t seems like much,
but it also provides fuzzy finding, and allows me to define more specific
matches, like &lt;code&gt;:Econtroller foo&lt;&#x2F;code&gt; will open
&lt;code&gt;lib&#x2F;app_web&#x2F;controllers&#x2F;foo_controller.ex&lt;&#x2F;code&gt; (not exactly that as I use
different project layout, but that is topic on another article).&lt;&#x2F;li&gt;
&lt;li&gt;File templates, so when I start editing file (doesn&#x27;t matter how I opened it,
so this do not require to use above &lt;code&gt;:Elib&lt;&#x2F;code&gt; command), so when I start editing
test file it automatically add scaffold which I can configure per project.&lt;&#x2F;li&gt;
&lt;li&gt;Alternate files which in short are &quot;related&quot; files. For example when I edit
file &lt;code&gt;lib&#x2F;foo&#x2F;bar&#x2F;baz.ex&lt;&#x2F;code&gt; and I run &lt;code&gt;:A&lt;&#x2F;code&gt; it will create (if not exist) and
jump to the file &lt;code&gt;test&#x2F;foo&#x2F;bar&#x2F;baz_test.exs&lt;&#x2F;code&gt; which will be already scaffolded
by the earlier functionality. Recently it even became possible to have
multiple alternates.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Whole plugin is configured by &lt;code&gt;.projections.json&lt;&#x2F;code&gt; file, but it would be
infeasible to add this file to each project you work for. Fortunately there is
solution for that, we can define &quot;heuristics&quot; that will try to match for given
project structure and provide such features &quot;globally&quot;. My configuration for
that looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; g:projectionist_heuristics[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;mix.exs&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;apps&#x2F;*&#x2F;mix.exs&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;app&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;lib&#x2F;*.ex&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;lib&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;alternate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;test&#x2F;{}_test.exs&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;template&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;defmodule {camelcase|capitalize|dot} do&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;end&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;test&#x2F;*_test.exs&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;test&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;alternate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;lib&#x2F;{}.ex&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;template&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       &amp;#39;defmodule {camelcase|capitalize|dot}Test do&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       &amp;#39;  use ExUnit.Case&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       &amp;#39;  alias {camelcase|capitalize|dot}, as: Subject&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       &amp;#39;  doctest Subject&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       &amp;#39;end&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt;   ]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;mix.exs&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;mix&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;config&#x2F;*.exs&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;config&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;*.ex&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;makery&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     &amp;#39;lint&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;compiler&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;credo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     &amp;#39;test&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;compiler&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;exunit&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     &amp;#39;build&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;compiler&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;mix&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt;   }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;*.exs&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;makery&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     &amp;#39;lint&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;compiler&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;credo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     &amp;#39;test&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;compiler&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;exunit&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     &amp;#39;build&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;compiler&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;mix&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt;   }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; g:projectionist_heuristics[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;rebar.config&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;*.erl&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;template&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;-module({basename}).&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-export([]).&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;src&#x2F;*.app.src&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;app&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;src&#x2F;*.erl&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;src&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;alternate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;test&#x2F;{}_SUITE.erl&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;test&#x2F;*_SUITE.erl&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;test&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   &amp;#39;alternate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;src&#x2F;{}.erl&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;rebar.config&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;rebar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;this-will-provide&quot;&gt;This will provide:&lt;a class=&quot;zola-anchor&quot; href=&quot;#this-will-provide&quot; aria-label=&quot;Anchor link for: this-will-provide&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;for-elixir&quot;&gt;For Elixir:&lt;a class=&quot;zola-anchor&quot; href=&quot;#for-elixir&quot; aria-label=&quot;Anchor link for: for-elixir&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lib&lt;&#x2F;code&gt; that will contain project source files which will be already filled with
module named &lt;code&gt;Foo.BarBaz&lt;&#x2F;code&gt; for file named &lt;code&gt;lib&#x2F;foo&#x2F;bar_baz.ex&lt;&#x2F;code&gt; (jump by &lt;code&gt;:Elib foo&#x2F;bar_baz&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;test&lt;&#x2F;code&gt; for test files which will be instantiated with module named
&lt;code&gt;Foo.BarBazTest&lt;&#x2F;code&gt; for file &lt;code&gt;test&#x2F;foo&#x2F;bar_baz_test.exs&lt;&#x2F;code&gt; that will already use
&lt;code&gt;ExUnit.Case&lt;&#x2F;code&gt; (you can jump via &lt;code&gt;:Etest foo&#x2F;bar_baz&lt;&#x2F;code&gt;), will define
&lt;code&gt;alias Foo.BarBaz, as: Subject&lt;&#x2F;code&gt;, and will run doctests for that module&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;config&lt;&#x2F;code&gt; for configuration files&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;mix&lt;&#x2F;code&gt; for &lt;code&gt;mix.exs&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It will also define test files as default alternates for each source file (and
vice versa, because alternate files do not need to be symmetric), so if you
run &lt;code&gt;:A&lt;&#x2F;code&gt; in file &lt;code&gt;lib&#x2F;foo&#x2F;bar_baz.ex&lt;&#x2F;code&gt; it will automatically jump to the
&lt;code&gt;test&#x2F;foo&#x2F;bar_baz_test.exs&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;for-erlang&quot;&gt;For Erlang:&lt;a class=&quot;zola-anchor&quot; href=&quot;#for-erlang&quot; aria-label=&quot;Anchor link for: for-erlang&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src&lt;&#x2F;code&gt; for source files&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;app&lt;&#x2F;code&gt; for &lt;code&gt;*.app.src&lt;&#x2F;code&gt; files&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;test&lt;&#x2F;code&gt; for common test suites&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;rebar&lt;&#x2F;code&gt; for &lt;code&gt;rebar.config&lt;&#x2F;code&gt; file&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The relation between source files and test files is exactly the same as in
Elixir projects.&lt;&#x2F;p&gt;
&lt;p&gt;One thing can bring your attention, why the hell I define helpers for &lt;code&gt;mix.exs&lt;&#x2F;code&gt;
and &lt;code&gt;rebar.config&lt;&#x2F;code&gt; as you can simply use &lt;code&gt;:e &amp;lt;file&amp;gt;&lt;&#x2F;code&gt;. The answer is simple, &lt;code&gt;:e&lt;&#x2F;code&gt;
will work for files in Vim working directory while &lt;code&gt;:E&lt;&#x2F;code&gt; will work form the
projectionist root, aka directory where is &lt;code&gt;.projections.json&lt;&#x2F;code&gt; file defined (or
in case of heuristics, from the directory that matched files). This mean that
when I edit files in umbrella application I can use &lt;code&gt;:Emix&lt;&#x2F;code&gt; (or &lt;code&gt;:Erebar&lt;&#x2F;code&gt;) to
edit current sub-project config file and &lt;code&gt;:e mix.exs&lt;&#x2F;code&gt; to edit global one.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;completion-and-language-server&quot;&gt;Completion and language server&lt;a class=&quot;zola-anchor&quot; href=&quot;#completion-and-language-server&quot; aria-label=&quot;Anchor link for: completion-and-language-server&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;For completion and code formatting I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;prabirshrestha&#x2F;vim-lsp&quot;&gt;&lt;code&gt;vim-lsp&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. I have tried most of the
language server clients out there, but I always come back to this one for a few
reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It is implemented only in VimL which mean that I am not forced to installing
any compatibility layers or fighting with different runtimes.&lt;&#x2F;li&gt;
&lt;li&gt;It is simple enough that I can easily dig into it, and fix problems that I
have encountered.&lt;&#x2F;li&gt;
&lt;li&gt;It doesn&#x27;t override any built in Vim functionality and instead provide set of
commands that you can then bind to whatever mappings you want.&lt;&#x2F;li&gt;
&lt;li&gt;It do not force me to use autocompletion, which I do not use at all. At the
same time it provides seamless integration with built-in Vim functionality of
omnicompletion and user completion by providing &lt;code&gt;lsp#complete&lt;&#x2F;code&gt; function.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This approach of not providing default mappings is really nice for power users,
as this allow us to define everything on our own. For example some of plugins
use &lt;kbd&gt;&amp;lt;C-]&amp;gt;&lt;&#x2F;kbd&gt; for jumping to definition, which I often use (it is
jump to tag definition) and shadowing it would be problematic for me. So in the
end I have created my own set of mappings, that have additional feature of being
present only if there is any server that supports them:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;func!&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; s:setup_ls&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;...&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; abort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:servers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; lsp#get_whitelisted_servers&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:server&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:servers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; l:cap&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; lsp#get_server_capabilities&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;l:server&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; has_key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;l:cap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;completionProvider&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;            setlocal&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; omnifunc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;lsp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;complete&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        endif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; has_key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;l:cap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;hoverProvider&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;            setlocal&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; keywordprg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;:LspHover&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        endif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; has_key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;l:cap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;definitionProvider&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;            nmap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;silent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; gd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;lsp&lt;&#x2F;span&gt;&lt;span&gt;-definition&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        endif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; has_key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;l:cap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;referencesProvider&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;            nmap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;silent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; gr &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;lsp&lt;&#x2F;span&gt;&lt;span&gt;-references&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        endif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    endfor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;endfunc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;augroup&lt;&#x2F;span&gt;&lt;span&gt; LSC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-keyword z-operator&quot;&gt;    autocmd!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    autocmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; lsp_setup &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;call&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; lsp#register_server&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;name&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;ElixirLS&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;cmd&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {_-&amp;gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;elixir-ls&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;whitelist&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;elixir&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;eelixir&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    autocmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; lsp_setup &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;call&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; lsp#register_server&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;name&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;RLS&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;cmd&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {_-&amp;gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;rls&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;whitelist&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;rust&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    autocmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; lsp_setup &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;call&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; lsp#register_server&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;name&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;solargraph&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;cmd&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {server_info-&amp;gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;solargraph&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;stdio&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;initialization_options&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;diagnostics&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;true&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;whitelist&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;ruby&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    autocmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; lsp_setup &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;call&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; lsp#register_server&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;name&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;dot&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;cmd&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {server_info-&amp;gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;dot-language-server&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;--stdio&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;whitelist&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;dot&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                \&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    autocmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; lsp_server_init &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;call&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;SID&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;setup_ls&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    autocmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; BufEnter&lt;&#x2F;span&gt;&lt;span&gt; * &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;call&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;SID&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;setup_ls&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;augroup&lt;&#x2F;span&gt;&lt;span&gt; END&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;running-tasks-and-linting&quot;&gt;Running tasks and linting&lt;a class=&quot;zola-anchor&quot; href=&quot;#running-tasks-and-linting&quot; aria-label=&quot;Anchor link for: running-tasks-and-linting&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;A lot of people &quot;cannot live&quot; without lint-as-you-type feature, but I think,
that not using such functionality makes me a less sloppy and better programmer.
It makes me to think when I write and do not rely on some magical friend that
will always watch over my shoulder. However when the problem happens in my code
I would like to know where and quickly jump to the place where error occurred.
Additionally I would like to run tasks in the background without interruption to
my current work. All of it became possible with introduction of asynchronous
tasks in NeoVim and Vim 8. So I have created plugin &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hauleth&#x2F;asyncdo.vim&quot;&gt;&lt;code&gt;asyncdo.vim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; that
allows me to easily implement &lt;code&gt;:Make&lt;&#x2F;code&gt; command that works exactly like built
in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimhelp.org&#x2F;quickfix.txt.html#%3Amake&quot;&gt;&lt;code&gt;:make&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, but do not halt my normal work. Together with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;igemnace&#x2F;vim-makery&quot;&gt;&lt;code&gt;vim-makery&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
(which nicely integrates with &lt;code&gt;vim-projectionsit&lt;&#x2F;code&gt;) and built in functionality of
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimhelp.org&#x2F;quickfix.txt.html#%3Acompiler&quot;&gt;&lt;code&gt;:compiler&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which is supported by &lt;code&gt;vim-elixir&lt;&#x2F;code&gt;, it allows me to easily run all
sorts of commands very easily. If you look into projectionist heuristics above
you will see that there is &lt;code&gt;&quot;makery&quot;&lt;&#x2F;code&gt; key defined for &lt;code&gt;*.ex&lt;&#x2F;code&gt; and &lt;code&gt;*.exs&lt;&#x2F;code&gt; files.
That allows me to run &lt;code&gt;:Mlint %&lt;&#x2F;code&gt; to run Credo on current file and the results
will be present within QuickFix window which together with my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;hauleth&#x2F;qfx.vim&quot;&gt;&lt;code&gt;qfx.vim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; will
mark lines with errors using signs. In the same manner I can run &lt;code&gt;:Mtest&lt;&#x2F;code&gt; to run
tests for whole project and have failed tasks visible in QuickFix window.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;other-utilities&quot;&gt;Other utilities&lt;a class=&quot;zola-anchor&quot; href=&quot;#other-utilities&quot; aria-label=&quot;Anchor link for: other-utilities&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;There is bunch of other plugins that are quite helpful when it comes to working
on Elixir projects and do not interfere with Vim features, ex.:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tpope&#x2F;vim-dadbod&quot;&gt;&lt;code&gt;vim-dadbod&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which allows you to run SQL queries from within Vim, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elixir-editors&#x2F;vim-elixir&#x2F;pull&#x2F;481&quot;&gt;I
have written integration with Ecto&lt;&#x2F;a&gt; which is provided with
&lt;code&gt;vim-elixir&lt;&#x2F;code&gt; by default. So if you are working on Elixir application that has
&lt;code&gt;MyApp.Repo&lt;&#x2F;code&gt; Ecto repository then you can run &lt;code&gt;:DB MyApp.Repo&lt;&#x2F;code&gt; and Vim will
open your DB client within separate terminal that will be connected to your DB&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tpope&#x2F;vim-endwise&quot;&gt;&lt;code&gt;vim-endwise&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; that will automatically add end to your do blocks&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;direnv&#x2F;direnv.vim&quot;&gt;&lt;code&gt;direnv.vim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; simplify management of environment variables in per-directory
manner&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sgur&#x2F;vim-editorconfig&quot;&gt;&lt;code&gt;vim-editorconfig&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sgur&quot;&gt;sgur&lt;&#x2F;a&gt;&#x27;s one, not official one) - pure VimL support
for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;editorconfig.org&quot;&gt;EditorConfig&lt;&#x2F;a&gt; files&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;I hope that you find some nice ideas within this article that will help in
improving your own Vim configuration without adding much clutter.&lt;&#x2F;p&gt;
&lt;p&gt;No, I will not publish my own &lt;code&gt;vimrc&lt;&#x2F;code&gt; in fear that some of you will copy it as
is (also not that this is particularly troublesome for anyone who is aware of
Google to find it). Instead I highly suggest You to dig into your own
configuration and for each line ask yourself:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Do I know what this line &lt;strong&gt;does&lt;&#x2F;strong&gt;?&lt;&#x2F;li&gt;
&lt;li&gt;Do I really &lt;strong&gt;need&lt;&#x2F;strong&gt; this line?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And if answer for any of these questions is &lt;strong&gt;no&lt;&#x2F;strong&gt; then remove such line. In the
end you either learn what for it was, or that you never needed it.&lt;&#x2F;p&gt;
</content>
    </entry>
</feed>
