<?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: Mirco</title>
    <description>The latest articles on DEV Community by Mirco (@ablx).</description>
    <link>https://dev.to/ablx</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%2F420556%2F179b6df0-3291-4747-b930-f460e34f3403.jpg</url>
      <title>DEV Community: Mirco</title>
      <link>https://dev.to/ablx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ablx"/>
    <language>en</language>
    <item>
      <title>Valet Key Design Pattern in 30 Seconds</title>
      <dc:creator>Mirco</dc:creator>
      <pubDate>Thu, 18 Nov 2021 14:12:02 +0000</pubDate>
      <link>https://dev.to/ablx/valet-key-design-pattern-in-30-seconds-2jje</link>
      <guid>https://dev.to/ablx/valet-key-design-pattern-in-30-seconds-2jje</guid>
      <description>&lt;h4&gt;
  
  
  Do not waste your applications resources on big uploads.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a9rI62Gd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AVCTMbAPumFQnIiEHfRwa0g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a9rI62Gd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AVCTMbAPumFQnIiEHfRwa0g.jpeg" alt="" width="880" height="587"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Old Money on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Routing large up- and downloads through your application absorbs valuable resources like bandwidth and CPU time. After the service authenticated the upload request, it uploads data to a storage system like Amazon S3 or Google Cloud Storage. Authentication is fast. &lt;strong&gt;The service wastes most of its time while it waits for the file to be saved by the storage system.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.java67.com/2018/05/top-20-system-design-interview-questions-answers-programming.html"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GfMKDzim--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/418/1%2AYgXElATpbbp92oNdIYUseQ.png" alt="" width="418" height="446"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The service wastes most of its time while it waits for the file to be saved by the storage system.Uploading via the service locks resources.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why waste so much valuable time?&lt;/strong&gt; The Valet Key Pattern creates a remedy for this problem.&lt;/p&gt;

&lt;p&gt;Clients do not call your service anymore to upload things. They only call your service to get a specialized key with limited validity. Then, they use this key to upload their data directly to the storage system. The storage system must be able to verify that the key is valid. In this way, your application will not have to wait for the upload.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.java67.com/2019/09/top-5-courses-to-learn-system-design.html"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V7u3Npf1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/384/1%2AprEaN8gejARdz0xLxPOa9Q.png" alt="" width="384" height="446"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Use the Valet Key Pattern to reduce load on your system.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the downside, you lose some control over your storage system. You have to ensure that the key has the lowest possible scope. Limit the maximum upload size, the reusability of the key and its validity. If possible, make the client notify you after the upload is finished, so that you can invalidate the key right away.&lt;/p&gt;

&lt;p&gt;Do not forget to validate and sanitize all uploaded data before using it. You can achieve this with an own service which regularly scans all new uploads.&lt;/p&gt;

&lt;p&gt;Use this pattern only if clients must upload extensive files often. It will save you resources. And this will save you money.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Want to learn more about Cloud Design Patterns? Check out these articles:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/javarevisited/fabulous-claim-check-design-pattern-explained-in-just-one-minute-5bac14df0edc"&gt;Fabulous Claim-Check Design Pattern explained in just one minute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/javarevisited/circuit-breaker-pattern-in-30-seconds-79166ddedaed"&gt;Circuit Breaker Pattern in 30 seconds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/javarevisited/4-really-helpful-and-important-cloud-design-patterns-explained-in-short-time-4b087bebb97b"&gt;4+1 helpful and important Cloud Design Patterns explained in short time&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;If this article was helpful for your, please consider to buy me a coffee :-)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ko-fi.com/Y8Y1EKYJI"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKanlt08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi" width="223" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cloudcomputing</category>
      <category>technology</category>
      <category>googlecloudplatform</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Circuit Breaker Pattern in 30 seconds</title>
      <dc:creator>Mirco</dc:creator>
      <pubDate>Thu, 11 Nov 2021 13:47:00 +0000</pubDate>
      <link>https://dev.to/ablx/circuit-breaker-pattern-in-30-seconds-dp2</link>
      <guid>https://dev.to/ablx/circuit-breaker-pattern-in-30-seconds-dp2</guid>
      <description>&lt;p&gt;In a microservice architecture, remote services may be unavailable for a long time. Retrying a request won’t help in this case.&lt;/p&gt;

&lt;p&gt;The Circuit Breaker pattern offers a solution to this problem.&lt;/p&gt;

