<?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: Ladies In DevOps</title>
    <description>The latest articles on DEV Community by Ladies In DevOps (@ladiesindevops).</description>
    <link>https://dev.to/ladiesindevops</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.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F4096%2F1ad7317e-90fc-41ca-a35f-c302d1729373.jpeg</url>
      <title>DEV Community: Ladies In DevOps</title>
      <link>https://dev.to/ladiesindevops</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ladiesindevops"/>
    <language>en</language>
    <item>
      <title>Load Balancing</title>
      <dc:creator>Nancy Chauhan</dc:creator>
      <pubDate>Tue, 28 Sep 2021 05:58:15 +0000</pubDate>
      <link>https://dev.to/ladiesindevops/load-balancing-461l</link>
      <guid>https://dev.to/ladiesindevops/load-balancing-461l</guid>
      <description>&lt;p&gt;We encounter load balancers every day. Even when you are reading this article, your requests flow through multiple load balancers, before this content reaches your browser.&lt;/p&gt;

&lt;p&gt;Load balancing is one of the most important and basic concepts we encounter every single day. It is the process of distributing incoming requests across multiple servers/processes/machines at the backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we need load balancing?
&lt;/h2&gt;

&lt;p&gt;Usually, when we make an application, clients will route their request to one of the backend servers, but soon as traffic grows, that server will reach its limits. To overcome this, we can spin up another server to share the traffic. But how to let the clients know to connect to the new machine?&lt;br&gt;
Load balancing is the technique used for discovery and decision-making for this routing. There are two ways of achieving this — server-side load balancing or client-side load balancing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ds-PEW5c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/4800/1%2AYxgXygvKUmCpYjKfXEeCzw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ds-PEW5c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/4800/1%2AYxgXygvKUmCpYjKfXEeCzw.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;br&gt;Single application server gets overloaded with request
  &lt;p&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Server-side Load Balancing:
&lt;/h1&gt;

&lt;p&gt;There is a middle layer, a load balancer that forwards the incoming requests to different servers to remove that complexity. All backend servers get registered with a load balancer which then routes to one of the server instances using various algorithms. AWS ELB, Nginx, Envoy are some examples of server-side load balancers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rxAx41Pt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AM013EIjXPW81qIWWKbwU_w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rxAx41Pt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AM013EIjXPW81qIWWKbwU_w.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;br&gt;Server-side load balancing
  &lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No need for client-side changes.&lt;/li&gt;
&lt;li&gt;Easy to make changes to load balancing algorithms and backend servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Client-Side Load Balancing:
&lt;/h1&gt;

&lt;p&gt;In client-side load balancing, the client handles the load balancing. Let’s take an abstract look at how this can be achieved. To perform load balancing on the client-side -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client should be aware of all available web servers&lt;/li&gt;
&lt;li&gt;A library on the client-side to implement a load balancing algorithm&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The client routes the requests to one of the servers using client-side load balancing libraries like Ribbon. Client-side load balancing is also used for service discovery.&lt;/p&gt;

&lt;p&gt;Suppose Service A (client-side) wants to access Service B (server-side). Service B has three instances and register all at the discovery server (X). Service A has enabled the Ribbon client which allows doing the client-side load balancing. It fetches the available Service B instances from the discovery server and redirects the traffic from the client-side and constantly listens for any changes.&lt;/p&gt;

&lt;p&gt;Here I have implemented client-side load balancing using consul service discovery: &lt;a href="https://github.com/Nancy-Chauhan/consul-service-discovery"&gt;https://github.com/Nancy-Chauhan/consul-service-discovery&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZQZpHQ6k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2ACtMtKBTIpfiKTNdRHD-ccQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZQZpHQ6k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2ACtMtKBTIpfiKTNdRHD-ccQ.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;br&gt;Server-side load balancing
  &lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No need for additional infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Benefits of Loadbalancing
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yBZvsiGh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AVtCPP8DOJX7XUhwr4Gp7jg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yBZvsiGh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AVtCPP8DOJX7XUhwr4Gp7jg.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;br&gt;Reference: &lt;a href="https://www.nginx.com/resources/glossary/load-balancing/"&gt;https://www.nginx.com/resources/glossary/load-balancing/&lt;/a&gt;
  &lt;p&gt;&lt;/p&gt;

