<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[codeblend]]></title><description><![CDATA[codeblend]]></description><link>https://codeblend.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1661536724951/oXdYx-pRC.jpg</url><title>codeblend</title><link>https://codeblend.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 02:43:29 GMT</lastBuildDate><atom:link href="https://codeblend.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Working Code Isn’t Enough]]></title><description><![CDATA[In A Philosophy of Software Design, John Ousterhout argues that striving only for working code is not enough. The mindset of getting a feature done as fast as possible is not ideal, he calls this approach Tactical Programming.Tactical programming res...]]></description><link>https://codeblend.dev/working-code-isnt-enough</link><guid isPermaLink="true">https://codeblend.dev/working-code-isnt-enough</guid><category><![CDATA[design thinking]]></category><category><![CDATA[Complexity]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Tobias Haindl]]></dc:creator><pubDate>Tue, 11 Jun 2024 05:30:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Iq9SaJezkOE/upload/1e16c953dd076223da7e876a22db69c4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In <em>A Philosophy of Software Design,</em> John Ousterhout argues that striving only for working code is not enough. The mindset of getting a feature done as fast as possible is not ideal, he calls this approach <em>Tactical Programming</em>.<br />Tactical programming results in addition of too much unnecessary complexity since not enough time is spent on coming up with a well-designed solution for your problem. This approach seems reasonable since some developers have to perform in high-pressure environments. With the next deadline lurking around the corner aiming for working code as quickly as possible seems like a good idea. Unfortunately, achieving working code in a short period of time often involves taking shortcuts. Each little shortcut increases the complexity of our code which harms the quality of our software systems in the long run.</p>
<p>For Ousterhout the opposite of tactical programming is <em>Strategic Programming</em> which requires more long-term thinking and a different mindset. A strategic developer doesn't sacrifice well-designed code for quicker delivery time. Ousterhout encourages us to come up with different solutions for a specific task and continue with the best design. Of course this approach costs more time but Ousterhout argues that it pays of in the long run and I think most of us would agree.<br />Working in a well-designed codebase with fewer complexities enables us to not only develop new features faster but will also lead to fewer bugs in our software systems.</p>
<p>Personally, I think it is very important to think about those two approaches when we are developing software. I believe that none of us adds complexity to a system on purpose but due to deadlines and external pressure we might tell ourselves that the little shortcuts we take are not too bad. Unfortunately, only time will reveal the amount of complexity caused by our shortcuts.<br />Let’s fight off complexity and avoid taking too many shortcuts for faster delivery times.<br />I'm convinced that I will pay off in the long run!</p>
]]></content:encoded></item><item><title><![CDATA[Spring IO 2024: Day 1]]></title><description><![CDATA[Spring IO opened with an awesome keynote featuring various members of the Spring team.They showcased new additions to the ecosystem like Spring AI and Spring Modulith and presented features that have been recently added to the Spring Framework.
My fa...]]></description><link>https://codeblend.dev/spring-io-2024-day-1</link><guid isPermaLink="true">https://codeblend.dev/spring-io-2024-day-1</guid><category><![CDATA[Java]]></category><category><![CDATA[Spring]]></category><category><![CDATA[Spring Boot]]></category><dc:creator><![CDATA[Tobias Haindl]]></dc:creator><pubDate>Thu, 30 May 2024 19:56:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/hVhfqhDYciU/upload/7b1b3afcf33eeeb53d06963066933a90.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Spring IO opened with an awesome keynote featuring various members of the Spring team.<br />They showcased new additions to the ecosystem like Spring AI and Spring Modulith and presented features that have been recently added to the Spring Framework.</p>
<p>My favorite quote from the keynote was: <em>Make Monoliths Modern Again</em> by Cora Iberkleid. We should definitely work hard to avoid building big balls of (distributed) mud 🙂</p>
<p>In <em>This Ain’t Your Parents’ Java</em> Venkat Subramiam discussed how Java is evolving continuously and coming up with neat language features allowing us and future generations of developer to write better and more maintainable code.<br />Favorite quotes:</p>
<ul>
<li><p><em>They call this casting, I call it punishment</em></p>
</li>
<li><p><em>Don’t work for the compiler, let the compiler work for you</em></p>
</li>
</ul>
<p>Daniel Garnier-Moiroux did a great job in explaining core concepts of Spring Security like filters and the <code>Authentication</code> interface.<br />Key takeaways:</p>
<ul>
<li><p>You can become a Spring Security ninja by enabling TRACE logging for <a target="_blank" href="http://org.springframework.security"><code>org.springframework.security</code></a> and digging through the logs</p>
</li>
<li><p>Writing some extra code for proper emoji support is always worth it 🙂</p>
</li>
</ul>
<p>After the lunch break Philip Riecks kicked of this Spring Boot testing workshop.<br />He gave an excellent overview about the out-of-the box features provided by the Spring Boot Starter Test and presented useful testing libraries like WireMock and Testcontainers.</p>
<p>Key takeaways:</p>
<ul>
<li><p>Pay attention to the number of Spring contexts created during the execution of your test suite. Keep the number low to ensure fast feedback cycles.</p>
</li>
<li><p>With some creativity you can even use Java testing libraries for excelling at your favorite browser game 😉</p>
</li>
</ul>
<p>Аlina Yurenko talked about the past, the present and the future of GraalVM in her session and demonstrated the power of going native with the help of benchmarking demos.</p>
<p>Key takeaway:</p>
<ul>
<li><p>Always use GraalVM ! 😉 (Since it provides a high-performance JIT compiler as well)</p>
</li>
<li><p>Adopt a pet!</p>
</li>
</ul>
<p>In the final session of the day, Joris Kuipers emphasized that production-grade applications require more than just architecture and business logic to succeed.<br />He provided useful and applicable tips for logging, caching and error handling.</p>
<p>Key takeaways:</p>
<ul>
<li><p>Start building your own Autoconfigurations to share functionality between projects/modules</p>
</li>
<li><p>Save time and money by using proper caching</p>
</li>
</ul>
<p>I thoroughly enjoyed today’s sessions, and I'm already looking forward to day 2 of Spring IO 2024.</p>
<p>A big shout-out to all the speakers and the exceptional organization team for making this conference both possible and fantastic.</p>
]]></content:encoded></item><item><title><![CDATA[Container Deep Dive 2: Container Engines]]></title><description><![CDATA[In the last post of this series we had a closer look at Container Runtimes.However, for us developers interacting with Container Runtimes is tedious and not straightforward since they have not been designed to be consumed directly by the end-user.
Th...]]></description><link>https://codeblend.dev/container-deep-dive-2-container-engines</link><guid isPermaLink="true">https://codeblend.dev/container-deep-dive-2-container-engines</guid><category><![CDATA[Docker]]></category><category><![CDATA[containers]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[beginner]]></category><dc:creator><![CDATA[Tobias Haindl]]></dc:creator><pubDate>Thu, 01 Dec 2022 17:16:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/xFjti9rYILo/upload/v1669541719900/Dk6gcNkZ3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last post of this series we had a closer look at Container Runtimes.<br />However, for us developers interacting with Container Runtimes is tedious and not straightforward since they have not been designed to be consumed directly by the end-user.</p>
<p>This issue is solved by Container Engines!<br />They provide convenient APIs for interacting with Container Runtimes without having to know all the low-level details.<br />Furthermore, this abstraction allows using <strong>different</strong> Container Runtimes if necessary.</p>
<p>If you started a container on your local machine once, you already interacted with a Container Engine since Docker is one of the most popular engines out there.</p>
<p>The <code>docker</code> Command Line Interface (CLI) allows us to interact with the heart of the Container engine.<br />In Docker terms called the Docker Daemon.<br />This CLI provides a high level of abstraction for the end-user since it focuses on the <strong>most</strong> important parts of a container's life cycle.<br />The CLI allows us to: </p>
<ul>
<li>start a new container</li>
<li>stop a container</li>
<li>restart a stopped container</li>
<li>fetch a new image</li>
<li>... and much more</li>
</ul>
<p>Based on that brief overview of functionality we can extract the main responsibilities of a Container Engine:</p>
<ul>
<li>Management of the container life cycle (forwarding proper commands to the underlying runtime)</li>
<li>Pulling and pushing container images to image repositories</li>
<li>Configuring storage for containers</li>
</ul>
<p>Since we are now more familiar with the functionalities provided by a Container Engine, let’s have a closer look at two very popular engines:</p>
<h1 id="heading-docker">Docker</h1>
<p>The Docker Engine consists of the following parts:</p>
<ul>
<li><code>dockerd</code> a long-running daemon process which acts as server. Also called Docker daemon</li>
<li>the <code>docker</code> CLI which acts as a client and communicates with <code>dockerd</code> via the <code>Docker Engine API</code></li>
</ul>
<p>The Docker daemon comes with it's one CLI called <a target="_blank" href="https://docs.docker.com/engine/reference/commandline/dockerd/"><code>dockerd</code></a>.<br />It can be configured either by passing flags to <code>dockerd</code> or a JSON configuration file.   </p>
<p>Once a request from the <code>Docker Engine API</code> is received, the Docker daemon takes care of processing the request and reporting the status back to the <code>docker</code> CLI.<br />Under the hood <code>containerd</code> is used for interacting with the underlying Container runtime (in this case <code>runc</code>).<br />So the Docker daemon does not interact with the Container runtime directly but makes use of another abstraction layer on top of <code>runc</code>, called <code>containerd</code>.<br />If you haven't heard about Container Runtimes, check out the first article of this series: <a target="_blank" href="https://codeblend.dev/container-deep-dive-part-1-container-runtime">Container Runtimes</a>.  </p>
<p>If you want to tinker with the <code>Docker Engine API</code> you can use the API directly via HTTP  or integrate a provided SDK into your code.<br />See <a target="_blank" href="https://docs.docker.com/engine/api/">API docs</a> for more information.</p>
<p>The client-server architecture of Docker allows the <code>docker</code> CLI to easily interact with remote Docker daemons as well.
The Docker daemon process can listen to requests from the <code>Docker Engine API</code> via three different socket types:</p>
<ul>
<li>unix</li>
<li>fd</li>
<li>tcp</li>
</ul>
<p>TCP sockets enable the possibility for remote connections. 
The other two socket types are bound to the host and cannot be access from a remote machine.    </p>
<p>Docker is a prominent example of a Container Engine.  It gained a lot of popularity since the initial release in 2013.<br />However, with the rise of Kubernetes another popular engine was born.<br />Let's have a look at <code>CRIO-O</code>.  </p>
<h1 id="heading-cri-o">CRI-O</h1>
<blockquote>
<p>The <a target="_blank" href="http://cri-o.io/">CRI-O</a> container engine provides a stable, more secure, and performant platform for running <a target="_blank" href="https://www.opencontainers.org/">Open Container Initiative</a> (OCI) compatible runtimes.<br />CRI-O’s purpose is to be the container engine that implements the Kubernetes Container Runtime Interface (CRI) for OpenShift Container Platform and Kubernetes, replacing the Docker service.<br /><a target="_blank" href="https://docs.openshift.com/container-platform/3.11/crio/crio_runtime.html">Source</a></p>
</blockquote>
<p>The CRI-O container engine can launch a container by using an OCI-compliant Container Runtime like <code>runc</code>.</p>
<p>It uses <code>containers/image</code> library to pull images from a registry. 
Therefore, it supports Docker schema2/version 1 and schema2/version2.</p>
<p>Although it is not really necessary to interact with CRI-O directly, CRI-O comes with a bunch of CLIs and tools:</p>
<ul>
<li><code>crictl</code>: allows debugging issue with the underlying runtime without having to set up other Kubernetes components</li>
<li><code>runc</code>: CLI for interacting directly with the runtime</li>
<li><code>podman</code>: offers the same command-line features as the <code>docker</code> CLI and additional features on top of it</li>
<li><code>buildah</code>: allows building of OCI images <strong>with</strong> and <strong>without</strong> a Dockerfile</li>
<li><code>skopeo</code>: helps with the management of container images</li>
</ul>
<p>For more information regarding the bundled tools see: 
<a target="_blank" href="https://github.com/containers/buildah/tree/main/docs/containertools">CRI tools</a>.  </p>
<p>Why was <code>CRI-O</code> created?<br /><code>CRI-O</code> was started by Red Hat, with the goal of decoupling Kubernetes from Docker.<br />It is now a project of the Cloud Native Computing Foundation.<br />With it, it is possible to use any OCI compliant Container Runtime in Kubernetes.<br />Since both <code>containerd</code> and <code>CRI-O</code> implement the Kubernetes Container Runtime Interface both can be used easily in Kubernetes.  </p>
<h1 id="heading-wrap-up">Wrap up</h1>
<p>Let's summarize what was covered in this article:  </p>
<p>First, we had a look at the responsibilities of a Container Engine.<br />Then we had a closer look at how the Docker Container Engine works under the hood.<br />Last but not least, <code>CRI-O</code> was introduced as an alternative to Docker.  </p>
]]></content:encoded></item><item><title><![CDATA[Container Deep Dive 1: Container Runtime]]></title><description><![CDATA[Containerization technologies stand upon the shoulders of giants.Several building blocks are needed to make Docker, Kubernetes and co as powerful as they currently are.In this series I want to explore each layer of those tools individually.We will st...]]></description><link>https://codeblend.dev/container-deep-dive-1-container-runtime</link><guid isPermaLink="true">https://codeblend.dev/container-deep-dive-1-container-runtime</guid><category><![CDATA[Docker]]></category><category><![CDATA[containers]]></category><category><![CDATA[OCI]]></category><category><![CDATA[CNCF]]></category><category><![CDATA[cncflandscape]]></category><dc:creator><![CDATA[Tobias Haindl]]></dc:creator><pubDate>Sun, 06 Nov 2022 15:23:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/RJPEfLuv6Ao/upload/v1667663097935/iM6OFx_jX.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Containerization technologies stand upon the shoulders of giants.<br />Several building blocks are needed to make Docker, Kubernetes and co as powerful as they currently are.<br />In this series I want to explore each layer of those tools individually.<br />We will start at the bottom with Container Runtimes and move upwards to higher abstraction layers.<br /><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667740596298/szkz3Hvkb.png" alt="containerization.png" />  </p>
<h1 id="heading-container-runtime">Container Runtime</h1>
<p>A Container Runtime provides an execution environment for processes in an isolated manner (a container).<br />The most common Container Runtimes follow the Open Container Initiative (OCI) Runtime Specification.   </p>
<ul>
<li>What is the purpose of this specification?   </li>
<li>What does it include?  </li>
</ul>
<blockquote>
<p>Open Container Initiative Runtime Specification aims to specify the configuration, execution environment, and lifecycle of a container.<br /><a target="_blank" href="https://github.com/opencontainers/runtime-spec/blob/main/spec.md">Source</a></p>
</blockquote>
<p>A detailed specification exists for different platforms (Linux, Windows etc.).<br />The Linux specification for example includes: </p>
<ul>
<li>available Namespaces</li>
<li>available File systems</li>
<li>available Devices</li>
</ul>
<p>Let’s have a look at three prominent Container Runtimes:</p>
<ul>
<li>runc</li>
<li>crun</li>
<li>gVisor (runsc)</li>
</ul>
<h2 id="heading-runc">runc</h2>
<p>Is a low level CLI capable of spawning and managing containers compliant with the OCI Runtime Specification.<br />It is written in Go and a project of the OCI.</p>
<p>Since it takes care of low level interactions it is not recommended to use runc directly. </p>
<blockquote>
<p>…unless there is some specific use case that prevents the use of tools like Docker or Podman, it is not recommended to use runc directly.<br /><a target="_blank" href="https://github.com/opencontainers/runc#using-runc">Source</a></p>
</blockquote>
<p>So if you want to build the next Docker, feel free to use it directly :)</p>
<p>runc is currently used by Docker as a default Container Runtime and can be used with Podman &amp; Kubernetes as well.</p>
<h2 id="heading-crun">crun</h2>
<p>crun basically solves the same problem as runc: creation and management of the actual container instances.<br />Of course it also fully implements the OCI Runtime Specification.<br />crun is written in C and promises a lower memory footprint and better performance. 
crun is used by default by Podman and can be used with Docker &amp; Kubernetes as well.</p>
<h2 id="heading-gvisor-runsc">gVisor (runsc)</h2>
<p>gVisor is all about security. It includes a container runtime matching the OCI Runtime specification called runsc.<br />For improved security, containers created by gVisor are <strong>sandboxed</strong> which leads to better isolation between your containers and the host system.<br />Only a limited surface of the host kernel is available for the container and calls to it are intercepted and monitored for suspicious activities.<br />gVisor is written in Go and maintained by Google.<br />runsc can be used with Docker &amp; Kubernetes.</p>
<h1 id="heading-summary">Summary</h1>
<p>In this article we had a look at the most basic building block of any modern Containerization tool. 
We briefly touched the Container Runtime Specification from the Open Container Initiative and compared three different implementations of the specification.</p>
<p>In the next article we will explore Container Engines!</p>
]]></content:encoded></item><item><title><![CDATA[Why I love IntelliJ's database window]]></title><description><![CDATA[In this article I want to share some of my favorite features of IntelliJ's database window/console.Let's jump right in!
Find usage of tables
One of my most used shortcuts is “Find usage” but it took me quite some time to figure out that this also wor...]]></description><link>https://codeblend.dev/why-i-love-intellijs-database-window</link><guid isPermaLink="true">https://codeblend.dev/why-i-love-intellijs-database-window</guid><category><![CDATA[intellij]]></category><category><![CDATA[Databases]]></category><category><![CDATA[Java]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[tips]]></category><dc:creator><![CDATA[Tobias Haindl]]></dc:creator><pubDate>Fri, 28 Oct 2022 16:36:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/lRoX0shwjUQ/upload/v1666974778178/0fKxmsla5l.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article I want to share some of my favorite features of IntelliJ's database window/console.<br />Let's jump right in!</p>
<h1 id="heading-find-usage-of-tables">Find usage of tables</h1>
<p>One of my most used shortcuts is “Find usage” but it took me quite some time to figure out that this also works with database objects like tables:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661022982152/m0-kuWqpv.png" alt="usage" /></p>
<p>This makes refactoring your database easier since you can analyze the dependencies between your database objects and your source code quite effortless with the help of “Find usage”</p>
<h1 id="heading-multiple-consoles">Multiple consoles</h1>
<p>In IntelliJ, it is possible to have multiple database consoles for a single data source.<br />All open consoles can be found under Scratches and Consoles in the side navigation:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661022989903/Dd7CThSce.png" alt="consoles" /></p>
<p>Furthermore, those console can be renamed like all the other files in your project!<br />For me this is especially helpful when I have to switch between different issues or tasks. 
With the help of multiple consoles I can keep all the queries needed for analyzing an issue together in one console and even give the console a telling name, so I can find those queries faster later on.</p>
<h1 id="heading-safety-features">Safety features</h1>
<h2 id="heading-preview-delete">Preview delete</h2>
<p>Like in the “normal” source code editor ALT + ENTER is your best friend in the database console as well.
With it, you can safely preview a delete query!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661022999215/fj0AO38k6.png" alt="preview-delete" /></p>
<p>Gives a preview of the affected row:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661023043742/6o9hchdhH.png" alt="affected-row" /></p>
<p>In my opinion this makes removing data from your production database far more comfortable 🙂</p>
<h2 id="heading-warnings">Warnings</h2>
<p>Tired of dropping all your data due to a missing <code>where</code> condition in your delete statement?
IntelliJ issues a warning for unsafe statement and requires extra confirmation before executing such statements.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666975509537/kIcd9Werh.png" alt="image.png" />
Quite helpful in my opinion!
This also works for update statements:  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666975492087/j17aB9Q5_.png" alt="image.png" /></p>
<h1 id="heading-auto-expand-column-names">Auto-expand column names</h1>
<p>Last but not least, auto expansion!<br />Let’s say you want to select <strong>nearly</strong> all of your columns but do not want to type all column names manually.<br />In my opinion the easiest way to achieve this is by using the expand column list feature.
Simply write: <code>SELECT * FROM &lt;your_table&gt;</code> highlight the asterisk character and press ALT + ENTER. 
This will give you all the column names, afterwards you can delete any unwanted column!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661023063535/CHiZiSDjK.gif" alt="expand-column-list.gif" /></p>
<h1 id="heading-wrap-up">Wrap up</h1>
<p>That's all from my side for now.<br />What do you think about the mentioned features?<br />Did I miss a feature you love?<br />Let me know in the comments!</p>
]]></content:encoded></item><item><title><![CDATA[Building Flutter Linux on Manjaro]]></title><description><![CDATA[Last week I was eager to check out a little Flutter application built by Lucas Schuster.I was especially interested in trying the Flutter Desktop support for Linux.After installing Flutter via fvm, I checked out his Git repository and issued the foll...]]></description><link>https://codeblend.dev/building-flutter-linux-on-manjaro</link><guid isPermaLink="true">https://codeblend.dev/building-flutter-linux-on-manjaro</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Linux]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Tobias Haindl]]></dc:creator><pubDate>Sat, 06 Aug 2022 08:56:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/8Gg2Ne_uTcM/upload/v1659377309497/00i0UHbC3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last week I was eager to check out a little Flutter application built by <a class="user-mention" href="https://hashnode.com/@internerd">Lucas Schuster</a>.<br />I was especially interested in trying the Flutter Desktop support for Linux.<br />After installing Flutter via <a target="_blank" href="https://github.com/fluttertools/fvm">fvm</a>, I checked out his Git repository and issued the following command for building the Flutter app on Linux:</p>
<pre><code><span class="hljs-attribute">flutter</span> build linux
</code></pre><p>Unfortunately this gave me the following error message:</p>
<pre><code>CMake <span class="hljs-built_in">Error</span> at <span class="hljs-operator">/</span>usr<span class="hljs-operator">/</span>share<span class="hljs-operator">/</span>cmake<span class="hljs-operator">/</span>Modules<span class="hljs-operator">/</span>FindPkgConfig.cmake:<span class="hljs-number">605</span> (message):
A required package was not found
Call Stack (most recent call first):
<span class="hljs-operator">/</span>usr<span class="hljs-operator">/</span>share<span class="hljs-operator">/</span>cmake<span class="hljs-operator">/</span>Modules<span class="hljs-operator">/</span>FindPkgConfig.cmake:<span class="hljs-number">827</span> (_pkg_check_modules_internal)
flutter<span class="hljs-operator">/</span>CMakeLists.txt:<span class="hljs-number">25</span> (pkg_check_modules)
</code></pre><p>I doubled checked the <a target="_blank" href="https://docs.flutter.dev/development/platform-integration/desktop">official documentation</a> and verified that the following packages were installed:</p>
<ul>
<li>clang </li>
<li>cmake </li>
<li>ninja-build </li>
<li>pkg-config </li>
<li>gtk3</li>
</ul>
<p>Afterwards I reran the build command but with the verbose flag enabled:</p>
<pre><code><span class="hljs-attribute">flutter</span> build linux -v
</code></pre><p>Which resulted in:  </p>
<pre><code>[        ] <span class="hljs-operator">-</span><span class="hljs-operator">-</span> Checking <span class="hljs-keyword">for</span> module <span class="hljs-string">'gtk+-3.0'</span>
[   <span class="hljs-operator">+</span><span class="hljs-number">1</span> ms] <span class="hljs-operator">-</span><span class="hljs-operator">-</span>   No package <span class="hljs-string">'gtk+-3.0'</span> found
</code></pre><p>Flutter was not able to locate my gtk installation.<br />You can check if <code>pkg-config</code> can locate the package by running:</p>
<pre><code>pkg<span class="hljs-operator">-</span>config <span class="hljs-operator">-</span><span class="hljs-operator">-</span>libs gtk<span class="hljs-operator">+</span><span class="hljs-number">-3.0</span>
</code></pre><p>This command returned the following error on my system:</p>
<pre><code>Package gtk<span class="hljs-operator">+</span><span class="hljs-number">-3.0</span> was not found in the pkg<span class="hljs-operator">-</span>config search path.
Perhaps you should add the directory containing `gtk<span class="hljs-operator">+</span><span class="hljs-number">-3.0</span>.pc'
to the PKG_CONFIG_PATH environment variable
No package <span class="hljs-string">'gtk+-3.0'</span> found
</code></pre><p>I fixed this by figuring out where <code>gtk3</code> is installed and adding the directory to the <code>PKG_CONFIG_PATH</code> variable.<br />Check where the package is located:</p>
<pre><code>pacman <span class="hljs-operator">-</span>Ql gtk3

gtk3 <span class="hljs-operator">/</span>usr<span class="hljs-operator">/</span>lib<span class="hljs-operator">/</span>pkgconfig<span class="hljs-operator">/</span>gtk<span class="hljs-operator">+</span><span class="hljs-number">-3.0</span>.pc
</code></pre><p>Let's add this directory to <code>PKG_CONFIG_PATH</code> environment variable:</p>
<pre><code>export PKG_CONFIG_PATH<span class="hljs-operator">=</span><span class="hljs-operator">/</span>usr<span class="hljs-operator">/</span>lib<span class="hljs-operator">/</span>pkgconfig
</code></pre><p>You might want to add this to your <code>.bashrc</code> or <code>.zshrc</code> config file.<br />Don't forget to reload your environment, e.g. with the <code>source ~/.zshrc</code>!</p>
<p>After modifying the <code>PKG_CONFIG_PATH</code> the Flutter build returned:</p>
<pre><code>Package <span class="hljs-string">'shared-mime-info'</span>, required <span class="hljs-keyword">by</span> <span class="hljs-string">'gdk-pixbuf-2.0'</span>, <span class="hljs-keyword">not</span> <span class="hljs-built_in">found</span>
Configuring incomplete, errors occurred!
</code></pre><p>Okay, another familiar error, let's check if <code>shared-mime-info</code> is available:</p>
<pre><code>pkg<span class="hljs-operator">-</span>config <span class="hljs-operator">-</span><span class="hljs-operator">-</span>libs shared<span class="hljs-operator">-</span>mime<span class="hljs-operator">-</span>info
</code></pre><p>If the package was not found on your system, you can install it via <code>yay</code> or <code>pacman</code><br />E.g.:
<code>yay -Sy shared-mime-info</code><br />Afterwards check the installation path:
<code>yay -Ql shared-mime-info</code><br />Search for the directory including the <code>shared-mime-info.pc</code> file, in my case it was: 
<code>/usr/share/pkgconfig/</code></p>
<p>Therefore, I added this directory to the <code>PKG_CONFIG_PATH</code> as well:<br /><code>export PKG_CONFIG_PATH=/usr/lib/pkgconfig/:/usr/share/pkgconfig/</code></p>
<p>Afterwards I was able to build and run the Flutter application on Manjaro!</p>
]]></content:encoded></item><item><title><![CDATA[Analyze your coding activity in a privacy-friendly way]]></title><description><![CDATA[These days data is ubiquitous, we generate loads of data each day, consciously and unconsciously.I'm not the biggest fan of giving away my personal data, but I still like to analyze my spent time by tracking some stats. This also applies for my codin...]]></description><link>https://codeblend.dev/analyze-your-coding-activity-in-a-privacy-friendly-way</link><guid isPermaLink="true">https://codeblend.dev/analyze-your-coding-activity-in-a-privacy-friendly-way</guid><category><![CDATA[Docker]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[statistics]]></category><category><![CDATA[habits]]></category><dc:creator><![CDATA[Tobias Haindl]]></dc:creator><pubDate>Thu, 23 Jun 2022 07:02:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/6EnTPvPPL6I/upload/v1653134488580/5-wePpHct.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>These days data is ubiquitous, we generate loads of data each day, consciously and unconsciously.<br />I'm not the biggest fan of giving away my personal data, but I still like to analyze my spent time by tracking some stats. This also applies for my coding activity.<br />That's why I was looking for an open source tools which helps with tracking and analyzing my coding time.<br />I found a great open-source, privacy-friendly tool called Wakapi which can help with those tasks.</p>
<h2 id="heading-wakapihttpsgithubcommuetywakapi"><a target="_blank" href="https://github.com/muety/wakapi">Wakapi</a></h2>
<p>Wakapi is a Wakatime compatible open-source backend for collecting and visualizing coding statistics.
It can be self-hosted fairly easily be running the provided Docker image.<br />The compatibility with Wakatime is a big bonus since Wakatime provides many plugins for data collection from your favorite IDE or text editor. 
I'm pretty sure you can find an integration for your most loved tool <a target="_blank" href="https://wakatime.com/plugins">here</a>.<br />Let's see how one can run Wakapi with Docker.</p>
<h3 id="heading-running-with-docker">Running with Docker</h3>
<p>First we will create a Docker volume to make sure our data is not lost when the container is stopped/removed:<br /><code>docker volume create wakapi-data</code></p>
<p>To make sure user passwords are hashed properly we generate a salt:<br /><code>SALT="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-32} | head -n 1)"</code></p>
<p>Then we run the Docker image:<br /><code>docker run -d \
  -p 3000:3000 \
  -e "WAKAPI_PASSWORD_SALT=$SALT" \
  -v wakapi-data:/data \
  --name wakapi \
  ghcr.io/muety/wakapi:latest</code><br /><a target="_blank" href="https://github.com/muety/wakapi">Source</a></p>
<h3 id="heading-create-account">Create account</h3>
<p>After the Docker container is up and running, we need to create an admin account.<br />Navigate to your Wakapi frontend e.g. if run locally http://localhost:3000/login and sign up there.<br />The first registered account will become the admin account for this Wakapi instance.
After you are logged in you can obtain your personal API key in the top right corner:
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ua33fmc88idikvugqiid.png" alt="Wakapi API key" /> (Don't worry the API key in the screenshot is from a local instance ;))<br />If you do not want any other users to create an account on your instance, you can set <code>WAKAPI_ALLOW_SIGNUP</code> environment variable to false.</p>
<h3 id="heading-configure-the-plugin">Configure the plugin</h3>
<p>After the account creation is done, you need to install the Wakatime plugin for your desired IDE. Once the installation is done you need to configure it to use your own Wakapi instance by creating a config file under <code>~/.wakatime.cfg</code> with the following content:  </p>
<pre><code><span class="hljs-section">[settings]</span>

<span class="hljs-comment"># Your Wakapi server URL</span>
<span class="hljs-attr">api_url</span> = http://localhost:<span class="hljs-number">3000</span>/api/heartbeat

<span class="hljs-comment"># Wakapi API key, obtained from the web interface in the previous step</span>
<span class="hljs-attr">api_key</span> = <span class="hljs-number">406</span>fe41f-<span class="hljs-number">6</span>d69-<span class="hljs-number">4183</span>-a4cc-<span class="hljs-number">121</span>e0c524c2b
</code></pre><h3 id="heading-analyze-your-activity">Analyze your activity</h3>
<p>After the Wakatime plugin is configured properly, it should send data from your IDE/editor to your Wakapi backend where your statistics are waiting for you to be analyzed. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655896375609/aSIjMlR43.png" alt="wakapi.png" /></p>
<p>Wakapi provides filters for different time-windows and statistics for editor usage, time spent on projects, time spent coding in a certain language.</p>
<h3 id="heading-wrap-up">Wrap up</h3>
<p>I think it is quite useful to visualize your coding activity. It provides insights into how you spend your days and might help optimizing your daily schedule.</p>
<p>Shout-out to <a target="_blank" href="https://muetsch.io/">Ferdinand Mütsch</a> for creating this amazing open-source tool and thanks to <a target="_blank" href="https://wakatime.com/">Wakatime</a> for open-sourcing their plugins.</p>
]]></content:encoded></item></channel></rss>