&lt;p&gt;The CB has three states: &lt;em&gt;closed&lt;/em&gt;, &lt;em&gt;half-open&lt;/em&gt;, and &lt;em&gt;open&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It starts in &lt;em&gt;closed&lt;/em&gt; state. Your service executes all calls to the remote service.&lt;/li&gt;
&lt;li&gt;CB switches to &lt;em&gt;open&lt;/em&gt; if many requests fail. Your service starts a timer and does not execute any calls to the service. It returns a default answer or throws an exception instead.&lt;/li&gt;
&lt;li&gt;CB switches to &lt;em&gt;half-open&lt;/em&gt; when the timer is up. Your service executes a fraction of the calls. If all pass, it switches to “closed”. If one fails, it switches to “open” again and restarts the timer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To summarize, the Circuit Breaker prevents the execution of calls which are doomed to fail. Look &lt;a href="https://docs.microsoft.com/en-us/azure/architecture/patterns"&gt;here&lt;/a&gt;/circuit-breaker) for more information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://verbosemode.dev/4-really-helpful-and-important-cloud-design-patterns-explained-in-short-time-4b087bebb97b"&gt;Learn four more patterns here!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/Y8Y1EKYJI"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKanlt08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi" width="223" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>architecture</category>
    </item>
    <item>
      <title>React faster: Forward Prometheus Alerts to Teams</title>
      <dc:creator>Mirco</dc:creator>
      <pubDate>Fri, 05 Nov 2021 08:54:00 +0000</pubDate>
      <link>https://dev.to/ablx/react-faster-forward-prometheus-alerts-to-teams-4k1k</link>
      <guid>https://dev.to/ablx/react-faster-forward-prometheus-alerts-to-teams-4k1k</guid>
      <description>&lt;p&gt;Many companies use Microsoft Teams. Receiving alerts in Teams allows you to react faster. It makes working on an incident visible, as you can answer the message. Let's add it to our monitoring stack!&lt;/p&gt;

&lt;p&gt;Head over to &lt;a href="https://github.com/ablx/monitoring_stack" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; to get the full code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teams configuration
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://verbosemode.dev/react-faster-alertmanager-to-teams-fa888bcd7c01" rel="noopener noreferrer"&gt;Alertmanager&lt;/a&gt; does not support Teams out of the box. You must use webhooks to achieve this. The webhook is used by prom2teams to write messages.&lt;/p&gt;

&lt;p&gt;Add a channel to the team which should receive the notifications. Click on the three dots beside the team name and choose  &lt;code&gt;Add channel&lt;/code&gt;.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzk6s03on1vb3fcur8u5.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzk6s03on1vb3fcur8u5.png" alt="Add a channel in Teams"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To add the webhook, click on the dots beside the channel and click on &lt;code&gt;Connectors&lt;/code&gt;.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpe7awkfw3m498l9y5onc.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpe7awkfw3m498l9y5onc.png" alt="Add connector in Teams"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configure an &lt;code&gt;Incoming Webhook&lt;/code&gt;. Teams shows the webhook URL once you click &lt;code&gt;Create&lt;/code&gt;. Copy this URL in the next step.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flaxa51ru0bhronz8y4q8.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flaxa51ru0bhronz8y4q8.png" alt="Configure Webhook in Teams"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add prom2teams to the stack
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/idealista/prom2teams" rel="noopener noreferrer"&gt;prom2teams&lt;/a&gt; will use the webhook to send  messages to Teams.&lt;/p&gt;

&lt;p&gt;Add prom2teams to your &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

  &lt;span class="na"&gt;prom2teams&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;idealista/prom2teams:2.7.0&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;PROM2TEAMS_CONNECTOR&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;webhook"&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8089:8089&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Update your alerts
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://verbosemode.dev/react-faster-alertmanager-to-teams-fa888bcd7c01" rel="noopener noreferrer"&gt;Alertmanager&lt;/a&gt; uses labels to decide which alert goes to which notification channel. Change the &lt;code&gt;prometheus/alerts.yml&lt;/code&gt; to contain the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;


&lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DemoAlerts&lt;/span&gt;
    &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;InstanceDown&lt;/span&gt; 
        &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;up{job="services"} &amp;lt; 1&lt;/span&gt; 
        &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1m&lt;/span&gt;
        &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# labels and annotations are new&lt;/span&gt;
          &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;low&lt;/span&gt;
        &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Alert&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;severity.'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;InstanceDownCritical&lt;/span&gt;
        &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;up{job="services"} &amp;lt; 1&lt;/span&gt; 
        &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1m&lt;/span&gt; 
        &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;high&lt;/span&gt;
        &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Alert&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;severity.'&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now you have two alerts with different labels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure the Alertmanager
&lt;/h2&gt;