&lt;p&gt;Load balancers are the foundation of modern cloud-native applications. The concept of load balancing and the ability to be dynamically configured has created innovations such as service mesh.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Branch Protection in GitHub</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Sat, 12 Jun 2021 08:53:18 +0000</pubDate>
      <link>https://dev.to/ladiesindevops/branch-protection-in-github-5fn9</link>
      <guid>https://dev.to/ladiesindevops/branch-protection-in-github-5fn9</guid>
      <description>&lt;p&gt;Ever been in a position where you wish you could prevent your teammates from merging unapproved code from a development branch to the main branch?&lt;/p&gt;

&lt;p&gt;Do you want to prevent merging code which you are not sure of its build status to your main branch?&lt;/p&gt;

&lt;p&gt;Recently, I found myself in this situation and I plan to share a concept which helped me out - 'Branch Protection in GitHub'.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Branch Protection?
&lt;/h3&gt;

&lt;p&gt;Branch protection is the act of setting rules to prevent certain actions from occurring on your branch(es) without your approval.&lt;/p&gt;

&lt;p&gt;This article focuses on, preventing branches (development etc) from being merged to the main branch; such that before any merge can occur, a pull request would require a selected reviewer to review the request and then merge the commit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;It is expected that you have prior knowledge of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Github&lt;/li&gt;
&lt;li&gt;  CI/CD tools (in this article, Travis CI)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out this guides for &lt;a href="https://youtu.be/8JJ101D3knE" rel="noopener noreferrer"&gt;an introduction to Github&lt;/a&gt; and &lt;a href="https://docs.travis-ci.com/user/tutorial" rel="noopener noreferrer"&gt;creating a simple .travis.yml file&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up branch protection rules
&lt;/h3&gt;

&lt;p&gt;We take the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Click on the

&lt;code&gt;Settings&lt;/code&gt;

option in your repository and then

&lt;code&gt;Branches&lt;/code&gt;

(located on the left hand side of the page)
-   Click on

&lt;code&gt;Add Rule&lt;/code&gt;

to create the rule(s) for your branch of choice&lt;/li&gt;
&lt;/ul&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%2Fuser-images.githubusercontent.com%2F49791498%2F121063732-9ad07b00-c7be-11eb-8832-609d2836485e.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%2Fuser-images.githubusercontent.com%2F49791498%2F121063732-9ad07b00-c7be-11eb-8832-609d2836485e.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Next, under

&lt;code&gt;Branch name pattern&lt;/code&gt;

type in the name of the branch you want to protect&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For this article, we choose the following rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'Require pull request reviews before merging': we limit the number of required reviews to 1 (you can choose to increase the required reviews).&lt;/li&gt;
&lt;li&gt;Then, we select

&lt;code&gt;Include administrators&lt;/code&gt;

, to ensure that as owners of the branch, our pull requests will have to be reviewed before a merge can occur (I mean, nobody is above mistakes 🥴)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Finally, we click on the 'Save changes' button to save our settings.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&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%2Fuser-images.githubusercontent.com%2F49791498%2F121062137-a3c04d00-c7bc-11eb-8da9-84605d19e07b.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%2Fuser-images.githubusercontent.com%2F49791498%2F121062137-a3c04d00-c7bc-11eb-8da9-84605d19e07b.png" alt="image"&gt;&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%2Fuser-images.githubusercontent.com%2F49791498%2F121062224-baff3a80-c7bc-11eb-9d9a-3090708eac69.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%2Fuser-images.githubusercontent.com%2F49791498%2F121062224-baff3a80-c7bc-11eb-9d9a-3090708eac69.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up our Travis CI script
&lt;/h3&gt;

&lt;p&gt;According to the Travis CI documentation, 'Travis CI supports your development process by automatically building and testing code changes, providing immediate feedback on the success of the change. Travis CI can also automate other parts of your development process by managing deployments and notifications.'&lt;/p&gt;

&lt;p&gt;It is a Continuous Integration/Continuous Deployment tool which automatically runs the test(s) you specify in a .travis.yml file and sends you a report stating the build status of your commit, in this way, broken code is prevented from being pushed to production.&lt;/p&gt;

&lt;p&gt;A simple Travis script can be written as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;language: python
python:
  - "3.6"      # current default Python on Travis CI

# command to install dependencies
install:
  - pip install -r requirements.txt

# command to run tests
script:
  - python -m unittest test

