<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stefan Verkerk</title>
    <description>The latest articles on DEV Community by Stefan Verkerk (@aksie).</description>
    <link>https://dev.to/aksie</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F73219%2F8bb0c128-8d37-45b9-9725-2e632f0e32ab.jpg</url>
      <title>DEV Community: Stefan Verkerk</title>
      <link>https://dev.to/aksie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aksie"/>
    <language>en</language>
    <item>
      <title>How AppSignal Monitors Their Own Kafka Brokers</title>
      <dc:creator>Stefan Verkerk</dc:creator>
      <pubDate>Thu, 30 Jul 2020 15:35:53 +0000</pubDate>
      <link>https://dev.to/appsignal/how-appsignal-monitors-their-own-kafka-brokers-g65</link>
      <guid>https://dev.to/appsignal/how-appsignal-monitors-their-own-kafka-brokers-g65</guid>
      <description>&lt;p&gt;Today, we dip our toes into collecting custom metrics with a standalone agent. We'll be taking our own Kafka brokers and using the StatsD protocol to get the metrics into AppSignal. This post is for those with some experience in using monitoring tools, and who want to take monitoring to every corner of their architecture, or want to add their own metrics to their monitoring setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Standalone Agent
&lt;/h2&gt;

&lt;p&gt;AppSignal for Ruby, Elixir, and Node out-of-the-box gives you all one in one monitoring: errors, performance, host metrics, custom metrics, and dashboards.&lt;/p&gt;

&lt;p&gt;By having all relevant metrics collected and sent to AppSignal, all the monitoring data is in one place. That is one of the things we think is crucial about good monitoring:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You need to have errors, performance and host metrics in one place, and you need as much of your architecture monitored like that in one place.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That way you can triage from all angles. For example, you might spot at a performance issue in a background job, then see it is caused by a long wait on the DB server, and then find out that that was caused by network issues on the host the database runs on.&lt;/p&gt;

&lt;p&gt;This works out-of-the-box in a Ruby, Elixir or Node.js app. If you have part of your architecture run on systems without any Ruby, Elixir or Node.js, you can add their metrics to AppSignal as well using the standalone agent. For example, when you have certain workers do things in Rust, or when you have a standalone database server.&lt;/p&gt;

&lt;h2&gt;
  
  
  How WE do In-house Monitoring
&lt;/h2&gt;

&lt;p&gt;We use this setup to monitor our Kafka brokers. &lt;/p&gt;

&lt;p&gt;One of the things we need to keep a close eye on is available retention in Kafka. There are some hard limits on disk space and we need to make sure we can achieve the required retention. Otherwise, we need to expand our cluster.&lt;/p&gt;

&lt;p&gt;Because the requests we monitor for our customers can have a lot of metadata added to them, that means that Kafka's topics can be huge. To make sure things don't go astray because a host disk is used fully, we've dimensioned our Kafka setup by disk usage that we monitor as well. 😉&lt;/p&gt;

&lt;p&gt;Disk usage is easy to monitor because the standalone AppSignal agent will automatically send host metrics to AppSignal right out of the box.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.appsignal.com%2Fimages%2Fblog%2F2020-03%2FHost_metrics.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.appsignal.com%2Fimages%2Fblog%2F2020-03%2FHost_metrics.png" alt="Kafka host metrics on AppSignal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can actually see see in this 30 day resolution graph when we did a clean up of that disk, way before things went wrong 😁&lt;/p&gt;

&lt;p&gt;That leaves retention. Retention is not available in Kafka's standard metrics, so we have to find another solution. We monitor retention by looking at the first indexed timestamp of each partition/topic on the broker itself. If that is shorter than a set amount of hours/days, we'd like to be notified as that might impact our customers during an outage. &lt;/p&gt;

&lt;p&gt;We do so using our Kafka monitoring tool (called Watchman). It is written in Rust and we use a (very simple) StatsD client code to send data to the &lt;a href="https://docs.appsignal.com/standalone-agent/installation.html" rel="noopener noreferrer"&gt;standalone AppSignal Agent&lt;/a&gt; running on each broker.&lt;/p&gt;