&lt;p&gt;Change the &lt;code&gt;alertmanager/alertmanager.yml&lt;/code&gt; so that the &lt;a href="https://verbosemode.dev/react-faster-alertmanager-to-teams-fa888bcd7c01" rel="noopener noreferrer"&gt;Alertmanager&lt;/a&gt; is aware of prom2teams.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;group_by&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;alertname&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;receiver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mail'&lt;/span&gt; &lt;span class="c1"&gt;# default receiver&lt;/span&gt;
  &lt;span class="na"&gt;repeat_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;24h&lt;/span&gt;
  &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;receiver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;teams'&lt;/span&gt;
      &lt;span class="na"&gt;repeat_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;12h&lt;/span&gt;
      &lt;span class="na"&gt;matchers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;severity="medium"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;receiver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;teams'&lt;/span&gt;
      &lt;span class="na"&gt;repeat_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;4h&lt;/span&gt;
      &lt;span class="na"&gt;matchers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;severity="high"&lt;/span&gt;


&lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mail'&lt;/span&gt;
    &lt;span class="na"&gt;email_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;smarthost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;yourmailhost.com:465'&lt;/span&gt;
        &lt;span class="na"&gt;auth_username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;yourmail@yourmailhost.com'&lt;/span&gt;
        &lt;span class="na"&gt;auth_password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;mail&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;password"&lt;/span&gt;
        &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;yourmail@yourmailhost.com'&lt;/span&gt;
        &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;someonesmail@yourmailhost.com'&lt;/span&gt;
        &lt;span class="na"&gt;require_tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;teams'&lt;/span&gt;
    &lt;span class="na"&gt;webhook_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://prom2teams:8089"&lt;/span&gt;
        &lt;span class="na"&gt;send_resolved&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, the &lt;a href="https://verbosemode.dev/react-faster-alertmanager-to-teams-fa888bcd7c01" rel="noopener noreferrer"&gt;Alertmanager&lt;/a&gt; can publish to two channels. &lt;br&gt;
&lt;code&gt;matchers&lt;/code&gt; tell the Alertmanager which channel to use.&lt;/p&gt;

&lt;p&gt;The Alertmanager sends alerts with &lt;code&gt;medium&lt;/code&gt; severity to Teams. This is repeated every four hours - until you fix it!&lt;/p&gt;

&lt;p&gt;The Alertmanager uses email if no route matcher matches.&lt;/p&gt;

&lt;p&gt;You can use the &lt;a href="https://www.prometheus.io/webtools/alerting/routing-tree-editor/" rel="noopener noreferrer"&gt;routing tree editor&lt;/a&gt; to check if the configuration is what you need. Add labels and values of your alert to see which route they will take.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9n9s2hked22jf34g86rd.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9n9s2hked22jf34g86rd.png" alt="Routing Tree Editor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the result
&lt;/h2&gt;

&lt;p&gt;Start the stack with &lt;code&gt;docker-compose up&lt;/code&gt; and wait until the alerts fire.&lt;/p&gt;

&lt;p&gt;You will get a notification from Teams for the &lt;code&gt;InstanceDownCritical&lt;/code&gt; alert:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9jasyd14pveiu04w9x0.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9jasyd14pveiu04w9x0.png" alt="Alert in Teams"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And an email for the &lt;code&gt;InstanceDown&lt;/code&gt; alert:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwb40tjyehsa5n0pm1ijc.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwb40tjyehsa5n0pm1ijc.png" alt="Mail alert"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which notification channels do you want to see next? Leave me a message!&lt;br&gt;
Head over to &lt;a href="https://github.com/ablx/monitoring_stack" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; to get the full code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If this article was helpful for your, please consider to buy me a coffee :-)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ko-fi.com/Y8Y1EKYJI" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fko-fi.com%2Fimg%2Fgithubbutton_sm.svg" alt="ko-fi"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>monitoring</category>
      <category>sre</category>
      <category>prometheus</category>
    </item>
    <item>
      <title>Monitoring setup with docker-compose - Part 3: Alertmanager</title>
      <dc:creator>Mirco</dc:creator>
      <pubDate>Wed, 27 Oct 2021 11:47:00 +0000</pubDate>
      <link>https://dev.to/ablx/monitoring-setup-with-docker-compose-part-3-alertmanager-35ln</link>
      <guid>https://dev.to/ablx/monitoring-setup-with-docker-compose-part-3-alertmanager-35ln</guid>
      <description>&lt;h2&gt;
  
  
  In short: What is Alertmanager?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://prometheus.io/docs/alerting/latest/alertmanager/" rel="noopener noreferrer"&gt;Alertmanager&lt;/a&gt; sends alerts to various channels like Slack or E-Mail.&lt;br&gt;
Recall from &lt;a href="https://dashdashverbose.medium.com/monitoring-setup-with-docker-compose-part-1-prometheus-3d2c9089ee82" rel="noopener noreferrer"&gt;part one&lt;/a&gt; that Prometheus creates an alert if something violates a rule.&lt;/p&gt;