# safelist
branches:
  only:
  - main
  - dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above script, and in other Travis scripts, commands are used to perform different operations. The ones used here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;language: This is used to specify the programming language in which our code is written (in this case Python).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python: We can specify the language version to run our tests against.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;install: This is used to specify the language specific command to install dependencies upon which our code is dependent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;script: This is used to specify the language specific command to run our pre-defined tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;branches: the 'only' option shows the branches we want to build using a safelist (in this case 'main' and 'dev')&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Demo Time
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Now, to check out if all our branch protection and CI/CD rules work, we push some code to our secondary branch and open up a pull request.&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%2Fuser-images.githubusercontent.com%2F49791498%2F121061520-d9186b00-c7bb-11eb-9d8b-33dd0dd7a9ac.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%2Fuser-images.githubusercontent.com%2F49791498%2F121061520-d9186b00-c7bb-11eb-9d8b-33dd0dd7a9ac.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
The pull request will fail.&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%2Fuser-images.githubusercontent.com%2F49791498%2F121061790-34e2f400-c7bc-11eb-81a2-8efa6c84e8bd.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%2Fuser-images.githubusercontent.com%2F49791498%2F121061790-34e2f400-c7bc-11eb-81a2-8efa6c84e8bd.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;voila, we are unable to merge our pull request to the main branch (it's the audacity for me😁).&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We are told that our pull request needs to be reviewed, so we add a reviewer by clicking on the icon next to 'Reviewers'.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also, our builds passed (yay!), so our reviewer will be more confident in merging our pull request.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information can be found in the &lt;a href="https://docs.github.com/en/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches" rel="noopener noreferrer"&gt;GitHub Docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to check out my &lt;a href="https://github.com/Mbaoma/ci-cd-tutorial.git" rel="noopener noreferrer"&gt;repository&lt;/a&gt; on which this article was built &lt;/p&gt;

&lt;p&gt;I hope we protect our branches better from now onwards. &lt;/p&gt;

&lt;p&gt;Feel free to reach out to me via &lt;a href="https://www.linkedin.com/in/mbaoma-chioma-mary" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selah!!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>github</category>
      <category>programming</category>
    </item>
    <item>
      <title>Enforcing Coding Best Practices using CI</title>
      <dc:creator>Nancy Chauhan</dc:creator>
      <pubDate>Sun, 30 May 2021 11:37:02 +0000</pubDate>
      <link>https://dev.to/ladiesindevops/enforcing-coding-best-practices-using-ci-44n5</link>
      <guid>https://dev.to/ladiesindevops/enforcing-coding-best-practices-using-ci-44n5</guid>
      <description>&lt;p&gt;High-performing teams usually ship faster, better, and often! Organizations irresepctive of their level, focusing on stability and continuous delivery, will deploy frequently. Hundreds of continuous integration build run for every organization on a typical day. It indicates how CI has become an integral part of our development process. Hence to ensure that we are shipping quality code, we should integrate code quality checking in our CI. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1368692809436303360-796" src="https://platform.twitter.com/embed/Tweet.html?id=1368692809436303360"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1368692809436303360-796');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1368692809436303360&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1281102326929874944-545" src="https://platform.twitter.com/embed/Tweet.html?id=1281102326929874944"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1281102326929874944-545');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1281102326929874944&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Continuous integration ensures easier bug fixes, improves software quality, and reduces project risk. This blog will show what steps we should integrate into our CI pipelines to ensure that we ship better code.&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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2A3cmnfnMsSS8u4kfcP1v2wg.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2A3cmnfnMsSS8u4kfcP1v2wg.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;br&gt;CI Pipeline integrating code quality checks
  &lt;p&gt;&lt;/p&gt;

&lt;p&gt;Traditionally code reviews use to enforce code quality, However checking for things like missing spaces, missing parameters becomes a burden for code reviewers. It would be great if you some tools to automate these checks. We can set some mandatory steps in our CI to run static analysis on the code for every code push. It creates a better development lifecycle by providing early feedback without human intervention.&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%2Fmiro.medium.com%2Fmax%2F1202%2F1%2AGnbnoXtaOeYZx5ijucW2mA.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%2Fmiro.medium.com%2Fmax%2F1202%2F1%2AGnbnoXtaOeYZx5ijucW2mA.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;br&gt;Source: &lt;a href="https://xkcd.com/1285/" rel="noopener noreferrer"&gt;https://xkcd.com/1285/&lt;/a&gt;
  &lt;p&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Unit Testing
&lt;/h1&gt;

&lt;p&gt;Unit testing is the process of testing discrete functions at the source code. It is ubiquitous that a CI pipeline contains a test job that verifies your code. If the tests fail, the pipeline fails, and users get notified. It allows fixing the code earlier. Unit tests should be fast and should aim to cover 100% of the codebase. It can give enough confidence that the application is functioning correctly at this point. If unit tests are not automated, the feedback cycle would be slow.&lt;/p&gt;

&lt;h1&gt;
  
  
  Code coverage
&lt;/h1&gt;

&lt;p&gt;Code coverage is a metric that can help you understand how comprehensive are your unit tests. It’s a handy metric that can help you assess the quality of your test suite. Code Coverage Reporting is how we know that all lines of code written have been exercised through testing.&lt;/p&gt;

&lt;h1&gt;
  
  
  Static code analysis
&lt;/h1&gt;

&lt;p&gt;Static code analysis parses and checks the source code and gives feedback about potential issues in code. It acts as a powerful tool to detect common security vulnerabilities, possible runtime errors, and other general coding errors. It can also enforce your coding guidelines or naming conventions along with your maintainability requirements.&lt;/p&gt;

&lt;p&gt;Static code analysis accelerates the feedback cycle in the development process. It gives feedback on new coding issues specific to the branch or commits containing them. It quickly exposes the block of code that we can optimize in terms of quality. By integrating these checks into the CI workflow, we can tackle these code quality issues in the early stages of the delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linting
&lt;/h2&gt;

&lt;p&gt;Linter is a tool that analyzes source code to flag programming errors, bugs, stylistic errors, and suspicious constructs. It helps in enforcing a standard code style.&lt;/p&gt;

&lt;p&gt;We can introduce linter checks in our CI pipelines according to our project setup. There are a vast number of linters out there. Depending on the programming language, there are even more than one linters for each job.&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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2A-WosNzXumx9wbyGbgpcIlA.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2A-WosNzXumx9wbyGbgpcIlA.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;br&gt;Source: &lt;a href="https://xkcd.com/1513/" rel="noopener noreferrer"&gt;https://xkcd.com/1513/&lt;/a&gt;
  &lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Linters for Static Analysis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.sourcelevel.io/engines/pep8/" rel="noopener noreferrer"&gt;pep8&lt;/a&gt; for Python&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.sourcelevel.io/engines/pmd/" rel="noopener noreferrer"&gt;PMD&lt;/a&gt; for Java&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; for Javascript&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Linters focused on Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.sourcelevel.io/engines/bandit/" rel="noopener noreferrer"&gt;Bandit&lt;/a&gt; for Python&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.sourcelevel.io/engines/nodesecurity/" rel="noopener noreferrer"&gt;Node Security&lt;/a&gt; for JavaScript&lt;/li&gt;
&lt;li&gt;SpotBugs with &lt;a href="https://find-sec-bugs.github.io/" rel="noopener noreferrer"&gt;Find sec bugs&lt;/a&gt; for Java&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker lint check
&lt;/h2&gt;

&lt;p&gt;Considering that dockerizing applications are the norm, it is evident how important it is to introduce docker lint checks in our CI pipelines. We should make sure that our docker image generated for our application is optimized and secure.&lt;/p&gt;

&lt;p&gt;There are many open source docker linters available :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hadolint/hadolint" rel="noopener noreferrer"&gt;hadolint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/RedCoolBeans/dockerlint" rel="noopener noreferrer"&gt;dockerlint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Secrets checks
&lt;/h2&gt;

&lt;p&gt;Sometimes developers leak GitHub tokens and various secrets in codebases which should be avoided. We should prevent the leaking of secrets when committing code. We can integrate Yelp’s &lt;a href="https://github.com/Yelp/detect-secrets" rel="noopener noreferrer"&gt;detect-secret&lt;/a&gt; in our workflow, which we can use to scan files for secrets and whitelist false positives to reduce the noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependency Checks
&lt;/h2&gt;

&lt;p&gt;Our code often uses many open source dependencies from public repositories such as maven, PyPI, or npm. These dependencies are maintained by third-party developers who often discover security vulnerabilities in their code. Such vulnerabilities are usually assigned a CVE number and are disclosed publicly to sensitize other developers utilizing their code to update the packages.&lt;/p&gt;

&lt;p&gt;Dependency checkers use information from CVE to check for vulnerable dependencies used in our codebase. There are different tools for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://snyk.io/" rel="noopener noreferrer"&gt;Snyk&lt;/a&gt; for many languages&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://owasp.org/www-project-dependency-check/" rel="noopener noreferrer"&gt;OWASP Dependency-Check&lt;/a&gt; for Java and Python&lt;/li&gt;
&lt;li&gt;npm comes with inbuilt dependency checks&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  All-in-one tools
&lt;/h1&gt;

&lt;p&gt;Some tools aggregate these different static code analysis tools into a single easy to use a package such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.sonarqube.org/" rel="noopener noreferrer"&gt;Sonarqube&lt;/a&gt;: Broad analysis tool&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/returntocorp/semgrep" rel="noopener noreferrer"&gt;Semgrep&lt;/a&gt; tool: Used for go, java, python&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools provide an easy-to-use GUI to find, track and assign issues to developers.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Having the above-discussed steps as a part of your CI/CD pipeline will allow you to monitor, quickly rectify, and grow your code with much higher code quality.&lt;/p&gt;

&lt;p&gt;Originally Posted at &lt;a href="https://medium.com/@_nancychauhan/enforcing-coding-best-practices-using-ci-b3287e362202" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Designing Idempotent APIs</title>
      <dc:creator>Nancy Chauhan</dc:creator>
      <pubDate>Fri, 14 May 2021 07:09:11 +0000</pubDate>
      <link>https://dev.to/ladiesindevops/designing-idempotent-apis-17o2</link>
      <guid>https://dev.to/ladiesindevops/designing-idempotent-apis-17o2</guid>
      <description>&lt;p&gt;Networks fail! Timeouts, outages, and routing problems are bound to happen at any time. It challenges us to design our APIs and clients that will be robust in handling failures and ensuring consistency.&lt;/p&gt;

&lt;p&gt;We can design our APIs and systems to be idempotent, which means that they can be called any number of times while guaranteeing that side effects only occur once. Let’s get a deeper dive into why incorporating idempotency is essential, how it works, and how to implement it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why Idempotency is critical in backend applications?
&lt;/h1&gt;

&lt;p&gt;Consider the design of a social networking site like Instagram where a user can share a post with all their followers. Let’s assume that we are hosting the app-server and database-server on two different machines for better performance and scalability. And also, we are using PostgreSQL to store the data. A post and creating a post will have the following model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE public.posts (
   id int(11) PRIMARY KEY,
   user_id int(11) REFERENCES users,
   image_id int(11) REFERENCES images NULL,
   content character varying(2048) COLLATE pg_catalog."default",
   create_timestamp timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Failures and Retries
&lt;/h2&gt;

&lt;p&gt;If we have our database on a separate server from our application server, sometimes posts will fail because of network issues. There could be the following issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The initial connection could fail as the application server tries to connect to a database server.&lt;/li&gt;
&lt;li&gt;The call could fail midway while the app server is fulfilling the operation, leaving the work in limbo.&lt;/li&gt;
&lt;li&gt;The call could succeed, but the connection breaks before the database server can tell the application server about it.&lt;/li&gt;
&lt;/ul&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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AgtfaDxb3P6Ut-rznIwy78g.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AgtfaDxb3P6Ut-rznIwy78g.png" alt="Retry"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can fix this with retry logic, but it is very tough to suspect the real cause of network failure. Hence it could lead to a scenario where the entry of the post has been made in the database but it could not send the ACK to the app server. Here app server unknowingly keeps retrying and creating duplicate posts. This would eventually lead to business loss. There are many other critical systems like payments, shopping sites, where idempotent systems are quite important.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;The solution to this is to retry, but make the operation idempotent. If an operation is idempotent, the app server can make that same call repeatedly while producing the same result.&lt;/p&gt;

&lt;p&gt;In our design, we can use universally unique identifiers. Each post will be given its own UUID by our application server. We can change our models to have a unique key constraint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
CREATE TABLE public.posts (
   id uuid PRIMARY KEY,
   user_id uuid REFERENCES users,
   image_id uuid REFERENCES images NULL,
   content character varying(2048) COLLATE pg_catalog."default",
   create_timestamp timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO posts (id, user_id, image_id, content)
VALUES ("DC2FB40E-058F-4208-B9A3-EB1790C532C8", "20C5ADC5-D1A5-4A1F-800F-1AADD1E4E954", "3CC32CAE-B6AC-4C53-97EC-25EB49F2E7F3", "Hello-world") RETURNING id ON CONFLICT DO NOTHING;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our application server will generate the UUID when it wants to create a post and retry the Insert statement until it gets a successful response from a database server. We need to change our system to handle constraint violations and return the existing post. Hence, there will always be exactly one post created.&lt;/p&gt;

&lt;h1&gt;
  
  
  Idempotency in HTTP
&lt;/h1&gt;

&lt;p&gt;One of the important aspects of HTTP is the concept that some methods are idempotent. Take GET for an example, how many times you may call the GET method it results in the same outcome. On the other hand, POST is not expected to be an idempotent method, calling it multiple times may result in incorrect updates.&lt;/p&gt;

&lt;p&gt;Safe methods don’t change the representation of the resource in the server e.g. GET method should not change the content of the page your accessing. They are read-only methods while the PUT method will update the page but will be idempotent in nature. To be idempotent, only the actual back-end state of the server is considered, the status code returned by each request may differ: the first call of a DELETE will likely return a 200, while successive ones will likely return a 404.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DELETE /idX/delete HTTP/1.1   -&amp;gt; Returns 200 if idX exists
DELETE /idX/delete HTTP/1.1   -&amp;gt; Returns 404 as it just got deleted
DELETE /idX/delete HTTP/1.1   -&amp;gt; Returns 404
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;GET is both safe and idempotent.&lt;/li&gt;
&lt;li&gt;HEAD is also both safe and idempotent.&lt;/li&gt;
&lt;li&gt;OPTIONS is also safe and idempotent.&lt;/li&gt;
&lt;li&gt;PUT is not safe but idempotent.&lt;/li&gt;
&lt;li&gt;DELETE is not safe but idempotent.&lt;/li&gt;
&lt;li&gt;POST is neither safe nor idempotent.&lt;/li&gt;
&lt;li&gt;PATCH is also neither safe nor idempotent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The HTTP specification defines certain methods to be idempotent but it is up to the server to actually implement it. For example, send a request-id header with a UUID which the server uses to deduplicate PUT request. If you are serving a GET request, we should not change the server-side data.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Designing idempotent systems is important for building a resilient microservice-based architecture. This helps in solving a lot of problems caused due to the network which is inherently lossy. By leveraging an idempotent queue such as Kafka, it makes sure your operations can be retried in case of a long outage. This helps you to design systems that never lose data and any missing data can be adjusted by replaying the message queue. If all operations are idempotent it will result in the same state regardless of how many times messages are processed.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://medium.com/@_nancychauhan/idempotency-in-api-design-bc4ea812a881" rel="noopener noreferrer"&gt;https://medium.com/@_nancychauhan/idempotency-in-api-design-bc4ea812a881&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a Prometheus Exporter</title>
      <dc:creator>Nancy Chauhan</dc:creator>
      <pubDate>Mon, 03 May 2021 11:34:39 +0000</pubDate>
      <link>https://dev.to/ladiesindevops/building-a-prometheus-exporter-1cb9</link>
      <guid>https://dev.to/ladiesindevops/building-a-prometheus-exporter-1cb9</guid>
      <description>&lt;p&gt;&lt;a href="https://prometheus.io/docs/introduction/overview/"&gt;Prometheus&lt;/a&gt; is an open-source monitoring tool for collecting metrics from your application and infrastructure. As one of the foundations of the cloud-native environment, Prometheus has become the de-facto standard for visibility in the cloud-native landscape.&lt;/p&gt;

&lt;h1&gt;
  
  
  How Prometheus Works?
&lt;/h1&gt;

&lt;p&gt;Prometheus is a &lt;a href="https://www.influxdata.com/time-series-database/"&gt;time-series database&lt;/a&gt; and a pull-based monitoring system. It periodically scrapes HTTP endpoints (targets) to retrieve metrics. It can monitor targets such as servers, databases, standalone virtual machines, etc.&lt;br&gt;
Prometheus read metrics exposed by target using a simple &lt;a href="https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format"&gt;text-based&lt;/a&gt; exposition format. There are client libraries that help your application to expose metrics in Prometheus format.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K2vVJzzp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AUhSRulXaVEDoQQRL4nPu6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K2vVJzzp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AUhSRulXaVEDoQQRL4nPu6g.png" alt="How Prometheus Works?"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Prometheus Metrics
&lt;/h1&gt;

&lt;p&gt;While working with Prometheus it is important to know about Prometheus metrics. These are the four types of metrics that will help in instrumenting your application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Counter (the only way is up): Use counters for counting events, jobs, money, HTTP request, etc. where a cumulative value is useful.&lt;/li&gt;
&lt;li&gt;Gauges (the current picture): Use where the current value is important — CPU, RAM, JVM memory usage, queue levels, etc.&lt;/li&gt;
&lt;li&gt;Histograms (Sampling Observations): Generally use with timings, where an overall picture over a time frame is required — query times, HTTP response times.&lt;/li&gt;
&lt;li&gt;Summaries (client-side quantiles): Similar in spirit to the Histogram, with the difference being that quantiles are calculated on the client-side as well. Use when you start using quantile values frequently with one or more histogram metrics.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Using Prometheus
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus provides client libraries that you can use to add instrumentation to your applications.&lt;/li&gt;
&lt;li&gt;The client library exposes your metrics at URLs such as &lt;a href="http://localhost:8000/metrics"&gt;http://localhost:8000/metrics&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Configure the URL as one of the targets in Prometheus. Prometheus will now scrape metrics in periodic intervals. You can use visualization tools such as Grafana to view your metrics or configure alerts using Alertmanager via custom rules defined in configuration files.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Prometheus Exporters
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rfWelX0B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/0%2A1OpRRb67QvRVg4nx" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rfWelX0B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/0%2A1OpRRb67QvRVg4nx" alt="Exporter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Prometheus has a huge ecosystem of &lt;a href="https://awesomeopensource.com/projects/prometheus-exporter"&gt;exporters&lt;/a&gt;. Prometheus exporters bridge the gap between Prometheus and applications that don’t export metrics in the Prometheus format. For example, Linux does not expose Prometheus-formatted metrics. That’s why Prometheus exporters, like &lt;a href="https://github.com/prometheus/node_exporter"&gt;the node exporter&lt;/a&gt;, exist.&lt;/p&gt;

&lt;p&gt;Some applications like Spring Boot, Kubernetes, etc. expose Prometheus metrics out of the box. On the other hand, exporters consume metrics from an existing source and utilize the Prometheus client library to export metrics to Prometheus.&lt;/p&gt;

&lt;p&gt;Prometheus exporters can be stateful or stateless. A stateful exporter is responsible for gathering data and exports them using the general metrics format such as counter, gauge, etc. Stateless exporters are exporters that translate metrics from one format to Prometheus metrics format using counter metric family, gauge metric family, etc. They do not maintain any local state instead they show a view derived from another metric source such as JMX. For example, Jenkins Jobmon is a Prometheus exporter for Jenkins which calls Jenkins API to fetch the metrics on every scrape.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/grofers"&gt;
        grofers
      &lt;/a&gt; / &lt;a href="https://github.com/grofers/jenkins-jobmon"&gt;
        jenkins-jobmon
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Prometheus exporter to monitor Jenkins jobs
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;h1&gt;
Jenkins Jobmon&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/grofers/jenkins-jobmon/actions"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cRWrnscq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/grofers/jenkins-jobmon/workflows/ci/badge.svg" alt="CI Actions Status"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Jenkins exporter for Prometheus in python.&lt;/p&gt;
&lt;p&gt;It uses &lt;a href="https://github.com/prometheus/client_python#custom-collectors"&gt;Prometheus custom collector API&lt;/a&gt;, which allows making custom
collectors by proxying metrics from other systems.&lt;/p&gt;
&lt;p&gt;Currently we fetch 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;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Labels&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jenkins_job_monitor_total_duration_seconds_sum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gauge&lt;/td&gt;
&lt;td&gt;Jenkins build total duration in millis&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;jobname&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, &lt;code&gt;repository&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jenkins_job_monitor_fail_count&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gauge&lt;/td&gt;
&lt;td&gt;Jenkins build fail counts&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;jobname&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, &lt;code&gt;repository&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jenkins_job_monitor_total_count&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gauge&lt;/td&gt;
&lt;td&gt;Jenkins build total counts&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;jobname&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, &lt;code&gt;repository&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jenkins_job_monitor_pass_count&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gauge&lt;/td&gt;
&lt;td&gt;Jenkins build pass counts&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;jobname&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, &lt;code&gt;repository&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jenkins_job_monitor_pending_count&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gauge&lt;/td&gt;
&lt;td&gt;Jenkins build pending counts&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;jobname&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, &lt;code&gt;repository&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jenkins_job_monitor_stage_duration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gauge&lt;/td&gt;
&lt;td&gt;Jenkins build stage duration in ms&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;jobname&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, &lt;code&gt;repository&lt;/code&gt;, &lt;code&gt;stagename&lt;/code&gt;, &lt;code&gt;build&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jenkins_job_monitor_stage_pass_count&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Counter&lt;/td&gt;
&lt;td&gt;Jenkins build stage pass count&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;jobname&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, &lt;code&gt;repository&lt;/code&gt;, &lt;code&gt;stagename&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jenkins_job_monitor_stage_fail_count&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Counter&lt;/td&gt;
&lt;td&gt;Jenkins build stage fail count&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;jobname&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, &lt;code&gt;repository&lt;/code&gt;, &lt;code&gt;stagename&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
Usage&lt;/h2&gt;
&lt;h3&gt;
Configuration&lt;/h3&gt;
&lt;p&gt;Create a file &lt;code&gt;config.yml&lt;/code&gt; using this template:&lt;/p&gt;
&lt;div class="highlight highlight-source-yaml position-relative js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;jobs&lt;/span&gt;
  &lt;span class="pl-ent"&gt;example&lt;/span&gt;:          &lt;/pre&gt;…
&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/grofers/jenkins-jobmon"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h1&gt;
  
  
  Let’s build a generic HTTP server metrics exporter!
&lt;/h1&gt;

&lt;p&gt;We will build a Prometheus exporter for monitoring HTTP servers from logs. It extracts data from HTTP logs and exports it to Prometheus. We will be using a &lt;a href="https://github.com/prometheus/client_python"&gt;python client library&lt;/a&gt;, &lt;code&gt;prometheus_client&lt;/code&gt;, to define and expose metrics via an HTTP endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RBqc8oLO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AtnVyecPLcTgwQY0LbChBxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RBqc8oLO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AtnVyecPLcTgwQY0LbChBxw.png" alt="One of the metrics from httpd_exporter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our HTTP exporter will repeatedly follow server logs to extract useful information such as HTTP requests, status codes, bytes transferred, and requests timing information. HTTP logs are structured and standardized across different servers such as Apache, Nginx, etc. You can read more about it from &lt;a href="https://publib.boulder.ibm.com/tividd/td/ITWSA/ITWSA_info45/en_US/HTML/guide/c-logs.html"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;We will use a counter metric to store the HTTP requests using status code as a label.&lt;/li&gt;
&lt;li&gt;We will use a counter metric to store bytes transferred.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the script which collects data from apache logs indefinitely and exposes metrics to Prometheus :&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;follow_log&lt;/code&gt; function tails apache logs stored var/log/apache in your system infinitely. &lt;code&gt;gather_metrics()&lt;/code&gt; uses a regular expression to fetch the useful information from logs like status_code and total_bytes_sent and accordingly increments the counters.&lt;/p&gt;

&lt;p&gt;If you run the script, it will start the server at &lt;a href="http://localhost:8000"&gt;http://localhost:8000&lt;/a&gt; The collected metrics will show up there. Setup &lt;a href="https://github.com/Nancy-Chauhan/httpd_exporter/blob/master/prometheus/prometheus.yml"&gt;Prometheus&lt;/a&gt; to scrape the endpoint. Over time, Prometheus will build the time-series for the metrics collected. Setup &lt;a href="https://github.com/Nancy-Chauhan/httpd_exporter/blob/master/docker-compose.yml"&gt;Grafana&lt;/a&gt; to visualize the data within Prometheus.&lt;/p&gt;

&lt;p&gt;You can find the code here and run the exporter:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Nancy-Chauhan"&gt;
        Nancy-Chauhan
      &lt;/a&gt; / &lt;a href="https://github.com/Nancy-Chauhan/httpd_exporter"&gt;
        httpd_exporter
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Prometheus exporter for monitoring apache
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;h1&gt;
httpd_exporter&lt;/h1&gt;
&lt;p&gt;Prometheus exporter for monitoring http servers from logs.&lt;/p&gt;
&lt;p&gt;It extracts data from http logs and export to prometheus.&lt;/p&gt;
&lt;h3&gt;
Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;python 3.6 +&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Usage&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Clone the repo&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;docker-compose up&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Grafana Dashboard&lt;/h2&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://raw.githubusercontent.com/Nancy-Chauhan/httpd_exporter/master/docs/grafana_dashboard.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W-VP-KO2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Nancy-Chauhan/httpd_exporter/master/docs/grafana_dashboard.png" alt="Grafana Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Nancy-Chauhan/httpd_exporter"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;Originally Posted at &lt;a href="https://medium.com/@_nancychauhan/building-a-prometheus-exporter-8a4bbc3825f5"&gt;https://medium.com/@_nancychauhan/building-a-prometheus-exporter-8a4bbc3825f5&lt;/a&gt; &lt;/p&gt;

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