&lt;p&gt;In our watchman process we send these retention metrics to the AppSignal agent that listens to StatsD:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="n"&gt;statsd_client&lt;/span&gt;&lt;span class="nf"&gt;.send_gauge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"topic_retention_hours"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;now_timestamp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;3600.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"topic:{},partition:{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;   &lt;span class="n"&gt;statsd_client&lt;/span&gt;&lt;span class="nf"&gt;.send_gauge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"topic_retention_short"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ms_short&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"topic:{},partition:{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kafka brokers report many more metrics, with JMX as the default reporter. So besides watchman, we also send these JMX metrics to our Standalone Agent running on the server. &lt;/p&gt;

&lt;h2&gt;
  
  
  Using Monitoring Data With Graphs and Triggers
&lt;/h2&gt;

&lt;p&gt;Once that data gets into AppSignal, you can make dashboards with it, and set triggers like with everything in AppSignal.&lt;/p&gt;

&lt;p&gt;Here’s what that dashboard looks like on AppSignal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.appsignal.com%2Fimages%2Fblog%2F2020-03%2FTopic_retention.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.appsignal.com%2Fimages%2Fblog%2F2020-03%2FTopic_retention.png" alt="Kafka metrics on AppSignal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this one-hour resolution you can actually see Kafka's logrotate which throws away these once every while. You can notice this happening with every sudden drop in the line. &lt;/p&gt;

&lt;p&gt;We can then set up triggers when the &lt;code&gt;topic_retention_short&lt;/code&gt; is above &lt;code&gt;0 ms&lt;/code&gt;, that way we will be alerted when the timestamp indicates that the retention is shorter than the specified time. This will help us make informed decisions on what topics to give more disk space or what impact the message flow has on retention times. &lt;/p&gt;

&lt;h2&gt;
  
  
  Roundup
&lt;/h2&gt;

&lt;p&gt;This concludes our little dive into using a standalone StatsD agent to get data monitored and how we dogfood AppSignal.&lt;/p&gt;

&lt;p&gt;This is not the only way to get custom metrics into AppSignal though, from your Ruby / Elixir / Node.js app you can also add any metric you want to. If you want to set this up yourself, read up on it in the documentation about &lt;a href="https://docs.appsignal.com/" rel="noopener noreferrer"&gt;custom metrics&lt;/a&gt; or the documentation about the &lt;a href="https://docs.appsignal.com/standalone-agent/installation.html" rel="noopener noreferrer"&gt;standalone agent&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;PS. Big thanks to Robert and Thijs. I typed the blogpost, but your brains wrote it 😉&lt;/p&gt;

</description>
      <category>devops</category>
      <category>webperf</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Performance and N+1 Queries: Explained, Spotted, and Solved</title>
      <dc:creator>Stefan Verkerk</dc:creator>
      <pubDate>Wed, 24 Jun 2020 14:29:05 +0000</pubDate>
      <link>https://dev.to/appsignal/performance-and-n-1-queries-explained-spotted-and-solved-10le</link>
      <guid>https://dev.to/appsignal/performance-and-n-1-queries-explained-spotted-and-solved-10le</guid>
      <description>&lt;p&gt;Today, we’ll dive into N+1 queries⁠—what they are, how to spot them, why they have such an impact, and how to solve them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It Matters
&lt;/h2&gt;

&lt;p&gt;When you run into performance issues in your app that affect user experience, or when things break, you'll probably look at the timeline of the requests in your APM. You might see a large part of the timeline being used by a single, repeated query.&lt;/p&gt;

&lt;p&gt;N+1 queries can be quite impactful but are usually easy to spot. In this article, we’ll go over ways to find, fix and prevent slowdowns caused by N+1 queries.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The N+1 Antipattern In Short&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The N+1 query antipattern happens when a query is executed for every result of a previous query. &lt;br&gt;&lt;br&gt;
The query count is N + 1, with N being the number of queries for every result of the initial query. &lt;br&gt;
If that initial query has one result, N+1 = 2. &lt;br&gt;&lt;br&gt;
If it has 1000 results, N+1 = 1001 queries.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  An N+1 Query Isn't That Hard to Spot (with AppSignal 😉)
&lt;/h2&gt;

&lt;p&gt;We’ve written about N+1 before, but today, we wanted to write a post that is language agnostic because we’ve just released a way to find N+1 queries more easily. So, if a query is slow because of an N+1 query, it will stand out even more.&lt;/p&gt;

&lt;p&gt;We were already tracking N+1 queries in the event timeline, but we've added two improvements that help you find these opportunities for improvement more quickly.&lt;/p&gt;

&lt;p&gt;First, the performance issues overview now includes an &lt;code&gt;N+1&lt;/code&gt; label. This indicates that there are queries that might need optimization. Second, we've added a box with a warning and a short explanation of what N+1 queries are.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OngOdnIZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.appsignal.com/images/blog/2020-06/nplus1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OngOdnIZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.appsignal.com/images/blog/2020-06/nplus1.png" alt="N+1 in AppSignal" title="N+1 in AppSignal" width="880" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s go back and look at what causes an N+1 query.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Lazy Loading, and Which ORMs Default to It?
&lt;/h2&gt;

&lt;p&gt;Loading relationships from a database can roughly be split into two approaches. First, lazy loading will only load data from your database when needed. Then, there’s eager loading, which loads all data right away. We’ll show you what that means.&lt;/p&gt;

&lt;p&gt;If you use an ORM, this is where you set lazy or eager loading. Looking at different languages we are familiar with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Elixir, things are set explicitly with Ecto (not an ORM really).&lt;/li&gt;
&lt;li&gt;In Node, TypeORM, the most popular ORM, doesn't do lazy loading by default.&lt;/li&gt;
&lt;li&gt;In Ruby, ActiveRecord by default uses lazy loading. This makes sense because, in Ruby on Rails, things are often implicit: convention over configuration. But it also means the N+1 anti-pattern is something you can easily stumble into when using ActiveRecord.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How It All Starts: When Fast, Easy and Lazy Are Nice
&lt;/h2&gt;

&lt;p&gt;Let's dive in with a specific example, where we can see the pattern emerge and understand its impact. Because we like Stroopwafels, the example will be an imaginary Cookie webshop. In this imaginary webshop example, each &lt;code&gt;cookie&lt;/code&gt; can have any number of &lt;code&gt;topping&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;We will start with the case where a page shows all cookies, and allows you to navigate to a cookie detail page to see all the available toppings.&lt;/p&gt;

&lt;p&gt;When we lazy load the data on the overview page, we loop over every cookie and only load their toppings later, at the point where we need them. On a detail page, you will load one cookie, and all of the toppings it has. Your ORM will do 2 queries to show these. To keep the explanation language-agnostic, we’ll just show the resulting queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;SELECT&lt;/span&gt; &lt;span class="s2"&gt;"cookies"&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"cookies"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="s2"&gt;"cookies"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="no"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="no"&gt;SELECT&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"cookie_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When a Thing Starts Going Bad
&lt;/h2&gt;

&lt;p&gt;When you want to not only list all cookies, but ALSO show all the toppings for each cookie, AND you lazy load, N+1 rears it’s ugly head. Because we lazy load, a query is executed for every result of a previous query.&lt;/p&gt;

&lt;p&gt;This case returns all 3 cookies from the database and each of their toppings. This leads to 4 queries. Again, we just show the queries to make this applicable across languages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;SELECT&lt;/span&gt; &lt;span class="s2"&gt;"cookies"&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"cookies"&lt;/span&gt;
&lt;span class="no"&gt;SELECT&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"cookie_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="no"&gt;SELECT&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"cookie_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="no"&gt;SELECT&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"cookie_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How Much Is N+1?
&lt;/h2&gt;

&lt;p&gt;We started with rendering a view for 1 cookie and its toppings. All was well, and it led to 2 queries. The second case rendering a view with all cookies and all toppings led to 4 queries.&lt;/p&gt;

&lt;p&gt;Looking at the first query, this is executed by the explicit call to &lt;code&gt;cookie.all&lt;/code&gt; in the controller, which finds all cookies. Queries 2 to 4 are lazily executed while we loop through all the cookies.&lt;/p&gt;

&lt;p&gt;This results in the number of queries being N+1.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;N here is the number of cookies (yum), and the plus one is the first (explicit) query that fetched all the cookies.&lt;/li&gt;
&lt;li&gt;It does one query, plus one, for each of the results in the first query.&lt;/li&gt;
&lt;li&gt;Because we have 3 cookies here, N = 3 and it leads to  N + 1 = 3 + 1 = 4 queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With 3 cookies, this probably won’t lead to any performance issues, but if we had 1000, we can predict it would lead to 1001 queries. Ouch. Perhaps there IS such a thing as too many stroopwafels.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Much Difference Does It Make?
&lt;/h2&gt;

&lt;p&gt;OK, we ate all of the cookies by now. But we timed how much time that took. I mean, how long the queries took 😉. We used a Ruby on Rails with ActiveRecord setup for this example, but the differences are negligible for any language. When we have 3 cookies, eager eating loading was 12% faster than lazy loading. With 10 cookies, the difference was already almost 60%. If we had 1000 cookies, the difference would be close to 80%, 58 ms, against a whopping 290 ms in our example.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Solve It: Eagerness
&lt;/h2&gt;

&lt;p&gt;The way to solve this is to use eager loading. By preloading the toppings, when we show all cookies and their toppings on a page again, the query count drops back to 2, even if the number of cookies increases to 1000. The query count is 2 because the second query depends on the data from the first one to know which toppings to fetch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;SELECT&lt;/span&gt; &lt;span class="s2"&gt;"cookies"&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"cookies"&lt;/span&gt;
&lt;span class="no"&gt;SELECT&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt; &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt; &lt;span class="no"&gt;WHERE&lt;/span&gt; &lt;span class="s2"&gt;"toppings"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"cookie_id"&lt;/span&gt; &lt;span class="no"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Now What?
&lt;/h2&gt;

&lt;p&gt;Depending on your state of mind, grab some cookies. Or &lt;a href="https://www.appsignal.com/tour/performance"&gt;find out more about AppSignal&lt;/a&gt; and setup an account. If you ask for stroopwafels, and we will send you some. If you are already using AppSignal, go and see whether you can solve some N+1 issues.&lt;/p&gt;

</description>
      <category>database</category>
      <category>webdev</category>
      <category>programming</category>
      <category>sql</category>
    </item>
    <item>
      <title>How to Monitor Your Host Metrics Automatically</title>
      <dc:creator>Stefan Verkerk</dc:creator>
      <pubDate>Wed, 04 Mar 2020 15:37:39 +0000</pubDate>
      <link>https://dev.to/appsignal/how-to-monitor-your-host-metrics-automatically-njh</link>
      <guid>https://dev.to/appsignal/how-to-monitor-your-host-metrics-automatically-njh</guid>
      <description>&lt;p&gt;Today, we’ll dive deep into monitoring hosts. The good news is that we’ll point you to some shortcuts on how to set up host monitoring in an easy way. The bad news is that we won't be doing any &lt;a href="https://www.technology.org/2019/03/29/its-not-stupid-if-it-works-why-percussive-maintenance-is-a-legit-repair-method/"&gt;percussive maintenance&lt;/a&gt; on any host.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Getting the Data In
&lt;/h2&gt;

&lt;p&gt;To monitor hosts, you have to set a few layers in place. Doing all this by yourself would be the hard way. You may ask: "How hard could it be?". Well, AppSignal started as a side project in 2012 because a group of "How hard can it be?" people worked on this system for three years before it was in a shape we were somewhat proud of.&lt;/p&gt;

&lt;p&gt;After monitoring thousands of billions of requests, we've learned all kinds of things along the way. So, regardless of whether you choose AppSignal to monitor your app, think thrice before you roll out a solution by yourself.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;These challenges go from emitting the data in a lightweight manner to ingesting masses of data in a way that doesn't influence the hosts you are monitoring. If you think that’s cool, we wrote a bit about how we do it in &lt;a href="https://docs.appsignal.com/appsignal/data-life-cycle.html"&gt;our documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Automated Part
&lt;/h2&gt;

&lt;p&gt;If you monitor your app with AppSignal, &lt;a href="https://docs.appsignal.com/metrics/host.html"&gt;host metrics&lt;/a&gt; are collected by the agent every minute. We try to give as many insights as possible right ‘out-of-the-box’, so you don't need to manually set up anything.&lt;/p&gt;

&lt;p&gt;We love the combination of many things working right away, and also being able to continuously tweak things. So, with this, you &lt;em&gt;can&lt;/em&gt; also turn it off if you want to.&lt;/p&gt;

&lt;p&gt;Out-of-the-box, we collect the following metrics:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU usage&lt;/td&gt;
&lt;td&gt;User, nice, system, idle and iowait in percentages. Read more about CPU metrics in our academy article.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Load average&lt;/td&gt;
&lt;td&gt;1 minute load average on the host.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory usage&lt;/td&gt;
&lt;td&gt;Available, free and used memory. Also includes swap total and swap used.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disk usage&lt;/td&gt;
&lt;td&gt;Percentage of every disk used.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disk IO&lt;/td&gt;
&lt;td&gt;Throughput of data read from and written to every disk.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network traffic&lt;/td&gt;
&lt;td&gt;Throughput of data received and transmitted through every network interface.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 2: Initial Triggers and Setting up Alerts
&lt;/h2&gt;

&lt;p&gt;Now that we have the host metrics available, let's put in some thresholds for when you want to be alerted. The first step would be to set this up with a relatively sensitive or noisy alerting on a day (not a night) where you are available to look into things.&lt;/p&gt;

&lt;p&gt;What a noisy setting is, depends on what you see on average on your hosts, but some sane defaults are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Trigger setting&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;idle over 100%, without warmup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disk I/O&lt;/td&gt;
&lt;td&gt;larger than 10MB per minute, without warmup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disk usage&lt;/td&gt;
&lt;td&gt;over 90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Load average&lt;/td&gt;
&lt;td&gt;over 1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When values go above these defaults, set up an alert via email or Slack (we don’t recommend starting with PagerDuty for these noisy alerts just yet).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4OTq3QOw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/bc266bd8435b693700b28d5ccd444531e53a79e7/7bc1c/images/blog/2020-02/new-host-trigger.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4OTq3QOw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/bc266bd8435b693700b28d5ccd444531e53a79e7/7bc1c/images/blog/2020-02/new-host-trigger.png" alt="New Host Trigger"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Monitoring the Patterns Over Time
&lt;/h2&gt;

&lt;p&gt;Once you have some data coming in, the next step is to monitor the emerging patterns. Simply having all this data available is nice, but in our experience, it is all about the patterns.&lt;/p&gt;

&lt;p&gt;There are some ‘right’s and ‘wrong’s but the key is to monitor, get to know the bandwidth in which your hosts operate in a ‘normal’ setting, and be able to see when things move beyond that bandwidth. In other words: it is not about having one data point, but about observing the line over a longer period of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Ice Cold Drinks
&lt;/h2&gt;

&lt;p&gt;Now that we have metrics coming in and we've set some triggers, we need to wait for some time before the patterns emerge.&lt;/p&gt;

&lt;p&gt;Sit back and relax, alt-tab to another task or get an ice-cold drink; looking at the graphs all day won’t speed up the process. You may want to have the noisy settings running for a week to get a full pattern of weekdays and perhaps lower-traffic weekends.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Monitoring Patterns Between Hosts
&lt;/h2&gt;

&lt;p&gt;The next step, while we're drinking that ice-cold drink, is to compare the metrics over different hosts. Because the other important patterns in monitoring hosts, next to patterns over time, are about how one host behaves in comparison to another host with similar function.&lt;/p&gt;

&lt;p&gt;This is why we show different hosts in one view like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uPet6PAd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/2cbdb5444d1b0d49dfdd0e55c1b0bd2519e2becc/3d722/images/blog/2020-02/hostcompared.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uPet6PAd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/2cbdb5444d1b0d49dfdd0e55c1b0bd2519e2becc/3d722/images/blog/2020-02/hostcompared.png" alt="HostsCompared"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ve experienced that sometimes different hosts can have different performance characteristics, especially in a virtualized environment. For example, if you share the hardware with another customer of your hosting company, a change on their end might trigger issues on your side.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens on the Hosts…
&lt;/h2&gt;

&lt;p&gt;We could also call this ‘when the host issue is the effect, and not the cause’. So far, we've focused on steps to make sure we monitor and set triggers to the overall host-level metrics. But other than interference by other virtual machines, something like a CPU spike is the effect, not the cause of an issue (although it can trigger new problems).&lt;/p&gt;

&lt;p&gt;This is why we built monitoring in an integrated way. We realize we are biased 😉 If you have your monitoring in one integrated way, like AppSignal or a comparable solution, you can also see what is running on a host that is causing those peaks.&lt;/p&gt;

&lt;p&gt;At AppSignal, these metrics are scoped per namespace. By default, we create web and background namespaces for you, but you have complete freedom in how you organize your namespaces.&lt;/p&gt;

&lt;p&gt;By &lt;a href="https://docs.appsignal.com/application/namespaces.html"&gt;setting your own namespaces&lt;/a&gt;, you can also set different levels of triggers. There might be webhooks where you can expect a much higher throughput. In a normal web request, you will want to set different triggers.&lt;/p&gt;

&lt;p&gt;We get really excited about this part, so apologies if we dove in a bit too deep. We’ll cover it in a separate post in a few weeks. Let’s get back to the basics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Less Noise &amp;amp; Repeat
&lt;/h2&gt;

&lt;p&gt;Once we’ve seen patterns emerge in time and between hosts, the next step is to set the alerting to some real levels that are not as noisy as the ones we started with. Once you’ve seen the spread of the mean, and you feel confident, hook up PagerDuty or OpsGenie and set up the real alerting that &lt;em&gt;will&lt;/em&gt; wake people up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: A Good Night’s Sleep
&lt;/h2&gt;

&lt;p&gt;In our Ops team, the vision is ‘a good night’s sleep’. You should aim for that as well: being alerted when needed, and solving things so it doesn’t keep alerting you.&lt;/p&gt;

&lt;p&gt;With all the steps taken, a good setup for monitoring your host will now get you some well-deserved sleep. Good night! (* depending on your timezone 😉)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PS: Another hard part about monitoring is digesting the hundreds of billions of requests that you may emit. We might write a blog post about that another day ;-) It's why we think you should use a dedicated service rather than run it yourself. And if you'd &lt;a href="https://appsignal.com"&gt;try us&lt;/a&gt;, we'd be honored.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>devops</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Monitoring the Erlang VM With AppSignal's Magic Dashboard</title>
      <dc:creator>Stefan Verkerk</dc:creator>
      <pubDate>Wed, 12 Feb 2020 15:53:40 +0000</pubDate>
      <link>https://dev.to/appsignal/monitoring-the-erlang-vm-with-appsignal-s-magic-dashboard-12a2</link>
      <guid>https://dev.to/appsignal/monitoring-the-erlang-vm-with-appsignal-s-magic-dashboard-12a2</guid>
      <description>&lt;p&gt;Today, we will dive into one of the hard parts of using any monitoring - making sense out of all the data that is emitted. We think this is one of the hard parts. And being developers building for developers, we think a lot like you do -- we think. Pun intended.&lt;/p&gt;