&lt;p&gt;You can use the Alertmanager to silence and group alerts as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;You can get all source code from &lt;a href="https://github.com/ablx/monitoring_stack" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. Check out the tag &lt;code&gt;part-2-grafana&lt;/code&gt; if you want to follow along.&lt;/p&gt;

&lt;h3&gt;
  
  
  docker-compose.yml
&lt;/h3&gt;

&lt;p&gt;First of all, add the Alertmanager and a volume to &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;


  &lt;span class="na"&gt;alertmanager&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prom/alertmanager:v0.23.0&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9093:9093"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./alertmanager:/config"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;alertmanager-data:/data&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;--config.file=/config/alertmanager.yml --log.level=debug&lt;/span&gt;


&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;alertmanager-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Alertmanager will persist silence configurations to the volume.&lt;/p&gt;

&lt;h3&gt;
  
  
  alertmanager/alertmanager.yml
&lt;/h3&gt;

&lt;p&gt;This configuration contains information about which channels to send to. For simplicity, we use E-Mail. Refer to &lt;a href="https://prometheus.io/docs/alerting/latest/configuration/#configuration-file" rel="noopener noreferrer"&gt;the Alertmanager docs&lt;/a&gt; to learn about other channels.&lt;/p&gt;

&lt;p&gt;Create a folder &lt;code&gt;alertmanager&lt;/code&gt; and add a file &lt;code&gt;alertmanager.yml&lt;/code&gt; to it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;receiver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mail'&lt;/span&gt;
  &lt;span class="na"&gt;repeat_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;4h&lt;/span&gt;
  &lt;span class="na"&gt;group_by&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;alertname&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;


&lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mail'&lt;/span&gt;
    &lt;span class="na"&gt;email_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;smarthost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;smtp.gmail.com:465'&lt;/span&gt;
        &lt;span class="na"&gt;auth_username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;your_mail@gmail.com'&lt;/span&gt;
        &lt;span class="na"&gt;auth_password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
        &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;your_mail@gmail.com'&lt;/span&gt;
        &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;some_mail@gmail.com'&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;route&lt;/code&gt; section configures which alerts will be sent. In our case, we sent all alerts. You could add more routes and filter, for example, on alert tags (see the &lt;a href="https://prometheus.io/docs/alerting/latest/configuration/#example" rel="noopener noreferrer"&gt;example&lt;/a&gt; in the docs.).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;receivers&lt;/code&gt; configures our target channels. Note how &lt;code&gt;route&lt;/code&gt; refers to the receiver &lt;code&gt;mail&lt;/code&gt; on line two.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connect to prometheus
&lt;/h3&gt;

&lt;p&gt;Finally, we need to tell Prometheus about the Alertmanager.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;prometheus/prometheus.yml&lt;/code&gt; and add the following:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="na"&gt;alerting&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
  &lt;span class="na"&gt;alertmanagers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;scheme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;alertmanager:9093'&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Testing&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;docker-compose up&lt;/code&gt;. Open &lt;a href=""&gt;http://localhost:9093&lt;/a&gt; in your browser to see the Alertmanager UI.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1w8e9kneiev3escmfa2.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1w8e9kneiev3escmfa2.png" alt="Alertmanager after start"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a couple of minutes, the test alert fires. You can check this in &lt;a href="http://localhost:9000/alerts" rel="noopener noreferrer"&gt;your Prometheus instance&lt;/a&gt;.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmayhplesq4glmsyjnx6.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmayhplesq4glmsyjnx6.png" alt="Prometheus with active alert"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can see the alert in the &lt;a href="https://dev.toAlertmanager"&gt;http://localhost:9093&lt;/a&gt; as well:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo5fj09wi5uzch714l8ff.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo5fj09wi5uzch714l8ff.png" alt="Alertmanager with alert"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check your inbox for the notification:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kno20xhfq8ox8hrb00v.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kno20xhfq8ox8hrb00v.png" alt="Alert mail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final note
&lt;/h2&gt;

&lt;p&gt;This series shows how to set up a basic Prometheus stack. Keep in mind that this is not production-ready! But it is enough to get your hands dirty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If this article was helpful for your, please consider to buy me a coffee :-)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ko-fi.com/Y8Y1EKYJI" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fko-fi.com%2Fimg%2Fgithubbutton_sm.svg" alt="ko-fi"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>monitoring</category>
      <category>prometheus</category>
    </item>
    <item>
      <title>Local Testing With Spring Data and GCP Datastore</title>
      <dc:creator>Mirco</dc:creator>
      <pubDate>Wed, 27 Oct 2021 08:57:00 +0000</pubDate>
      <link>https://dev.to/ablx/stats-for-all-storieslocal-testing-with-spring-data-and-gcp-datastore-4pc6</link>
      <guid>https://dev.to/ablx/stats-for-all-storieslocal-testing-with-spring-data-and-gcp-datastore-4pc6</guid>
      <description>&lt;p&gt;Developing in the cloud is quite different from traditional development. A recurring challenge is to write tests that work locally or on a CI system without access to the cloud.&lt;/p&gt;

