<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Programming on Giedrius Statkevičius</title><link>https://giedrius.blog/categories/programming/</link><description>Recent content in Programming on Giedrius Statkevičius</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Fri, 07 Jun 2024 14:18:01 +0000</lastBuildDate><atom:link href="https://giedrius.blog/categories/programming/feed.xml" rel="self" type="application/rss+xml"/><item><title>My gRPC Annoyances</title><link>https://giedrius.blog/2024/06/07/my-grpc-annoyances/</link><pubDate>Fri, 07 Jun 2024 14:18:01 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=1182</guid><description>&lt;p&gt;We have been using gRPC in &lt;a href="https://thanos.io"&gt;Thanos&lt;/a&gt; since Thanos inception - it has served us great and it has a ton of useful functionality, it solves a lot of problems, it is easy to use, and so on. However, I feel like some stuff is lacking, especially performance that will most likely never be fixed (or, I should say, changed). The framework just does not solve 100% of the things that the Thanos project needs right now. Let&amp;rsquo;s go through the list of my pet peeves.&lt;/p&gt;</description></item><item><title>How I Started Programming</title><link>https://giedrius.blog/2024/05/31/how-i-started-programming/</link><pubDate>Fri, 31 May 2024 09:40:00 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=1192</guid><description>&lt;p&gt;It all started in, I believe, the eventful year of 2001. I was 6 years old. Our family was lucky enough to get our own first personal computer! Completely for us and used by all members of our family back then. I consider that to be incredible luck given that Lithuania recently regained its independence after the Soviet occupation. I think we got internet connected to our house around 2003 so for a few years we were offline. My mom was still studying back then and she used the computer a lot for her studies. But me and my brother mostly used it for entertainment - music, games, videos. Someone left some pre-installed games like Dave Mirra Freestyle BMX and Worms Blast on the computer, and we played the heck out of them.&lt;/p&gt;</description></item><item><title>Dynamic hashrings with WAL in Thanos are bad</title><link>https://giedrius.blog/2024/05/24/dynamic-hashrings-with-wal-in-thanos-are-bad/</link><pubDate>Fri, 24 May 2024 14:30:01 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=1186</guid><description>&lt;p&gt;Hashrings are everywhere in distributed systems. Combined with a write-ahead log that uses an unbounded amount of RAM during WAL replay, they are a terrible idea. If there is a constant stream of metrics coming into Thanos, you want to push back on the producers of those metrics in case of one or a few node&amp;rsquo;s downtime. Having a dynamic hashring i.e. a hashring that immediately updates as soon as it notices that one node is down, prevents that. The same stream is now going to fewer nodes. And so on until, most likely, your whole stack collapses. In practice, this means that you should not remove a node from the hashring if it is unhealthy or unready.&lt;/p&gt;</description></item><item><title>Perils of /metrics data assertions</title><link>https://giedrius.blog/2024/02/28/perils-of-metrics-data-assertions/</link><pubDate>Wed, 28 Feb 2024 10:17:44 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=1155</guid><description>&lt;p&gt;In the Thanos project the e2e tests are written in part using assertions on the metrics data. I have encountered a few challenges with those assertions that I wanted to share with you.&lt;/p&gt;
&lt;h2 id="always-check-for-the-maximum-possible-value"&gt;Always check for the maximum possible value&lt;/h2&gt;
&lt;p&gt;Writing tests on /metrics data means your testing harness continuously checks /metrics data to see whether some metric equals some value. If the metric takes some time to reach the maximum value, you might erroneously write an equals check that checks for a smaller value. Later on, this will lead to a flaky test situation.&lt;/p&gt;</description></item><item><title>Starting up GitHub sponsors and some recent postings work</title><link>https://giedrius.blog/2024/02/22/starting-up-github-sponsors-and-some-recent-postings-work/</link><pubDate>Thu, 22 Feb 2024 19:04:51 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=1160</guid><description>&lt;p&gt;Hello everyone! I am happy to announce that I&amp;rsquo;ve set up GitHub sponsors on my &lt;a href="https://github.com/GiedriusS"&gt;profile&lt;/a&gt;. If you want to support my blog or my work on Thanos/Prometheus, and you have some free money then now you have a way to throw some money at these projects. Let&amp;rsquo;s see if I will even get one sponsor. I was thinking that maybe I should work on some custom features that could be behind a paywall. Let&amp;rsquo;s see when I will have some time to work on them.&lt;/p&gt;</description></item><item><title>Reproducing flaky Go tests using Linux cgroups and systemd</title><link>https://giedrius.blog/2023/07/17/reproducing-flaky-go-tests-using-systemd/</link><pubDate>Mon, 17 Jul 2023 20:07:40 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=1139</guid><description>&lt;p&gt;Sometimes, the &lt;code&gt;-race&lt;/code&gt; option might not be enough to trigger/debug races in Go tests. You might have &lt;code&gt;time.Sleep()&lt;/code&gt; in a test thinking that some event will surely trigger in some time. You might run it on GitHub actions on a shared runner. Alas, you don&amp;rsquo;t see that event happen. What could have caused this? Most of the time it is because of the minimal CPU time allocated for your tests. The runners are shared between many projects and thus sometimes CPU might be very split between many processes.&lt;/p&gt;</description></item><item><title>Distributed Systems Magic: K-way Merge in Thanos</title><link>https://giedrius.blog/2022/09/08/distributed-systems-magic-k-way-merge-in-thanos/</link><pubDate>Thu, 08 Sep 2022 15:59:56 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=975</guid><description>&lt;p&gt;Oops, it has been such a long time since I wrote a post that I even accidentally forgot to renew my site! That&amp;rsquo;s bad. I definitely owe you a few new posts. Thus, here is another post in the distributed systems magic series.&lt;/p&gt;
&lt;p&gt;Recently I undertook the &lt;a href="https://github.com/thanos-io/thanos/pull/5296"&gt;task of improving the proxying logic in Thanos&lt;/a&gt;. If you are not familiar with it, the Query component of Thanos sends out requests via gRPC to leaf nodes to retrieve needed data when it gets some kind of PromQL query from users. This article will show you how it worked previously, how it works now, and the learnings from doing this.&lt;/p&gt;</description></item><item><title>Distributed Systems Magic: Groupcache in Thanos</title><link>https://giedrius.blog/2022/03/04/distributed-systems-magic-groupcache-in-thanos/</link><pubDate>Fri, 04 Mar 2022 10:19:50 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=953</guid><description>&lt;p&gt;This is a sequel to my previous blog post about trying to migrate to a newer version of protocol buffer API. In this blog post, I will tell you how we&amp;rsquo;ve managed to get &lt;a href="https://github.com/golang/groupcache"&gt;groupcache&lt;/a&gt; into Thanos during the previous LFX mentorship. The team consisted of &lt;a href="https://github.com/akanshat"&gt;Akansha Tiwari&lt;/a&gt;, &lt;a href="https://onprem.dev/"&gt;Prem Saraswat&lt;/a&gt;, and me. It would not have been possible to implement this without the whole team.&lt;/p&gt;
&lt;p&gt;In the beginning, let&amp;rsquo;s quickly go over what is groupcache and why it solves a few important problems in Thanos.&lt;/p&gt;</description></item><item><title>Things Learned From Trying to Migrate To Protobuf V2 API from gogoprotobuf (So Far)</title><link>https://giedrius.blog/2022/02/04/things-learned-from-trying-to-migrate-to-protobuf-v2-api-from-gogoprotobuf-so-far/</link><pubDate>Fri, 04 Feb 2022 16:03:25 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=928</guid><description>&lt;p&gt;During the most recent LFX mentorship program&amp;rsquo;s iteration, I had the honor to work on trying to migrate to &lt;a href="https://go.dev/blog/protobuf-apiv2"&gt;version 2 of the protobuf API&lt;/a&gt; from gogoprotobuf on the Thanos project with my one and only awesome mentee &lt;a href="https://twitter.com/im_rsawra"&gt;Rahul Sawra&lt;/a&gt; and another mentor Lucas Serven who is also a co-maintainer of &lt;a href="https://thanos.io"&gt;Thanos&lt;/a&gt;. I wanted to share my technical learnings from this project.&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://giedrius.blog/wp-content/uploads/2022/02/image-1.png"/&gt;
&lt;/figure&gt;
&lt;p&gt;First of all, let&amp;rsquo;s quickly look at what protocol buffers are and what is the meaning of the different words in the jargon. Protocol buffers are a way of serializing data. It was &lt;a href="https://developers.google.com/protocol-buffers/"&gt;first made by Google&lt;/a&gt;. It is a quite popular library that is used by Thanos really everywhere. Thanos also uses &lt;a href="https://grpc.io/"&gt;gRPC&lt;/a&gt; to talk between different components. gRPC is a remote procedure call framework. With it, your (micro-)services can implement methods that could be called by others.&lt;/p&gt;</description></item><item><title>Surprising Behavior With inotify And ioutil</title><link>https://giedrius.blog/2021/03/06/surprising-behavior-with-inotify-and-ioutil/</link><pubDate>Sat, 06 Mar 2021 12:58:55 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=844</guid><description>&lt;p&gt;Recently I was working on trying to fix one flaky test of the &amp;ldquo;reloader&amp;rdquo; component in the &lt;a href="https://thanos.io"&gt;Thanos&lt;/a&gt; project. It was quite a long-standing one - almost took a whole year to fix this &lt;a href="https://github.com/thanos-io/thanos/issues/2622"&gt;issue&lt;/a&gt;. It is not surprising as it is quite tricky. But, before zooming into the details, let&amp;rsquo;s talk about what does this test does and what other systems come into play.&lt;/p&gt;
&lt;p&gt;Simply put, Thanos Sidecar works as a sidecar component for Prometheus that not just proxies the requests to it, captures the blocks produced by Prometheus &amp;amp; uploads them to remote object storage, but the Sidecar can also automatically reload your Prometheus instance if some kind of configuration files change. For that, it uses the &lt;code&gt;inotify&lt;/code&gt; mechanism on the Linux kernel. You can read more about inotify itself &lt;a href="https://man7.org/linux/man-pages/man7/inotify.7.html"&gt;here&lt;/a&gt;. Long story short, using it you can watch some files and get notifications when something changes e.g. new data gets written to the files.&lt;/p&gt;</description></item><item><title>Running systemd Units Only If Certain CPU Features Are Available</title><link>https://giedrius.blog/2021/02/19/running-systemd-units-only-if-certain-cpu-features-are-available/</link><pubDate>Fri, 19 Feb 2021 15:13:17 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=823</guid><description>&lt;figure&gt;
&lt;img loading="lazy" src="https://giedrius.blog/wp-content/uploads/2021/02/systemd-logomark.png"
alt="systemd&amp;#39;s logo (C) https://brand.systemd.io/"/&gt; &lt;figcaption&gt;
&lt;p&gt;systemd&amp;rsquo;s logo (C) &lt;a href="https://brand.systemd.io/"&gt;https://brand.systemd.io/&lt;/a&gt;&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Do you have some kind of application that should only be executed when the user&amp;rsquo;s CPU has a certain feature? Or maybe your application has horrible performance unless some certain instructions are available? As you might know already, the Linux kernel exposes this information via &lt;code&gt;/proc/cpuinfo&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;processor : &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vendor_id : AuthenticAMD
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cpu family : &lt;span style="color:#ae81ff"&gt;23&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;model : &lt;span style="color:#ae81ff"&gt;96&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;model name : AMD Ryzen &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; PRO &lt;span style="color:#ae81ff"&gt;4750&lt;/span&gt;U with Radeon Graphics
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd _apicid aperfmperf pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;dnowprefetch osvw ibs skinit wdt tce to poext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb cat_l3 cdp_l3 hw_pstate ssbd mba ibrs ibpb stibp vmmcall fsgsbase bmi1 avx2 smep bmi2 cqm rdt_a rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xge tbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local clzero irperf xsaveerptr rdpru wbnoinvd arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif umip rdpid overflow_recov succor smca
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where does this data come from? One source of information is the &lt;code&gt;cpuid&lt;/code&gt; instruction. On the x86 architecture systemd starting from v248 is now able to start or stop an unit based on the features exposed by the &lt;a href="https://en.wikipedia.org/wiki/CPUID"&gt;CPUID&lt;/a&gt; instruction. Enter &lt;code&gt;ConditionCPUFeature&lt;/code&gt;. On CPUs that do not have the CPUID instruction i.e. ARM CPUs, it is assumed that the CPU implements no features and thus any potential &lt;em&gt;CPUFeature&lt;/em&gt; conditions will fail.&lt;/p&gt;</description></item><item><title>Surprising Optimization When Appending Elements to an Array in ZSH</title><link>https://giedrius.blog/2021/01/18/surprising-optimization-when-appending-elements-to-an-array-in-zsh/</link><pubDate>Mon, 18 Jan 2021 19:32:00 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=801</guid><description>&lt;p&gt;Recently I ran into a surprising ZSH performance bottleneck while editing my &lt;code&gt;.zshrc&lt;/code&gt;. Because it gets loaded every time a new shell comes up, I have noticed the issue pretty fast. I quickly started digging into the problem. Apparently, this surprising behavior concerns appending new elements to an array. I did not have a huge file that I was trying to read, only about 6000 elements or so. But still, it had a significant impact on how fast the Z shell was able to start up.&lt;/p&gt;</description></item><item><title>Equivocal Puppet Class Parameters</title><link>https://giedrius.blog/2020/11/08/equivocal-puppet-class-parameters/</link><pubDate>Sun, 08 Nov 2020 20:13:43 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=744</guid><description>&lt;p&gt;While working with Puppet recently I have noticed that there is some funny business going on with the rules of parameter naming. The Puppet&amp;rsquo;s documentation &lt;a href="https://puppet.com/docs/puppet/6.17/lang_reserved.html#variable-names"&gt;states&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Parameter names begin with a dollar sign prefix ($). The parameter name after the prefix:&lt;/p&gt;
&lt;p&gt;Must begin with a lowercase letter.&lt;/p&gt;
&lt;p&gt;Can include lowercase letters.&lt;/p&gt;
&lt;p&gt;Can include digits.&lt;/p&gt;
&lt;p&gt;Can include underscores.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let&amp;rsquo;s see if this is true. Tried applying this manifest with Puppet 5.5.10 which is available on Ubuntu Focal Fossa (20.04):&lt;/p&gt;</description></item><item><title>Yet Another Failed Website (Startup?) Idea: Discount Search Engine</title><link>https://giedrius.blog/2020/09/15/yet-another-failed-website-startup-idea-discount-search-engine/</link><pubDate>Tue, 15 Sep 2020 21:20:38 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=707</guid><description>&lt;figure&gt;
&lt;img loading="lazy" src="https://giedrius.blog/wp-content/uploads/2020/09/nuolaidos.online.resized.jpg"
alt="Main logo of the website"/&gt; &lt;figcaption&gt;
&lt;p&gt;Main logo of the website&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Hello everyone! I want to do a write-up of another failed website that I have tried to make in order to earn some side income. The attempt has been a bit different from the previous &lt;a href="https://giedrius.blog/2019/02/17/lessons-learned-from-trying-to-validate-a-software-business-idea-for-the-first-time/"&gt;one&lt;/a&gt; - I have built a minimal viable product in this case. I have done that so that I could try out my hypothesis about the feasibility and viability a bit more but, of course, it took more time. But I have tried to take every shortcut that I could have thought of.&lt;/p&gt;</description></item><item><title>Dangers of IsEmpty() With Enums and FluentValidation</title><link>https://giedrius.blog/2020/09/01/dangers-of-isempty-with-enums-and-fluentvalidation/</link><pubDate>Tue, 01 Sep 2020 14:27:24 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=699</guid><description>&lt;p&gt;I have recently run into this one small issue while using the &lt;a href="https://fluentvalidation.net/"&gt;FluentValidation&lt;/a&gt; library on &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/enum"&gt;enums&lt;/a&gt; in C#. In particular, there can be problems when using IsEmpty() on enums. Now I&amp;rsquo;m not an expert on C# but I will try my best to explain this issue.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s first start with a recap on how enums work. They allow you to associate some kind of numerical values with names, in essence. If you do not specify any explicit value for an enum value, the compiler automatically takes the numerical value of the previous enum that went in the same type and adds one to it. In the case of the non-existence of the previous value, it starts at 0.&lt;/p&gt;</description></item><item><title>Is it a good idea to use Prometheus for storing ASCII paintings?</title><link>https://giedrius.blog/2019/09/21/is-it-a-good-idea-to-use-prometheus-for-storing-ascii-paintings/</link><pubDate>Sat, 21 Sep 2019 10:35:31 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=592</guid><description>&lt;p&gt;In the Cloud-based computing world, a relatively popular free and open-source software product called &lt;a href="https://prometheus.io/"&gt;Prometheus&lt;/a&gt; exists which lets you monitor and observe other things. One of the components of its user interface lets you execute ad-hoc queries on the data that it has and see their results - not just in a table but also in a graphical way as well. For example, this is a query &lt;code&gt;time()&lt;/code&gt; which plots the current time using two dimensions:&lt;/p&gt;</description></item><item><title>Designing API Like It Is An Everyday Thing</title><link>https://giedrius.blog/2019/07/18/designing-api-like-it-is-an-everyday-thing/</link><pubDate>Thu, 18 Jul 2019 21:35:39 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=499</guid><description>&lt;p&gt;Recently I have read a quite popular book called &amp;ldquo;The Design of Everyday Things&amp;rdquo;. I feel that with software slowly taking over more and more parts of the world, we could say that it also became an everyday thing and that we should design it like that. This blog post will be about it.&lt;/p&gt;
&lt;p&gt;There are certain, general design principles that were explained in that book which we should apply to the process of programming in general.&lt;/p&gt;</description></item><item><title>Property-based testing in Golang</title><link>https://giedrius.blog/2019/07/08/property-based-testing-in-golang/</link><pubDate>Mon, 08 Jul 2019 19:35:23 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=529</guid><description>&lt;figure&gt;
&lt;img loading="lazy" src="https://cdn.pixabay.com/photo/2017/06/19/04/06/house-2418106%5F960%5F720.jpg"
alt="A simple house a.k.a. property"/&gt; &lt;figcaption&gt;
&lt;p&gt;A simple house a.k.a. property&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Testing software is ubiquitous and people naturally expect it to be a part of any kind of software development process. There are many different kinds of forms it can take:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;at the most rudimentary level: ad-hoc testing;&lt;/li&gt;
&lt;li&gt;integration testing;&lt;/li&gt;
&lt;li&gt;synthetic testing;&lt;/li&gt;
&lt;li&gt;and many others&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One of the forms that are quite novel is property-based testing. Essentially, the idea is to check if the software that you&amp;rsquo;ve produced espouses certain characteristics under inputs which have certain distinctive qualities. It sounds very similar to ordinary unit tests however here the catch is that a random number generator is leveraged in this case. Or, you can think of fuzzing but for ordinary code, not binary interfaces. It lets you run a bunch of tests very quickly and find the edge cases under which your code might not work as expected.&lt;/p&gt;</description></item><item><title>Lessons Learned From Trying To Validate a Software Business Idea for the First Time</title><link>https://giedrius.blog/2019/02/17/lessons-learned-from-trying-to-validate-a-software-business-idea-for-the-first-time/</link><pubDate>Sun, 17 Feb 2019 13:42:13 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=442</guid><description>&lt;figure&gt;
&lt;img loading="lazy" src="https://giedrius.blog/wp-content/uploads/2019/02/screencapture-date4gamers-2019-02-16-13%5F41%5F03.png" width="2880"/&gt;
&lt;/figure&gt;
&lt;p&gt;Like almost everyone, I also dream about starting my own business so that I could be free from the shackles of someone else and I would be my own boss. Or it could become potentially a source of passive income.&lt;/p&gt;
&lt;p&gt;As such, I have started reading some literature and sites like &lt;a href="https://indiehackers.com"&gt;Indiehackers&lt;/a&gt; to learn about how others start their own software businesses. After all, software is the thing that I am most skilled in and so I ought to connect that with the other things which are involved in having a successful business to start my own software company.&lt;/p&gt;</description></item><item><title>Capacity planning of Prometheus 2.4.2 + Thanos Sidecar 0.1.0</title><link>https://giedrius.blog/2018/12/16/capacity-planning-of-prometheus-2-4-2-thanos-sidecar-0-1-0/</link><pubDate>Sun, 16 Dec 2018 19:35:38 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=313</guid><description>&lt;figure&gt;
&lt;img loading="lazy" src="https://giedrius.blog/wp-content/uploads/2018/12/devops-what-is.png" width="955"/&gt;
&lt;/figure&gt;
&lt;h1 id="intro"&gt;Intro&lt;/h1&gt;
&lt;p&gt;Having a monitoring infrastructure is one of the tenets of the DevOps world. And, it seems that Prometheus and all of its extraneous integrations such as Thanos or Uber&amp;rsquo;s M3DB is taking over that world slowly. They give you a lot of improvements over the old Graphite set-ups such as increased reliability since Prometheus is based on HTTP which uses TCP thus you explicitly know when something goes wrong compared to UDP; it uses a pull based model so you explicitly know when something goes wrong and so on.&lt;/p&gt;</description></item><item><title>/etc/nsswitch.conf and /etc/hosts woes with the Alpine (and others) Docker image and Golang</title><link>https://giedrius.blog/2018/11/22/etc-nsswitch-conf-and-etc-hosts-woes-with-the-alpine-and-others-docker-image-and-golang/</link><pubDate>Thu, 22 Nov 2018 17:36:50 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=257</guid><description>&lt;p&gt;By default, the &lt;code&gt;alpine&lt;/code&gt; Docker image which is mostly used for Golang programs does &lt;a href="https://github.com/gliderlabs/docker-alpine/issues/367"&gt;&lt;em&gt;not&lt;/em&gt;&lt;/a&gt; contain &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt;. Golang&amp;rsquo;s &lt;code&gt;net&lt;/code&gt; package used to do a sane thing when that file did not exist back in the day (before April 30, 2015) i.e. they checked the &lt;code&gt;/etc/hosts&lt;/code&gt; file first, and then moved on to trying to query the DNS servers.&lt;/p&gt;
&lt;p&gt;However, it was changed later - now Go&amp;rsquo;s resolver tries to query the local machine as per the manual page of &lt;a href="http://man7.org/linux/man-pages/man5/nsswitch.conf.5.html"&gt;&lt;em&gt;nsswitch.conf(5)&lt;/em&gt;&lt;/a&gt;. You can find the commit &lt;a href="https://go-review.googlesource.com/c/go/+/9380/"&gt;here&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Ancient specification "bug": you cannot use colons in your username with the HTTP basic authentication method</title><link>https://giedrius.blog/2018/08/02/ancient-specification-bug-you-cannot-use-colons-in-your-username-with-the-http-basic-authentication-method/</link><pubDate>Thu, 02 Aug 2018 19:21:11 +0000</pubDate><guid isPermaLink="false">https://giedrius.blog/?p=231</guid><description>&lt;p&gt;Out there, in the wild exists a lot of different authentication schemes or methods however one of them which is relatively popular because it&amp;rsquo;s implemented in most popular browsers at the moment, has this one peculiar &amp;ldquo;bug&amp;rdquo; in its specification - you cannot use a colon (&amp;rsquo;:&amp;rsquo;) in the username field. If you have ever seen a window such as this:&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://giedrius.blog/wp-content/uploads/2018/08/Screen-Shot-2018-08-02-at-21.41.36.png" width="1774"/&gt;
&lt;/figure&gt;
&lt;p&gt;Then that website is probably using HTTP basic auth and you must not use a colon in your username on that site because simply you would not be able to do that.&lt;/p&gt;</description></item><item><title>scanf(3) is a newbie trap, use fgets(3) with sscanf(3) instead</title><link>https://giedrius.blog/2018/06/15/scanf-is-a-newbie-trap-use-fgets-sscanf-instead/</link><pubDate>Fri, 15 Jun 2018 23:11:53 +0000</pubDate><guid isPermaLink="false">http://giedrius.blog/?p=193</guid><description>&lt;p&gt;If you have not known before, &lt;code&gt;scanf(3)&lt;/code&gt; and &lt;code&gt;fgets(3)&lt;/code&gt; are both functions intended for reading something from standard input and doing something with the result - in the former case it is interpreted and the results might possibly be stored in specified arguments and in the latter case the result is simply put into a buffer. The first one is commonly recommended to beginner C programmers for reading something from the user and parsing it. However, it should be avoided mainly because it is very error-prone and it is difficult to understand how it actually works for new people. Instead of &lt;code&gt;scanf(3)&lt;/code&gt;, &lt;code&gt;sscanf(3)&lt;/code&gt; should be used in combination with &lt;code&gt;fgets(3)&lt;/code&gt;. That way, you can easily guess in what state your standard input stream is after using those functions and you get other benefits. Let me give some examples and explain more.&lt;/p&gt;</description></item><item><title>No, programming languages do not have speeds</title><link>https://giedrius.blog/2018/05/18/no-programming-languages-do-not-have-speeds/</link><pubDate>Fri, 18 May 2018 17:56:49 +0000</pubDate><guid isPermaLink="false">http://giedrius.blog/?p=188</guid><description>&lt;p&gt;I see time and time again this myth that programming languages have varying speeds perpetually peddled in various discussions between programmers in different IRC channels, forums, and so on. Some people think that, for example, C is much, much faster than Python. And a few of them go even further - they argue that C is a language that is &amp;ldquo;close to the metal&amp;rdquo;. Well, let me tell you. The code that you write in C is actually dedicated for a virtual machine that can eat that code and spit out assembly which roughly does the things that it is supposed to according to the C language standard. Why roughly? Simply because that virtual machine is poorly defined and it has a lot of undefined behaviour. This opposes our original argument that C is &amp;ldquo;close to the metal&amp;rdquo;. How could real hardware be poorly defined? Could it be that if you executed a certain instruction one time it would do something completely different, that was not mentioned at all in the CPU manual? Well, the answer is obviously no. Nobody would use such computers.&lt;/p&gt;</description></item><item><title>10 nuggets of knowledge that I picked up from "Code Complete"</title><link>https://giedrius.blog/2018/04/27/10-nuggets-of-knowledge-that-i-picked-up-from-code-complete/</link><pubDate>Fri, 27 Apr 2018 22:15:59 +0000</pubDate><guid isPermaLink="false">http://giedrius.blog/?p=181</guid><description>&lt;figure&gt;
&lt;img loading="lazy" src="https://giedrius.blog/wp-content/uploads/2018/04/5781724216906946015.jpg" width="338"/&gt;
&lt;/figure&gt;
&lt;p&gt;You could probably find &amp;ldquo;Code Complete&amp;rdquo; by Steve McConnell in any of the top 10 lists of books recommended to read for all programmers. I recently finished reading that book too. I have to confess that at times the tips and knowledge in there was a bit too basic and fundamental but, on the other hand, I also think that it has a lot of golden nuggets of knowledge.&lt;/p&gt;
&lt;p&gt;While reading it, I was writing down notes after every section. Essentially, they were three/four ideas that I thought were the most important in each section. Sometimes, they were paraphrased from the conclusions of each section written by the author himself. In other cases, I summarised them myself, in my own words.&lt;/p&gt;</description></item><item><title>Why os.move() Sometimes Does Not Work And Why shutil.move() Is The Savior?</title><link>https://giedrius.blog/2018/01/28/why-os-move-sometimes-does-not-work-and-why-shutil-move-is-the-savior/</link><pubDate>Sun, 28 Jan 2018 21:16:30 +0000</pubDate><guid isPermaLink="false">http://giedrius.blog/?p=120</guid><description>&lt;p&gt;Recently I ran into an issue where this, for example, code fails:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; os
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;rename(&lt;span style="color:#e6db74"&gt;&amp;#39;/foo/a.txt&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;/bar/b.txt&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Traceback (most recent call last):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;File &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, line &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#f92672"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;OSError&lt;/span&gt;: [Errno &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;] Invalid cross&lt;span style="color:#f92672"&gt;-&lt;/span&gt;device link
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;a href="https://docs.python.org/3/library/os.html"&gt;documentation&lt;/a&gt; for the &lt;em&gt;os&lt;/em&gt; module says that sometimes it might fail when the source and the destination are on different file-systems:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;os.rename&lt;/code&gt;( &lt;em&gt;src&lt;/em&gt;, &lt;em&gt;dst&lt;/em&gt;, &lt;em&gt;*&lt;/em&gt;, &lt;em&gt;src_dir_fd=None&lt;/em&gt;, &lt;em&gt;dst_dir_fd=None&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;Rename the file or directory src to dst. If dst is a directory, &lt;a href="https://docs.python.org/3/library/exceptions.html#OSError" title="OSError"&gt;&lt;code&gt;OSError&lt;/code&gt;&lt;/a&gt; will be raised. On Unix, if dst exists and is a file, it will be replaced silently if the user has permission. &lt;strong&gt;The operation may fail on some Unix flavors if src and dst are on different filesystems.&lt;/strong&gt; If successful, the renaming will be an atomic operation (this is a POSIX requirement). On Windows, if dst already exists, &lt;a href="https://docs.python.org/3/library/exceptions.html#OSError" title="OSError"&gt;&lt;code&gt;OSError&lt;/code&gt;&lt;/a&gt; will be raised even if it is a file.&lt;/p&gt;</description></item><item><title>What is Actually True and False in Python?</title><link>https://giedrius.blog/2018/01/04/what-is-actually-true-and-false-in-python/</link><pubDate>Thu, 04 Jan 2018 23:15:06 +0000</pubDate><guid isPermaLink="false">http://giedrius.blog/?p=85</guid><description>&lt;h1 id="intro"&gt;Intro&lt;/h1&gt;
&lt;p&gt;Did you know that in Python 2.x you can do the following?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt; python2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Python &lt;span style="color:#ae81ff"&gt;2.7.14&lt;/span&gt; (default, Sep &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2017&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;59&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[GCC &lt;span style="color:#ae81ff"&gt;7.2.0&lt;/span&gt;] on linux2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Type &lt;span style="color:#e6db74"&gt;&amp;#34;help&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;copyright&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;credits&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;or&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;license&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; more information&lt;span style="color:#f92672"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;How can it be that not True is True and True is equal to False? Why is it even possible to do this? Isn&amp;rsquo;t what is True and False in the language defined to be constant and unchangeable? What sense does it make to change the meaning of what is True and what is False? In any way, to fix this bug in the matrix, do this:&lt;/p&gt;</description></item><item><title>Making Unwinding Functions in C Simple: Do Not be Afraid of Using Gotos</title><link>https://giedrius.blog/2017/10/22/making-unwinding-functions-in-c-simple-do-not-be-afraid-of-using-gotos/</link><pubDate>Sun, 22 Oct 2017 14:41:19 +0000</pubDate><guid isPermaLink="false">http://giedrius.blog/?p=54</guid><description>&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;Today I wanted to talk about unwinding and releasing resources in C functions. Let’s begin by stating that there are three main techniques for handling errors in the C programming language. Sometimes more than one technique may be used. Here is a list of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You must test the value functions return. Abnormal value indicates that some kind of error has happened and a normal value indicates that it was successful;&lt;/li&gt;
&lt;li&gt;There is an external variable whose value you must check. For example, the POSIX variant of this is to have an variable called errno that changes to 0 when nothing bad happened and it has some kind of other value when an error occurs;&lt;/li&gt;
&lt;li&gt;You pass a pointer to a function. The function changes the value of the variable it points to or even calls it with certain arguments if it is a function pointer depending on the result.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have not mentioned one method but some people use atexit(3) to register functions that will be called at the end of a program which will release resources. However, this is unusual so I have not included it in the list.This is very much related to our topic because when an error occurs, you will have to handle it. That process includes releasing the resources which were acquired before in the function. Especially if you are deep down in your function and then an error occurred, the choice that you make in how to release the resources will matter a lot so it is important to make the correct decision. In C++ you have the destructors and so on but how are you going to do that in C? Are you going to sprinkle all of your error paths with:&lt;/p&gt;</description></item><item><title>On Trustworthiness of Sources While Gathering Information About Software</title><link>https://giedrius.blog/2017/08/27/on-trustworthiness-of-sources-while-gathering-information-about-software/</link><pubDate>Sun, 27 Aug 2017 16:34:17 +0000</pubDate><guid isPermaLink="false">http://giedrius.blog/?p=25</guid><description>&lt;p&gt;&lt;img alt="Read the fine manual" loading="lazy" src="https://giedrius.blog/wp-content/uploads/2017/08/rtfm.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Time and time I see people who follow all these random online tutorials and then when something does not work they become dazed and confused. “Why this does not work? But this tutorial shows that it should work” – I see similar questions occasionally in various forms on forums and IRC. I think people do not realize that there is some kind of hierarchy of trustworthiness of information sources. We should be conscious of that hierarchy when looking for information and remember it when we notice that something is not correct or up-to-date.&lt;/p&gt;</description></item><item><title>Why You Should Read Programming Books</title><link>https://giedrius.blog/2017/08/16/why-you-should-read-programming-books/</link><pubDate>Wed, 16 Aug 2017 05:31:17 +0000</pubDate><guid isPermaLink="false">http://giedrius.blog/?p=13</guid><description>&lt;p&gt;Nowadays it seems like we are on an information highway and it is very hard to keep up with all the knowledge. Especially this is acute when considering how many websites there are on the Internet and how long it would take you to read and understand them all. However, there is a solution – books offer a way to get condensed information from the field experts and learn a lot of things. Many people think that this is only true for other fields except programming. But I think that is false. In software development, a lot of things are timeless as well and they do not change so often. Let me present this and other arguments in more detail, and try to convince you to pick up a programming book and read it.&lt;/p&gt;</description></item></channel></rss>