&lt;p&gt;Nowadays, we monitor AppSignal with AppSignal (on a separate setup), so we are still dogfooding all the time. We still run into challenges as you do, often before you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Magic Dashboards
&lt;/h2&gt;

&lt;p&gt;We believe one of the harder challenges is finding the right data and making sense of it. Once we discover what works best for a certain setup, we don't just keep the solution to ourselves, we make it into a solution that's available to all of our users.&lt;/p&gt;

&lt;p&gt;We call this solution Magic Dashboards. Based on the architecture that you are running, we add dashboards that make sense for that architecture.&lt;/p&gt;

&lt;p&gt;If you are running a recent version of the AppSignal integration, magic dashboards will show up when you add a new application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O04QtW9z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/dd04ec2fce63d135836cd58b00dfb44580cd3db5/784be/images/blog/2020-01/erlang_splash.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O04QtW9z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/dd04ec2fce63d135836cd58b00dfb44580cd3db5/784be/images/blog/2020-01/erlang_splash.png" alt="Erlang VM Magic Dashboard image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Erlang VM Magic Dashboard
&lt;/h2&gt;

&lt;p&gt;A Magic Dashboard that we made for the Elixir integration is the Erlang VM dashboard. It has graphs metrics on IO, schedulers, processes and memory. This is what it looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iT5Y0s07--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/14fd699b02f933344dbc61781f385cbd54b712b7/5f782/images/blog/2020-01/erlang_bdashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iT5Y0s07--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d33wubrfki0l68.cloudfront.net/14fd699b02f933344dbc61781f385cbd54b712b7/5f782/images/blog/2020-01/erlang_bdashboard.png" alt="Erlang VM Magic Dashboard image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  IO
&lt;/h3&gt;