&lt;p&gt;This article presents a way to test services that use Spring Boot and Google’s Datastore.&lt;br&gt;
Prerequisites&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 11 ( which can easily be installed with sdkman.)&lt;/li&gt;
&lt;li&gt;Docker and docker-compose&lt;/li&gt;
&lt;li&gt;Basic knowledge Maven, Spring Boot and Google Cloud Platform.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Before we start
&lt;/h2&gt;

&lt;p&gt;To see that everything runs locally, log out of gcloud and unset the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud auth revoke
gcloud config &lt;span class="nb"&gt;unset &lt;/span&gt;project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete code is available on &lt;a href="https://github.com/ablx/spring-data-datastore_local_testing"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;We start with a Spring Boot project which has all the necessary dependencies to use Datastore. You can find all code on GitHub.&lt;/p&gt;

&lt;p&gt;The project contains a simple entity ( Article) and a spring-data repository with a custom method ( ArticleRepository ).&lt;br&gt;
Let the test fail.&lt;/p&gt;

&lt;p&gt;Checkout the tag 1-let-the-tests-fail if you want to follow this step by step.&lt;/p&gt;

&lt;p&gt;If you run mvn clean install in this state, the test will fail since there is no active project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[...]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.google.cloud.datastore.Datastore]: Factory method ‘datastore’ threw exception; nested exception is java.lang.IllegalArgumentException: A project ID is required for this service but could not be determined from the builder or the environment. Please set a project ID using the builder.
Caused by: java.lang.IllegalArgumentException: A project ID is required for this service but could not be determined from the builder or the environment. Please set a project ID using the builder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is easily fixed by adding a mock project id to the application.properties (See the git tag 2-add-project-id-property) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;spring.cloud.gcp.project-id=test-project&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maven (&lt;code&gt;mvn clean install&lt;/code&gt;) now fails with the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.google.cloud.datastore.DatastoreException: Cloud Datastore API has not been used in project … before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/datastore.googleapis.com/overview?project=… then retry.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spring now tries to connect to Datastore in test-project , which does not exist.&lt;br&gt;
Make the tests green.&lt;/p&gt;

&lt;p&gt;Here comes the Datastore emulator into play. You can install it via gcloud, but for portability, we will use a dockerized version.&lt;/p&gt;

&lt;p&gt;We add the following docker-compose.yml to the root of the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;datastore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;knarz/datastore-emulator&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8081:8432&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;CONSISTENCY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;# If you omit this, the emulator will emulate eventual consistency.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To ensure that Spring uses the emulator, we must add a property to application.properties that points to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring.cloud.gcp.datastore.host=localhost:8081
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(See the git tag 3-datastore-emulator for all code in this step)&lt;/p&gt;

&lt;p&gt;Start the emulator with docker-compose up and run the test again with mvn clean install .&lt;/p&gt;

&lt;p&gt;Now, the tests are green! You created a test with datastore which runs 100% locally!&lt;br&gt;
Make it more comfortable.&lt;/p&gt;

&lt;p&gt;Starting and stopping the container by hand is tedious and error-prone. Luckily, we can configure maven so that this happens automatically.&lt;/p&gt;

&lt;p&gt;First, we add maven-failsafe-plugin to our build section in the pom.xml :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
&amp;lt;plugin&amp;gt;
  &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;maven-failsafe-plugin&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;2.22.2&amp;lt;/version&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main task of the plugin is to run integration tests. You can discuss if our test qualifies as an integration test or not. However, there are no appropriate maven lifecycle phases for unit tests as there are for integration tests (which we’ll need in a second). Feel free to alter this step so that it suits your needs.&lt;/p&gt;

&lt;p&gt;In order for maven-failsafe-plugin to execute our test, we have to rename it from ArticleRepositoryTest to ArticleRepositoryIT .&lt;/p&gt;