&lt;p&gt;This shows the amount of input and output you have cumulatively, expressed in kb.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schedulers
&lt;/h3&gt;

&lt;p&gt;This graph shows the total number of available schedulers and the number of online schedulers. Erlang's schedulers schedule CPU time between your processes. The number of schedulers defaults to the number of CPU cores on the machine.&lt;/p&gt;

&lt;p&gt;If you want to know more about schedulers, here’s &lt;a href="https://hamidreza-s.github.io/erlang/scheduling/real-time/preemptive/migration/2016/02/09/erlang-scheduler-details.html"&gt;a good article on Hamidreza Soleimani’s Blog on why the details of schedulers are important&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Processes
&lt;/h3&gt;

&lt;p&gt;The number of processes and the limit are plotted here. The limit is the maximum number of simultaneously existing processes at the local node. If you reach the limit, the process will raise an exception. But the default Erlang limit is 262144, which should be high enough for almost all applications. &lt;/p&gt;

&lt;h3&gt;
  
  
  Memory
&lt;/h3&gt;

&lt;p&gt;This shows the total amount of memory that is used as well as its usage, split into processes, system, binary, ets and code.&lt;/p&gt;

&lt;p&gt;The level that is considered normal, obviously depends on your situation. But when this suddenly goes up, it might be an indicator that something is wrong.&lt;/p&gt;