&lt;p&gt;Then, we add exec-maven-plugin which will start the emulator before the integration tests and stop them afterward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.codehaus.mojo&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;exec-maven-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;start-datastore-emulator&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;phase&amp;gt;&lt;/span&gt;pre-integration-test&lt;span class="nt"&gt;&amp;lt;/phase&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;exec&lt;span class="nt"&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;executable&amp;gt;&lt;/span&gt;docker-compose&lt;span class="nt"&gt;&amp;lt;/executable&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;arguments&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;argument&amp;gt;&lt;/span&gt;up&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;argument&amp;gt;&lt;/span&gt;-d&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/arguments&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;stop-datastore-emulator&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;phase&amp;gt;&lt;/span&gt;post-integration-test&lt;span class="nt"&gt;&amp;lt;/phase&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;exec&lt;span class="nt"&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;executable&amp;gt;&lt;/span&gt;docker-compose&lt;span class="nt"&gt;&amp;lt;/executable&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;arguments&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;argument&amp;gt;&lt;/span&gt;down&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;argument&amp;gt;&lt;/span&gt;-v&lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/arguments&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to stop the docker container now with docker-compose down . Then, run &lt;code&gt;mvn clean install&lt;/code&gt; to see that maven starts the emulator, runs the test and stops the emulator afterward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO] Scanning for projects…
[INFO] 
[INFO] — — — — — — — &amp;lt; com.example:data-datastore-local-testing &amp;gt; — — — — — — — 
[INFO] Building data-datastore-local-testing 0.0.1-SNAPSHOT...[INFO] 
[INFO] — — exec-maven-plugin:3.0.0:exec (start-datastore-emulator) @ data-datastore-local-testing — -
Creating network “data-datastore-local-testing_default” with driver “bridge”
Creating data-datastore-local-testing_datastore_1 … done
[INFO] 
[INFO] — — maven-failsafe-plugin:2.22.2:integration-test (default) @ data-datastore-local-testing — -
[INFO] 
[INFO] — — — — — — — — — — — — — — — — — — — — — — — — — — — -
[INFO] T E S T S
[INFO] — — — — — — — — — — — — — — — — — — — — — — — — — — — -
[INFO] Running com.example.localtesting.repository.ArticleRepositoryIT...[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.849 s — in com.example.localtesting.repository.ArticleRepositoryIT
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] 
[INFO] — — exec-maven-plugin:3.0.0:exec (stop-datastore-emulator) @ data-datastore-local-testing — -
Stopping data-datastore-local-testing_datastore_1 … done
Removing data-datastore-local-testing_datastore_1 … done
Removing network data-datastore-local-testing_default...[INFO] — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 
[INFO] BUILD SUCCESS
[INFO] — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 
[INFO] Total time: 18.264 s
[INFO] Finished at: 2021–10–19T16:10:59+02:00
[INFO] — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done! Thanks for reading this article. Head over to &lt;a href="https://github.com/ablx/spring-data-datastore_local_testing"&gt;GitHub&lt;/a&gt; to get the complete code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If this article was helpful for your, please consider to buy me a coffee :-)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ko-fi.com/Y8Y1EKYJI"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKanlt08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi" width="223" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>docker</category>
      <category>java</category>
      <category>testing</category>
    </item>
    <item>
      <title>Monitoring setup with docker-compose - Part 2: Grafana</title>
      <dc:creator>Mirco</dc:creator>
      <pubDate>Fri, 21 May 2021 11:03:00 +0000</pubDate>
      <link>https://dev.to/ablx/monitoring-setup-with-docker-compose-part-2-grafana-385b</link>
      <guid>https://dev.to/ablx/monitoring-setup-with-docker-compose-part-2-grafana-385b</guid>
      <description>&lt;p&gt;I assume that you have Prometheus running as described in &lt;a href="https://dev.to/ablx/minimal-prometheus-setup-with-docker-compose-56mp"&gt;part 1 of the series&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  In short: what is Grafana?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://grafana.com/" rel="noopener noreferrer"&gt;Grafana&lt;/a&gt; is a tool to create rich dashboards from your metrics.&lt;br&gt;
Grafana can ingest from many different data sources, including Prometheus.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Grafana can work without any configuration files. However, we want to configure Prometheus as a data source, so we create &lt;code&gt;grafana/provisioning/datasources/prometheus_ds.yml&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  grafana/provisioning/datasources/prometheus_ds.yml
&lt;/h3&gt;

&lt;p&gt;This configuration file will tell Grafana about Prometheus. You could omit this and add the configuration via the Grafana UI.&lt;/p&gt;

&lt;p&gt;Add the following to &lt;code&gt;grafana/provisioning/datasources/prometheus_ds.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;datasources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prometheus&lt;/span&gt;
  &lt;span class="na"&gt;access&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;proxy&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prometheus&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://prometheus:9090&lt;/span&gt;
  &lt;span class="na"&gt;isDefault&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  docker-compose.yml
&lt;/h3&gt;