&lt;p&gt;For anything that's monitored on a dashboard, you can set up triggers (which we call ‘anomaly detection’), that will message you via email/slack/PagerDuty when it goes over a normal value for your case, for a certain period. Our &lt;a href="https://docs.appsignal.com/application/anomaly-detection"&gt;Documentation on Anomaly Detection&lt;/a&gt; describes how to set that up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dashboards for Host Metrics
&lt;/h2&gt;

&lt;p&gt;Apart from the things that you are running in your Elixir setup, when you have AppSignal running, we also immediately add &lt;a href="https://docs.appsignal.com/metrics/host.html"&gt;dashboards and metrics for your hosts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example, check the ‘Host usage’ link in the Inspect menu item to see throughput, response time and queue time for any Namespace on that Host. And check the 'Host Metrics' to see CPU, Disk usage, Load average and more for each of the Hosts.&lt;/p&gt;

&lt;p&gt;We've seen that the integrated approach of monitoring really helps in narrowing down what causes issues. So for each of these metrics, you can click on a peak, check 'what happened here' in the graph legend and see the entire overview of errors, performance issues and host metrics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edit or Extend as You Want
&lt;/h2&gt;

&lt;p&gt;We always mix having loads of insight out-of-the-box with being able to tweak things exactly as you want. So if you want to have any of these dashboards set up differently, you can edit the dashboard configuration YAML and make it do exactly what you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  What More Do You Want Us to Add?
&lt;/h2&gt;

&lt;p&gt;We are always curious to hear what else you’d like us to set up Magic dashboards for. So if you have something in your Elixir setup that you want us to help visualize in a graph, drop us a line at &lt;a href="mailto:support@appsignal.com"&gt;support@appsignal.com&lt;/a&gt;. We'll then let everyone else have it magically.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PS: Another hard part about monitoring is digesting the hundreds of billions of requests that you may emit. We might write a blog post about that another day ;-) It's why we think you should use a dedicated service rather than run it yourself. And if you'd &lt;a href="https://appsignal.com/elixir/"&gt;try us&lt;/a&gt; we'd be honored.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>erlang</category>
      <category>elixir</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