&lt;p&gt;Next, add the following to &lt;code&gt;docker-compose.yml&lt;/code&gt; to add Grafana:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;grafana&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grafana/grafana:7.5.7&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;3000:3000&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;grafana-data:/var/lib/grafana&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first volume points to our data source configuration. The second volume is used to save dashboards etc. We need to add the second volume to the &lt;code&gt;volumes&lt;/code&gt; section in &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;prometheus-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;grafana-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Start
&lt;/h2&gt;

&lt;p&gt;Start Prometheus and Grafana:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;&lt;code&gt;http://localhost:3000&lt;/code&gt;&lt;/a&gt; in your browser. Use user &lt;strong&gt;admin&lt;/strong&gt; with password &lt;strong&gt;admin&lt;/strong&gt; for the first login.&lt;/p&gt;

&lt;p&gt;You should see the Grafana Landing Page after login:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2h3ta26f9jkell4a34p6.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2h3ta26f9jkell4a34p6.png" alt="Grafana Landing Page"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Add the first dashboard
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="http://localhost:3000/dashboard/new" rel="noopener noreferrer"&gt;&lt;code&gt;http://localhost:3000/dashboard/new&lt;/code&gt;&lt;/a&gt; to add a new dashboard (or use the plus sign in the navigation bar). &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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nk2s36ptkjwpbadhka3.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nk2s36ptkjwpbadhka3.png" alt="Add an empty panel"&gt;&lt;/a&gt;&lt;br&gt;
Click on &lt;code&gt;Add an empty panel&lt;/code&gt;.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fvn9sqcbvbq3ub94oxj.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fvn9sqcbvbq3ub94oxj.png" alt="Empty panel before"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the dropdown which says &lt;code&gt;-- Grafana --&lt;/code&gt; select &lt;code&gt;Prometheus&lt;/code&gt;. You can select Prometheus here because we added the configuration earlier. &lt;/p&gt;

&lt;p&gt;Now we need Grafana to tell what to graph. Add the following PromQL statement to the input field &lt;code&gt;metric&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;increase(prometheus_http_requests_total[1m])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will show you how often Prometheus endpoints were called. To learn more about PromQL, see the &lt;a href="https://prometheus.io/docs/prometheus/latest/querying/basics/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwu3po1t2ci5yio47zu9.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwu3po1t2ci5yio47zu9.png" alt="New panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Apply&lt;/code&gt; to save and go back to the dashboard. Finally, click on the dashboard save button in the upper right corner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your final dashboard
&lt;/h2&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flonbdfiw5qe1qvu8uetw.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flonbdfiw5qe1qvu8uetw.png" alt="Final dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! Next time I will show you how to add &lt;a href="https://prometheus.io/docs/alerting/latest/alertmanager/" rel="noopener noreferrer"&gt;AlertManager&lt;/a&gt; to the stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ablx/dev.to_monitoring_stack/tree/part-2-grafana"&gt;See the full source code on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If this article was helpful for your, please consider to buy me a coffee :-)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ko-fi.com/Y8Y1EKYJI" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fko-fi.com%2Fimg%2Fgithubbutton_sm.svg" alt="ko-fi"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>monitoring</category>
      <category>devops</category>
      <category>grafana</category>
      <category>docker</category>
    </item>
    <item>
      <title>Monitoring setup with docker-compose - Part 1: Prometheus</title>
      <dc:creator>Mirco</dc:creator>
      <pubDate>Fri, 02 Oct 2020 14:11:00 +0000</pubDate>
      <link>https://dev.to/ablx/minimal-prometheus-setup-with-docker-compose-56mp</link>
      <guid>https://dev.to/ablx/minimal-prometheus-setup-with-docker-compose-56mp</guid>
      <description>&lt;p&gt;In this post, you'll learn how to set up Prometheus in a Docker container.&lt;/p&gt;

&lt;h2&gt;
  
  
  In short: what is Prometheus?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://prometheus.io" rel="noopener noreferrer"&gt;Prometheus&lt;/a&gt; is an open-source monitoring application. It scrapes HTTP endpoints to collect metrics exposed in a simple text format.&lt;/p&gt;

&lt;p&gt;For example, your web app might expose a metric like&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

http_server_requests_seconds_count{exception="None", method="GET",outcome="SUCCESS",status="200",uri="/actuator/health"} 435


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;which means that the endpoint &lt;code&gt;/actuator/health&lt;/code&gt; was successfully queried 435 times via a GET request.&lt;/p&gt;

&lt;p&gt;Prometheus can also create alerts if a metric exceeds a threshold, e.g. if your endpoint returned more than one-hundred times the status code 500 in the last 5 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;To set up Prometheus, we create three files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prometheus/prometheus.yml - the actual Prometheus configuration&lt;/li&gt;
&lt;li&gt;prometheus/alert.yml - alerts you want Prometheus to check&lt;/li&gt;
&lt;li&gt;docker-compose.yml&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  prometheus/prometheus.yml
&lt;/h3&gt;

&lt;p&gt;Add the following to &lt;code&gt;prometheus/prometheus.yml&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scrape_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
  &lt;span class="na"&gt;scrape_timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;

&lt;span class="na"&gt;rule_files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;alert.yml&lt;/span&gt;

&lt;span class="na"&gt;scrape_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;services&lt;/span&gt;
    &lt;span class="na"&gt;metrics_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/metrics&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prometheus:9090'&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;idonotexists:564'&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;scrape_configs&lt;/code&gt; tell Prometheus where your applications are. Here we use &lt;code&gt;static_configs&lt;/code&gt; hard-code some endpoints.&lt;br&gt;
The first one is Prometheus (this is the service name in the &lt;code&gt;docker-compose.yml&lt;/code&gt;) itself, the second one is for demonstration purposes. It is an endpoint that is always down.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rule_files&lt;/code&gt; tells Prometheus where to search for the alert rules. We come to this in a moment.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;scrape_interval&lt;/code&gt; defines how often to check for new metric values.&lt;/p&gt;

&lt;p&gt;If a scrape takes longer than &lt;code&gt;scrape_timeout&lt;/code&gt; (e.g. slow network), Prometheus will cancel the scrape.&lt;/p&gt;

&lt;h3&gt;
  
  
  prometheus/alert.yml
&lt;/h3&gt;

&lt;p&gt;This file contains rules which Prometheus evaluates periodically. Insert this into the file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DemoAlerts&lt;/span&gt;
    &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;InstanceDown&lt;/span&gt; 
        &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;up{job="services"} &amp;lt; 1&lt;/span&gt; 
        &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5m&lt;/span&gt; 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;up&lt;/code&gt; is a built-in metric from Prometheus. It returns zero if the services were not reachable in the last scrape.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{job="services"}&lt;/code&gt; filters the results of &lt;code&gt;up&lt;/code&gt; to contain only metrics with the tag &lt;code&gt;service&lt;/code&gt;. This tag is added to our metrics because we defined this as the job name in &lt;code&gt;prometheus.yml&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  docker-compose.yml
&lt;/h3&gt;

&lt;p&gt;Finally, we want to launch Prometheus. Put this into your &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;prometheus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prom/prometheus:v2.21.0&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;9000:9090&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./prometheus:/etc/prometheus&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;prometheus-data:/prometheus&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;--web.enable-lifecycle  --config.file=/etc/prometheus/prometheus.yml&lt;/span&gt;


&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;prometheus-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The volume &lt;code&gt;./prometheus:/etc/prometheus&lt;/code&gt; mounts our &lt;code&gt;prometheus&lt;/code&gt; folder in the right place for the image to pick up our configuration.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;prometheus-data:/prometheus&lt;/code&gt; is used to store the scraped data so that they are available after a restart.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;command: --web.enable-lifecycle  --config.file=/etc/prometheus/prometheus.yml&lt;/code&gt; is optional. If you use &lt;code&gt;--web.enable-lifecycle&lt;/code&gt; you can reload configuration files (e.g. rules) without restarting Prometheus:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

curl -X POST http://localhost:9000/-/reload


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you change the command, you override the default of the image and must include &lt;code&gt;--config.file=/etc/prometheus/prometheus.yml&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Prometheus.
&lt;/h2&gt;

&lt;p&gt;Finally, start Prometheus with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and open &lt;code&gt;http://localhost:9000&lt;/code&gt; in your browser. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fml5b31r5tzn891lpussv.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fml5b31r5tzn891lpussv.png" alt="Prometheus UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll see Prometheus UI where you can enter some ad-hoc queries on your metrics, like &lt;code&gt;up&lt;/code&gt;:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0q1jvg22qcqlm2uo8l7i.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0q1jvg22qcqlm2uo8l7i.png" alt="UP Query"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As expected, this tells you that your Prometheus is up, and the other service is not.&lt;/p&gt;

&lt;p&gt;If you go to  &lt;code&gt;Alerts&lt;/code&gt; you'll see that our alert is pending (or already firing):&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmbo0wyddzec8l9gmi2e3.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmbo0wyddzec8l9gmi2e3.png" alt="Alert"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ablx/dev.to_monitoring_stack/tree/part-1-prometheus"&gt;See the full source code on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If this article was helpful for your, please consider to buy me a coffee :-)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ko-fi.com/Y8Y1EKYJI" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fko-fi.com%2Fimg%2Fgithubbutton_sm.svg" alt="ko-fi"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>prometheus</category>
      <category>monitoring</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
