<?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: Priyank Sevak</title>
    <description>The latest articles on DEV Community by Priyank Sevak (@decoders_lord).</description>
    <link>https://dev.to/decoders_lord</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%2F1369921%2F7439313e-995e-4127-a91d-38317b7532b7.jpeg</url>
      <title>DEV Community: Priyank Sevak</title>
      <link>https://dev.to/decoders_lord</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/decoders_lord"/>
    <language>en</language>
    <item>
      <title>Building a PR Review Agent: My Transition from Learning Scripts to Real Tools (Phase 3)</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Mon, 23 Mar 2026 10:41:20 +0000</pubDate>
      <link>https://dev.to/decoders_lord/building-a-pr-review-agent-my-transition-from-learning-scripts-to-real-tools-phase-3-3a5f</link>
      <guid>https://dev.to/decoders_lord/building-a-pr-review-agent-my-transition-from-learning-scripts-to-real-tools-phase-3-3a5f</guid>
      <description>&lt;p&gt;In Phase 1, I just &lt;a href="https://dev.to/decoders_lord/ai-agent-vs-chatbot-156i"&gt;tried to understand the mental model&lt;/a&gt; of what an agent actually is. In Phase 2, I &lt;a href="https://dev.to/decoders_lord/building-my-first-ai-agent-from-scratch-1e35"&gt;built a basic toy agent from scratch&lt;/a&gt; using raw Python to figure out how the LLM tool-calling loop actually works under the hood. &lt;/p&gt;

&lt;p&gt;That was great for learning, but writing manual orchestrations for every tool quickly became a bottleneck. So for Phase 3, I forced myself to build something I could actually use, using a real framework.&lt;/p&gt;

&lt;p&gt;Here is what I built, and more importantly, what building it taught me.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built: A PR Review Agent
&lt;/h2&gt;

&lt;p&gt;Instead of an abstract "code analyzer," I built a dedicated AI workflow that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Takes a public GitHub Pull Request URL.&lt;/li&gt;
&lt;li&gt;Fetches the raw &lt;code&gt;.diff&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Analyzes the changes (lines added/removed, functions touched, nesting depth).&lt;/li&gt;
&lt;li&gt;Fetches the target repository's &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; guidelines.&lt;/li&gt;
&lt;li&gt;Generates a PR title and description matching the repo's rules.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because this evolved from a "learning script" into a standalone tool, I extracted it into its own repository:&lt;br&gt;
🔗 &lt;strong&gt;&lt;a href="https://github.com/DecodersLord/PR-Review-Agent" rel="noopener noreferrer"&gt;GitHub Repo: PR Review Agent&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Moving to an Agentic Framework
&lt;/h2&gt;

&lt;p&gt;In Phase 2, I wrote all the orchestration (the while loops, appending to conversation history, managing API retries) myself. It was tedious.&lt;/p&gt;

&lt;p&gt;For this project, I used &lt;strong&gt;&lt;a href="https://github.com/huggingface/smolagents" rel="noopener noreferrer"&gt;smolagents&lt;/a&gt;&lt;/strong&gt; by Hugging Face. The difference was night and day, but it also forced me to change how I think about building.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Tool Descriptions are Contracts
&lt;/h3&gt;

&lt;p&gt;In my previous raw Python agent, I had to write massive JSON schemas to explain my tools to the LLM. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;smolagents&lt;/code&gt; abstracts that away with a simple &lt;code&gt;@tool&lt;/code&gt; decorator. However, I quickly learned that the &lt;strong&gt;docstring&lt;/strong&gt; of that function is the most critical code you will write. If your description is vague, the LLM will hallucinate parameters or ignore the tool entirely. I stopped thinking about "writing code" and started thinking about "designing clear contracts."&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Single-Agent vs Multi-Agent
&lt;/h3&gt;

&lt;p&gt;There is a lot of hype right now about "Multi-Agent Systems." It’s tempting to try and build a complex swarm of agents (a fetcher, a reader, a reviewer). &lt;/p&gt;

&lt;p&gt;As a beginner in this space, I explicitly avoided that. I stuck to a &lt;strong&gt;Single-Agent + Tools&lt;/strong&gt; architecture. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CodeAgent&lt;/code&gt; (powered by the powerful open-weights &lt;code&gt;Qwen2.5-Coder-32B-Instruct&lt;/code&gt; model) was more than capable of handling the linear task (fetch diff → read guidelines → write summary) on its own if I just gave it the right tools. Splitting it into multiple agents would have been over-engineering just for the sake of buzzwords.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Splitting Up Tools Increases Reliability
&lt;/h3&gt;

&lt;p&gt;My first instinct was to write one giant tool: &lt;code&gt;fetch_and_analyze_pr&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;But I realized that tools should &lt;em&gt;execute&lt;/em&gt;, not &lt;em&gt;reason&lt;/em&gt;. I split it up: one tool just fetches the diff text, and another tool parses the metadata. By giving the LLM granular tools, it got visibility into both the raw code and the structured stats, which made its final PR description much more accurate.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;I am documenting this journey not because I’m an expert, but to demonstrate my capabilities as I transition into this field. Shipping this project showed me that open-source models (like Qwen via Hugging Face) are incredibly capable when you give them well-structured tools and a clean orchestration loop.&lt;/p&gt;

&lt;p&gt;The PR Review Agent works, but there's a lot of room for improvement.&lt;/p&gt;

&lt;p&gt;Until then, the rule remains: &lt;strong&gt;Build → Refine → Document → Move Forward.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are also navigating the shift into AI Engineering, you can follow the core learning tracking repository here:&lt;br&gt;
🔗 &lt;strong&gt;&lt;a href="https://github.com/DecodersLord/Agentic-AI-Journey" rel="noopener noreferrer"&gt;Agentic-AI-Journey&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" height="100" width="434"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>webdev</category>
      <category>learning</category>
    </item>
    <item>
      <title>Building my first AI Agent from scratch (Phase 2)</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Wed, 25 Feb 2026 08:54:48 +0000</pubDate>
      <link>https://dev.to/decoders_lord/building-my-first-ai-agent-from-scratch-1e35</link>
      <guid>https://dev.to/decoders_lord/building-my-first-ai-agent-from-scratch-1e35</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/decoders_lord/ai-agent-vs-chatbot-156i"&gt;last post&lt;/a&gt;, I broke down the mental model behind AI Agents: what they are, how they differ from chatbots, and the agent lifecycle (Observe → Think → Plan → Act → Repeat).&lt;/p&gt;

&lt;p&gt;That was Phase 1: &lt;strong&gt;understanding&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Phase 2 was about &lt;strong&gt;building&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I went from "I can explain agents" to "I can build one from scratch." Here's what that looked like.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Code Analyzer Agent&lt;/strong&gt; a simple tool-calling agent powered by Google Gemini.&lt;/p&gt;

&lt;p&gt;You give it code. It runs a local tool to analyze it: extracting function names, class names, import counts, nesting depth, complexity hints, and more, then Gemini summarizes the results in plain English.&lt;/p&gt;

&lt;p&gt;It follows the basic ReAct pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User input&lt;/strong&gt; → send to Gemini (with full conversation history)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini decides&lt;/strong&gt; → should I use a tool, or just respond?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If tool needed&lt;/strong&gt; → execute locally, send result &lt;strong&gt;back&lt;/strong&gt; to Gemini&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini responds&lt;/strong&gt; → writes a friendly summary using the tool result&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If no tool&lt;/strong&gt; → respond directly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loop&lt;/strong&gt; until the user exits&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ftq5zqnonrmhxamcep8vh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftq5zqnonrmhxamcep8vh.png" alt=" " width="800" height="641"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the &lt;a href="https://github.com/DecodersLord/Agentic-AI-Journey" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; if you want to look at the code.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The agent has three pieces:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Reasoning Engine (Gemini)
&lt;/h3&gt;

&lt;p&gt;Gemini acts as the brain. It reads the user's message, looks at the available tools, and decides "Should I call a function or just answer this myself?"&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;function calling&lt;/strong&gt; — Gemini doesn't just generate text, it can generate structured function calls that your code executes.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Tool (analyze_code)
&lt;/h3&gt;

&lt;p&gt;A Python function that takes code as input and returns rich analysis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_lines&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;blank_lines&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;comment_lines&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;import_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function_names&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__init__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;load&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;process&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;helper&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;class_names&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DataProcessor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;has_main_guard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;longest_function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;load&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lines&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;complexity_hints&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deeply nested code detected (max depth: 5 levels)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool doesn't think. It just executes. It uses Python's &lt;code&gt;re&lt;/code&gt; module (regex) to extract names and patterns.&lt;/p&gt;

&lt;p&gt;But to make Gemini aware of it, I had to define a &lt;strong&gt;function declaration&lt;/strong&gt;, a schema that describes the tool's name, what it does, and what parameters it expects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;analyze_code_declaration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FunctionDeclaration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyze_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Analyze a code snippet and return the number of lines, functions, and classes.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OBJECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The code snippet to analyze&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. The Orchestrator (main.py)
&lt;/h3&gt;

&lt;p&gt;The loop that ties it all together. Notice how &lt;code&gt;history&lt;/code&gt; accumulates every message and how tool results are fed &lt;strong&gt;back&lt;/strong&gt; to Gemini:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;  &lt;span class="c1"&gt;# Conversation memory
&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;user_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Add user message to history
&lt;/span&gt;    &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;

    &lt;span class="c1"&gt;# Send FULL history to Gemini (not just latest message)
&lt;/span&gt;    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3-flash-preview&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_call&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;available_tools&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="c1"&gt;# Add tool call + result to history
&lt;/span&gt;        &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_function_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]))&lt;/span&gt;

        &lt;span class="c1"&gt;# Send result BACK to Gemini for a friendly summary
&lt;/span&gt;        &lt;span class="n"&gt;follow_up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3-flash-preview&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;follow_up&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;follow_up&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What I Actually Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The LLM is too smart for your tools
&lt;/h3&gt;

&lt;p&gt;This was the biggest surprise. I gave Gemini an &lt;code&gt;analyze_code&lt;/code&gt; tool, sent it the code, and it... just analyzed the code itself instead of calling my tool.&lt;/p&gt;

&lt;p&gt;Why? Because Gemini looked at the tool (counts lines and functions) and decided it could give a &lt;strong&gt;better&lt;/strong&gt; answer by responding directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; System instructions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;system_instruction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a code analysis agent. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;When the user provides any code snippet, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;you MUST use the analyze_code tool.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Function declarations are the contract
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;FunctionDeclaration&lt;/code&gt; isn't just metadata it's the &lt;strong&gt;contract&lt;/strong&gt; between your code and the LLM. The description and parameter names directly affect whether Gemini decides to call the tool.&lt;/p&gt;

&lt;p&gt;A vague description = Gemini ignores your tool.&lt;br&gt;
A clear description = Gemini uses it correctly.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Tool dispatch needs to be dynamic
&lt;/h3&gt;

&lt;p&gt;In my first version, I hardcoded the tool call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Bad — doesn't scale
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;analyze_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix is a simple dict that maps tool names to functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;available_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyze_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;analyze_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Good — works for any number of tools
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;available_tools&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is exactly how you'd scale to a multi-tool agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Your agent needs memory
&lt;/h3&gt;

&lt;p&gt;My first version sent only the &lt;strong&gt;latest&lt;/strong&gt; user message to Gemini. It had zero memory. So when I said &lt;em&gt;"What can I improve in the code above?"&lt;/em&gt;, Gemini replied &lt;em&gt;"Please provide the code"&lt;/em&gt; it genuinely didn't remember "above."&lt;/p&gt;

&lt;p&gt;The fix: maintain a &lt;code&gt;history&lt;/code&gt; list that accumulates every message (user + agent + tool calls). Send the &lt;strong&gt;full history&lt;/strong&gt; to Gemini on every turn. Now follow-up questions just work.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Tool results must go back to the LLM
&lt;/h3&gt;

&lt;p&gt;This was the biggest "aha" moment. My first agent loop looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User → Gemini → Tool Call → Print raw result → Done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool result was just printed as a raw dictionary. Gemini never saw it! So it could never summarize it or reason about it.&lt;/p&gt;

&lt;p&gt;The correct pattern is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User → Gemini → Tool Call → Run Tool → Send result BACK to Gemini → Gemini responds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This "return trip" is what makes the agent actually useful. Without it, you're just printing JSON.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Yes, 2 API calls when using a tool — and that's OK
&lt;/h3&gt;

&lt;p&gt;When a tool is used, you make 2 Gemini calls:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Call 1:&lt;/strong&gt; User message → Gemini decides to call a tool&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Call 2:&lt;/strong&gt; Tool result → Gemini writes a friendly response&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the standard pattern across &lt;strong&gt;every&lt;/strong&gt; LLM API (OpenAI, Anthropic, Google). The LLM can't execute your code it can only &lt;em&gt;ask&lt;/em&gt; you to run it. So there's always a round trip.&lt;/p&gt;

&lt;p&gt;But when &lt;strong&gt;no tool is needed&lt;/strong&gt; (follow-up questions), it's only &lt;strong&gt;1 call&lt;/strong&gt; — Gemini already has the context in the conversation history.&lt;/p&gt;

&lt;p&gt;Lesson: Be mindful of LLM round-trips, but don't over-optimize. The 2-call pattern is the cost of giving your agent autonomy.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Phase 2 gave me a working agent with a single tool, conversation memory, and a complete tool-feedback loop.&lt;/p&gt;

&lt;p&gt;Next up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-tool agent&lt;/strong&gt; — adding more tools and letting the LLM choose between them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent memory&lt;/strong&gt; — saving context across sessions (not just within one conversation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-evaluation&lt;/strong&gt; — having the agent check its own output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building this agent taught me that the core of agentic AI is not the model itself, but the control flow that connects the model, tools, and memory into a coherent reasoning cycle.&lt;/p&gt;




&lt;p&gt;🔗 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/DecodersLord/Agentic-AI-Journey" rel="noopener noreferrer"&gt;DecodersLord/Agentic-AI-Journey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📖 &lt;strong&gt;Phase 1 Post:&lt;/strong&gt; &lt;a href="https://dev.to/decoders_lord/ai-agent-vs-chatbot-156i"&gt;AI Agent VS Chatbot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" height="100" width="434"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>python</category>
      <category>beginners</category>
    </item>
    <item>
      <title>AI Agent VS Chatbot (Phase 1)</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Wed, 11 Feb 2026 14:21:48 +0000</pubDate>
      <link>https://dev.to/decoders_lord/ai-agent-vs-chatbot-156i</link>
      <guid>https://dev.to/decoders_lord/ai-agent-vs-chatbot-156i</guid>
      <description>&lt;h2&gt;
  
  
  What is a Chatbot?
&lt;/h2&gt;

&lt;p&gt;Long before Large Language Model (LLMs) became mainstream, chatbots were already widely used in customer support, websites, and internal tools. &lt;/p&gt;

&lt;p&gt;A traditional chatbot was essentially a &lt;strong&gt;structured decision tree&lt;/strong&gt;, Set of predefined rules, flows and conditions &lt;code&gt;if/else&lt;/code&gt; logic or state machines. Based on the user's response, the system would move to the next predefined step in the conversation.&lt;/p&gt;

&lt;p&gt;While it worked well for &lt;strong&gt;predictable use cases&lt;/strong&gt;, it had major limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It could only handle scenarios that were explicitly programmed.&lt;/li&gt;
&lt;li&gt;Any unexpected input would break the flow.&lt;/li&gt;
&lt;li&gt;The chatbot can not reason, adapt, or decide new action dynamically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At best, a chatbot could collect information and maybe trigger a fixed action (like creating a support ticket), but it could not actively try to solve the problem or adjust its strategy.&lt;/p&gt;

&lt;p&gt;In short:&lt;br&gt;
&lt;strong&gt;Chatbots were reactive, not intelligent.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction of LLMs
&lt;/h2&gt;

&lt;p&gt;Large Language Models (LLMs) introduced a fundamental shift.&lt;/p&gt;

&lt;p&gt;Instead of treating every message as just another condition in a decision tree, LLMs interpret user input in a much deeper way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;understanding intent&lt;/li&gt;
&lt;li&gt;extracting meaning&lt;/li&gt;
&lt;li&gt;handling ambiguity&lt;/li&gt;
&lt;li&gt;deciding whether to act or ask clarifying questions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This made conversations feel natural and human-like, rather than mechanical.&lt;/p&gt;

&lt;p&gt;For the first time, a system could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;understand what the user really wants&lt;/li&gt;
&lt;li&gt;reason about multiple possible responses&lt;/li&gt;
&lt;li&gt;generate new solutions instead of following fixed scripts&lt;/li&gt;
&lt;li&gt;LLMs provided the cognitive layer that chatbots were missing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introducing AI Agent
&lt;/h2&gt;

&lt;p&gt;The rise of LLMs enabled something more powerful than chatbots: AI Agents.&lt;/p&gt;

&lt;p&gt;An AI agent is not just a system that talks, it is a system that can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;observe the environment&lt;/li&gt;
&lt;li&gt;reason about goals&lt;/li&gt;
&lt;li&gt;plan steps&lt;/li&gt;
&lt;li&gt;use tools&lt;/li&gt;
&lt;li&gt;execute actions&lt;/li&gt;
&lt;li&gt;evaluate results&lt;/li&gt;
&lt;li&gt;and adapt based on feedback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This bridges the gap between:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I can talk to you"&lt;br&gt;
and&lt;br&gt;
"I can actually help you achieve something."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Here's how an agent work better than a chatbot
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ffr29p61lxwhcv56uo7p8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffr29p61lxwhcv56uo7p8.png" alt="Agent vs. chatbot" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a chatbot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The system mainly responds.&lt;/li&gt;
&lt;li&gt;It cannot perform complex multi-step actions.&lt;/li&gt;
&lt;li&gt;It depends heavily on predefined flows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In an AI agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The system can decide what to do next.&lt;/li&gt;
&lt;li&gt;It can call APIs and external tools.&lt;/li&gt;
&lt;li&gt;It can retry, replan, and self-correct.&lt;/li&gt;
&lt;li&gt;It can operate autonomously toward a goal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Agent Lifecycle
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F4qq7aw6tuc5rquny00c4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F4qq7aw6tuc5rquny00c4.png" alt="Agent Lifecycle" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A typical AI agent follows a loop like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Observe

&lt;ul&gt;
&lt;li&gt;Receive user input or system state.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Think

&lt;ul&gt;
&lt;li&gt;Interpret the situation using reasoning.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Plan

&lt;ul&gt;
&lt;li&gt;Decide which actions or tools are needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Act

&lt;ul&gt;
&lt;li&gt;Execute actions using APIs or services.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Result → Observe again

&lt;ul&gt;
&lt;li&gt;Use the outcome as new input and repeat.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This feedback loop is what makes agents adaptive and intelligent, rather than static systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools at agent's disposal
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fgdshwg8gv5of2jkrz3w6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fgdshwg8gv5of2jkrz3w6.png" alt="Agent Tools" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking at the Agent Lifecycle, you can imagine that it needs more than just state machine and codes, it needs the capabilities to make smart decisions and then act upon them. &lt;/p&gt;

&lt;p&gt;At high level, an agent usually consists of three core layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reasoning Engine (LLM)
The LLM acts as the cognitive core of the agent. It handles:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;interpreting user queries&lt;/li&gt;
&lt;li&gt;reasoning about context and intent. (i.e. understanding that user means Python programming language vs. reptile).&lt;/li&gt;
&lt;li&gt;evaluate results from tools.&lt;/li&gt;
&lt;li&gt;decide next steps.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Action (API/Tools)
Tools represent everything an agent can do in real world: 

&lt;ul&gt;
&lt;li&gt;search engine&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;li&gt;payment services&lt;/li&gt;
&lt;li&gt;scheduling systems&lt;/li&gt;
&lt;li&gt;internal microservices&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tools perform action, they don't think but execute.&lt;/p&gt;

&lt;p&gt;The agent can't perform any action on its own it needs access to external tools and APIs to perform action.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Control (Orchestrator)
The orchestrator system is responsible for:

&lt;ul&gt;
&lt;li&gt;Managing the agent loop.&lt;/li&gt;
&lt;li&gt;Track state and Memory.&lt;/li&gt;
&lt;li&gt;Route Decision to tools.&lt;/li&gt;
&lt;li&gt;Handle retries and failures.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An Orchestrator is implemented using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;workflow engines&lt;/li&gt;
&lt;li&gt;task queues&lt;/li&gt;
&lt;li&gt;state machines&lt;/li&gt;
&lt;li&gt;agent workflows such LangGraph, CrewAI, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Instead of writing rigid workflows and hardcoded logic, we are moving towards systems that can: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reason about goals.&lt;/li&gt;
&lt;li&gt;adapt to changing environments.&lt;/li&gt;
&lt;li&gt;orchestrate tools dynamically.&lt;/li&gt;
&lt;li&gt;and improve through feedback loops.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" height="100" width="434"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>System Design: Availability Patterns</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Wed, 02 Oct 2024 17:22:12 +0000</pubDate>
      <link>https://dev.to/decoders_lord/system-design-availability-patterns-104i</link>
      <guid>https://dev.to/decoders_lord/system-design-availability-patterns-104i</guid>
      <description>&lt;p&gt;Imagine you're shopping online on a popular e-commerce platform. You've added items to your cart, entered your payment information, and clicked "Place Order." Suddenly, the website crashes. Your order is lost, and you're left frustrated and uncertain. This scenario highlights the critical importance of system availability.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Availability Patterns Matter&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Availability patterns are essential for ensuring that systems remain operational and accessible, even in the face of hardware failures, software bugs, or other disruptions. They provide redundancy, fault tolerance, and disaster recovery capabilities, ultimately improving the user experience and protecting valuable data.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Factors Affecting System Availability&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network Connectivity:&lt;/strong&gt;&lt;br&gt;
Imagine an online banking system. If there's a network outage in a specific region, customers in that area will be unable to access their accounts or perform transactions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hardware and Software Failures:&lt;/strong&gt;&lt;br&gt;
A data center experiencing a power outage can lead to hardware failures and system downtime. Additionally, software bugs or vulnerabilities can cause crashes or unexpected behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability Issues:&lt;/strong&gt;&lt;br&gt;
During peak shopping seasons, an e-commerce website may experience a surge in traffic. If the system is not designed to scale effectively, it could become overwhelmed and experience slowdowns or outages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security Breaches:&lt;/strong&gt;&lt;br&gt;
A ransomware attack on a healthcare provider's network could encrypt patient data, making it inaccessible and disrupting critical operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;External Dependencies:&lt;/strong&gt;&lt;br&gt;
A social media platform relies on third-party services for image hosting and video streaming. If these services experience downtime, the social media platform's functionality will be affected.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Measuring Availability:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To assess the reliability and performance of distributed systems, several metrics are commonly used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Uptime Percentage:&lt;/strong&gt; This measures the proportion of time a system is operational. A higher percentage indicates greater availability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mean Time Between Failures (MTBF):&lt;/strong&gt; This metric represents the average time between system failures. A higher MTBF suggests a more reliable system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mean Time To Repair (MTTR):&lt;/strong&gt; This measures the average time required to restore a system after a failure. A lower MTTR indicates faster recovery and higher availability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Service Level Agreements (SLAs):&lt;/strong&gt; These are formal contracts that define the expected level of service, including availability targets. Meeting or exceeding SLAs is crucial for ensuring customer satisfaction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Nine's of Availability:&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fk9vcpjqx0u9j8m3u42iz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fk9vcpjqx0u9j8m3u42iz.png" alt="Nine's of Availability" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The availability is measured using Nines rather than percentages. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Availability Patterns:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Consider a large-scale banking system. If the system were to go down, customers would be unable to access their accounts, make transactions, or pay bills. This could lead to significant financial losses, operational disruptions, and damage to the bank's reputation.&lt;/p&gt;

&lt;p&gt;To mitigate these risks, banks employ various availability patterns:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Fail-Over Pattern:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In a typical failover setup, there's a primary component handling the workload, and a secondary component waiting in the wings. The primary component is constantly monitored for signs of failure. If it goes down, the secondary component is automatically activated to ensure uninterrupted service.&lt;/p&gt;

&lt;p&gt;There are several ways to implement failover, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Active-Active:&lt;/strong&gt;
Both primary and secondary components are active, handling requests simultaneously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Faguo2ky281gim5tyn5kc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Faguo2ky281gim5tyn5kc.png" alt="Active-Active" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Active-Passive:&lt;/strong&gt;
The secondary component is inactive until the primary fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F0c3ngguhlt9c5lcta7jt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0c3ngguhlt9c5lcta7jt.png" alt="Active-Passive" width="800" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Disadvantages of Failover&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fail-over adds more hardware and additional complexity.&lt;/li&gt;
&lt;li&gt;There is a potential for loss of data if the active system fails before any newly written data can be replicated to the passive.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Replication Pattern:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Replication is a strategy that involves storing multiple copies of data across different locations. This redundancy ensures that even if one location experiences a failure, the data can still be accessed from another.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Master-Master:&lt;/strong&gt;
In this setup, both systems can serve as both the primary and secondary components. They can handle both read and write operations, providing high availability and fault tolerance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both Master-Master replication and Active-Active failover involve multiple active components. However, the focus is different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Master-Master:&lt;/strong&gt; Primarily concerned with data replication and redundancy. Both systems can handle read and write operations, ensuring high availability and fault tolerance.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Active-Active:&lt;/strong&gt; Primarily focused on load balancing and performance. Both systems share the workload, improving scalability and response times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Master-Slave:&lt;/strong&gt;&lt;br&gt;
Here, one system acts as the master, handling write operations, while the others (slaves) replicate the data for read operations. This provides data redundancy and offloads read traffic from the master.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In both Master-Slave replication and Active-Passive failover, one component is primary and the other is secondary. However, their roles differ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Master-Slave:&lt;/strong&gt; The primary system handles writes, while the secondary (slave) replicates data for reads. This provides data redundancy and offloads read traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active-Passive:&lt;/strong&gt; The primary system handles requests, while the secondary is on standby, ready to take over if the primary fails. This ensures high availability but may introduce latency during failover.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This post provides a comprehensive overview of availability patterns in distributed systems. It covers the importance of availability, factors affecting it, key metrics, and common patterns like failover and replication. The post also discusses the challenges and best practices for implementing these patterns.&lt;/p&gt;

&lt;p&gt;Leave a like.&lt;br&gt;
Leave a comment, Always open to discuss and learn.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>systemdesign</category>
      <category>devjournal</category>
      <category>learning</category>
    </item>
    <item>
      <title>Salesforce: Leveling Up with Apex Testing</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Mon, 30 Sep 2024 16:16:12 +0000</pubDate>
      <link>https://dev.to/decoders_lord/salesforce-leveling-up-with-apex-testing-1pc8</link>
      <guid>https://dev.to/decoders_lord/salesforce-leveling-up-with-apex-testing-1pc8</guid>
      <description>&lt;p&gt;Think of your code as a house. Testing is like a home inspector – it reveals hidden flaws before they become major problems.&lt;/p&gt;

&lt;p&gt;Just like a home inspector ensures your dream home is structurally sound, testing your code is crucial for guaranteeing its reliability and functionality. In the world of Salesforce development, Apex testing plays this vital role. It's a structured approach to simulating real-world scenarios and verifying if your code behaves as intended. Here's how Apex testing empowers you as a developer:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Benefits of Apex Testing:&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Uncover Hidden Defects:&lt;/strong&gt; Imagine deploying code riddled with production errors! Testing acts as a safety net, identifying and eliminating potential bugs before they disrupt your users' experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Confidence in Code Changes:&lt;/strong&gt; Ever hesitate to modify existing code for fear of breaking something? Robust testing provides peace of mind, allowing you to confidently enhance functionalities without introducing regressions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Meeting Deployment Requirements:&lt;/strong&gt; Salesforce enforces a minimum code coverage of 75% for deployment. Effective Apex testing ensures your code meets this threshold, enabling smooth deployments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmr77xlkz4okv10yikz0x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmr77xlkz4okv10yikz0x.jpg" alt="Image description" width="426" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Solution - Diving into Apex Testing:&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apex"&gt;&lt;code&gt;&lt;span class="nd"&gt;@isTest&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyTestClass&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@isTest&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;myTest&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
     &lt;span class="c1"&gt;//Your Test codes&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Sandbox Testing: A Clean Slate&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In Salesforce, Apex test classes operate in a sandbox environment, isolated from your production data. This means you can create and manipulate test data without affecting real-world records.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Understanding Data Access:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While test classes can't directly access your existing data, they can access setup and metadata objects like Users and Profiles. This provides a controlled environment for testing without risking production data.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Leveraging Test Data:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Creating test data is essential for effective testing. You can generate it within your test classes or use utility classes for reusable data creation. This allows you to simulate various scenarios and ensure your code functions as expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Benefits of Sandbox Testing:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Isolated Environment:&lt;/strong&gt; Prevents accidental changes to production data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controlled Testing:&lt;/strong&gt; Enables focused testing without external factors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Flexibility:&lt;/strong&gt; Create and modify test data to simulate different scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Utilizing &lt;code&gt;@testSetup&lt;/code&gt;:&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apex"&gt;&lt;code&gt;&lt;span class="nd"&gt;@isTest&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CommonTestSetup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@testSetup&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Create common test accounts&lt;/span&gt;
        &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;testAccts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;testAccts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;TestAcct'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="n"&gt;testAccts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@isTest&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testMethod1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Get the first test account by using a SOQL query&lt;/span&gt;
        &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="n"&gt;acct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;TestAcct0'&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="c1"&gt;// Modify first account&lt;/span&gt;
        &lt;span class="n"&gt;acct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Phone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;555-1212'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// This update is local to this test method only.&lt;/span&gt;
        &lt;span class="k"&gt;update&lt;/span&gt; &lt;span class="n"&gt;acct&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Delete second account&lt;/span&gt;
        &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="n"&gt;acct2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s2"&gt;TestAcct1'&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="c1"&gt;// This deletion is local to this test method only.&lt;/span&gt;
        &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;acct2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Perform some testing&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Things to remember while using &lt;code&gt;@testSetup&lt;/code&gt;:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Each test class can only have one &lt;code&gt;@testSetup&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;The entire test class fails if this method encounters a critical error, like a failed DML operation or assertion. &lt;/li&gt;
&lt;li&gt;Additionally, if the &lt;code&gt;@testSetup&lt;/code&gt; method calls a non-test method, code coverage won't be calculated for that non-test method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>webdev</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Escape the Mothership</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Sun, 29 Sep 2024 03:39:24 +0000</pubDate>
      <link>https://dev.to/decoders_lord/escape-the-mothership-2cd4</link>
      <guid>https://dev.to/decoders_lord/escape-the-mothership-2cd4</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/webgame"&gt;Web Game Challenge&lt;/a&gt;, Build a Game: Alien Edition&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a web game inspired by the alien abduction story. The game puts you in the shoes of a normal person going about their daily routine. However, a sudden twist awaits! You'll encounter an unexpected situation that forces you to make a crucial choice: run or fight.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;RUN:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Dodge and jump over a never-ending stream of aliens as they charge towards you. How long can you survive?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;FIGHT:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note to Self NEVER START A PROJECT LATE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjnwakyi5fc9u79phz996.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjnwakyi5fc9u79phz996.jpg" alt="scope creep" width="500" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had the brilliant idea of introducing a &lt;strong&gt;"Cuphead"&lt;/strong&gt; style boss fight to defeat the alien. But I got carried away fixing the bugs in the existing games purely from a code-base perspective. I should have focused on the implementation of this brilliant new feature. Still, my mind kept getting annoyed with the code dumped into my ".js" file and I wasted my time re-arranging and making performance enhancements to the existing game. Which I doubt had any real effect on the game. &lt;/p&gt;

&lt;p&gt;//TO-DO &lt;br&gt;
// "Fight" Button will not work... You might just see alien and our hero have a staring contest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href="https://escape-from-mothership-game.netlify.app/" rel="noopener noreferrer"&gt;Try it here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Github Repo:&lt;/strong&gt; &lt;a href="https://github.com/DecodersLord/alien-game" rel="noopener noreferrer"&gt;Github&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Choosing the Tools:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I opted for building it using HTML Canvas and JavaScript. This combination provides a lightweight and versatile framework for creating web-based games.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Creating the Sprites:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I started looking for free sprite sheets on &lt;a href="https://craftpix.net/freebies/filter/game-backgrounds/" rel="noopener noreferrer"&gt;craftpix&lt;/a&gt; and other resources but had no luck finding good alien sprite. I do not have a good drawing background let alone an animation, which I believe is one of my major drawbacks while trying to create attractive games. While I managed to find good sprites for our "Hero" my search continued to find a good "alien".&lt;br&gt;&lt;br&gt;
To my surprise, I found the &lt;a href="https://github.com/sanderfrenken" rel="noopener noreferrer"&gt;Universal LPC Spritesheet Generator&lt;/a&gt;. This amazing tool allowed me to customize the "alien" character, I can modify the characters from human to bizarre-looking creatures. This tool is a complete win for me. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Collision Detection &amp;amp; scoring:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To ensure a smooth player experience, I implemented collision detection between the player and the aliens. simply scoring if you are able to jump over the alien accurately.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Challenges and Learnings:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Working with sprite sheets involved learning how to define specific frames from the larger sheet and then manipulating them within the HTML Canvas. Additionally, ensuring proper collision detection required understanding how to calculate bounding boxes for the player and aliens.&lt;/p&gt;

&lt;p&gt;I was late to the party, I saw the challenge but took too much time thinking about my game theme and playability. I will implement the fighting scenario in the future and encourage you to check back here for the update. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcma7uk6e06pphon86g1z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcma7uk6e06pphon86g1z.gif" alt="Image description" width="128" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gamechallenge</category>
      <category>gamedev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>DevOps: Linux Performance Monitoring</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Thu, 26 Sep 2024 18:54:21 +0000</pubDate>
      <link>https://dev.to/decoders_lord/devops-linux-performance-monitoring-17oj</link>
      <guid>https://dev.to/decoders_lord/devops-linux-performance-monitoring-17oj</guid>
      <description>&lt;p&gt;In my previous post &lt;a href="https://dev.to/decoders_lord/devops-understanding-process-monitoring-on-linux-3o2g-temp-slug-7435118"&gt;DevOps: Understanding Process Monitoring on Linux&lt;/a&gt; I discussed how a Linux process works and why it's important to monitor process. &lt;/p&gt;

&lt;p&gt;Let's dig deeper into how we can keep an eye out for how a Linux server is "Performing". &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;TL;DR:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This article dives into Linux process monitoring tools and techniques, helping you keep an eye on your server's performance. It covers command-line tools like &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;htop&lt;/code&gt;, &lt;code&gt;vmstat&lt;/code&gt;, and &lt;code&gt;sar&lt;/code&gt; for in-depth monitoring, along with system utilities like &lt;code&gt;System Monitor&lt;/code&gt; for a graphical overview. The article also demonstrates a sample script using &lt;code&gt;top&lt;/code&gt; and &lt;code&gt;uptime&lt;/code&gt; to monitor CPU, memory, and system uptime, laying the groundwork for integrating push notifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Performance Monitoring&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.&lt;code&gt;/proc&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In my previous post, I explained that &lt;strong&gt;"Everything is a File in Linux system"&lt;/strong&gt; so where are these process files stored? &lt;/p&gt;

&lt;p&gt;go to your CMD and just type &lt;code&gt;ls /proc&lt;/code&gt; and you will see your PIDs in there. This is where the Linux process resides. the &lt;code&gt;/proc&lt;/code&gt; directory contains files that contain (including but not limited to): &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Current state of Linux Kernel.&lt;/li&gt;
&lt;li&gt;Information about System Hardware.&lt;/li&gt;
&lt;li&gt;Currently running process.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try running the below commands to find out more about what does &lt;code&gt;/proc&lt;/code&gt; consists of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/cpuinfo

&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/devices &lt;span class="c"&gt;#list serial ports, Network Interface, etc.&lt;/span&gt;

&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/cmdline &lt;span class="c"&gt;#useful in boot failures&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/proc&lt;/code&gt; can be modified and can be used to communicate configurational changes directly to the kernel.&lt;/p&gt;

&lt;p&gt;The Linux kernel is equipped with &lt;code&gt;procps&lt;/code&gt; package which contains useful tools such as ps, top, iostat, etc. to help us in performance and process monitoring. &lt;/p&gt;

&lt;p&gt;In addition to previously discussed &lt;code&gt;top&lt;/code&gt; and &lt;code&gt;ps&lt;/code&gt; there are other alternatives to the &lt;code&gt;top&lt;/code&gt; which can provide additional or graphical alternatives to the traditional &lt;code&gt;top&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;htop&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fljg0trxy4is0qlotrihv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fljg0trxy4is0qlotrihv.png" alt="htop" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;htop&lt;/code&gt; offers a more visually appealing interface with color-encoded bars for CPU and memory utilization.&lt;/p&gt;

&lt;p&gt;It views processes in a tree-like structure making it easier to understand the relationship between processes. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;atop&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcq9l75up9yaf3k7w4qxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcq9l75up9yaf3k7w4qxp.png" alt="atop" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;atop&lt;/code&gt; has the ability to be configured and run on remote systems, making it suitable for large-scale monitoring environments.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;atop&lt;/code&gt; provides long-term monitoring and analysis. It logs system data to a file which allows to review historic trends and identifies performance issue over time. &lt;/p&gt;

&lt;h3&gt;
  
  
  2.&lt;strong&gt;Where's my task manager?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Isn't it easy to find out what's going on in my system and process on Windows by just hitting &lt;strong&gt;"Ctrl+Alt+Del"&lt;/strong&gt; and going to &lt;strong&gt;"Task Manager"&lt;/strong&gt;? Why doesn't Linux provide something like that? &lt;/p&gt;

&lt;p&gt;If you are in a GNOME environment you can find a similar tool under your apps by searching for &lt;strong&gt;"System Monitor"&lt;/strong&gt;. &lt;strong&gt;System Monitor&lt;/strong&gt; has 4 tabs: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;System:&lt;/strong&gt; Shows basic system info.
-&lt;strong&gt;Process:&lt;/strong&gt; Lists all the running processes. Can sort them and also perform operations such as Kill, stop, or terminating that process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resources:&lt;/strong&gt; Lists current CPU usage, Memory and Swap usage, Network usage, and Disk usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File System:&lt;/strong&gt; Lists all currently mounted file systems and additional info such as mount point, system type, and memory usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.&lt;strong&gt;Virtual Memory statistics: &lt;code&gt;vmstat&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As the name suggests the &lt;code&gt;vmstat&lt;/code&gt; command provides detailed info regarding the processes, memory, paging, Input/Output blocks, traps and disk and CPU activity. &lt;/p&gt;

&lt;p&gt;The first time you run &lt;code&gt;vmstat&lt;/code&gt; it lists the average since the last reboot. the subsequent reports are from the sampling period of provided 'delay'.&lt;/p&gt;

&lt;p&gt;Some useful options with &lt;code&gt;vmstat&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vmstat &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="c"&gt;#lists memory and scheduling statistics&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Flkbcpodva1buoku2sswb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Flkbcpodva1buoku2sswb.jpg" alt="vmstat" width="520" height="673"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the above image you can see that running &lt;code&gt;vmstat -s&lt;/code&gt; gives you info regarding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amount of used memory:&lt;/strong&gt; Total memory, currently used memory, Active/Inactive memory, Free, Buffer, Cache, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU statistics:&lt;/strong&gt; High and low priority process, Kernel Process, I/O management, Software interrupts, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Paging:&lt;/strong&gt; Total pages paged in and paged out from virtual memory, total pages read from and written to swap memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event Counters:&lt;/strong&gt; Total interrupts, context switches, timestamps, and forks since last boot time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.&lt;strong&gt;System Activity Reporter: &lt;code&gt;sar&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Go to your terminal and write the below command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /var/log/sysstat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see a bunch of directories either named &lt;code&gt;saDD&lt;/code&gt; or &lt;code&gt;saYYYYMMDD&lt;/code&gt; where YYYY, MM, and DD stand for Year, Month, and Day. These are &lt;strong&gt;"Standard System Activity Daily Data Files"&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;These are the directories created by &lt;code&gt;sar&lt;/code&gt;, which collects and reports information about system activity that has occurred so far since the system started. It is possible to store the output of &lt;code&gt;sar&lt;/code&gt; to a different file by the below command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sar &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;filename] &lt;span class="c"&gt;#save output to a different file&lt;/span&gt;

sar &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="c"&gt;# shows sar output from the previous day&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fl2d2vkwl4qxs9mldblzw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fl2d2vkwl4qxs9mldblzw.png" alt="sar" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Real world example:&lt;/strong&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Problem statement:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You want to keep a check on the current performance of your Linux server. You want to get notified if either CPU usage, Memory Usage, or System usage is going over a certain threshold and prevent unintentional system overutilization. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Assumptions &amp;amp; lab setup&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I will be using the below command which is provided by Linux and is a way to benchmark the hardware or software component. It can generate various types of load, including I/O, CPU, Memory, and Network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;stress &lt;span class="nt"&gt;--cpu&lt;/span&gt; 8 &lt;span class="nt"&gt;--io&lt;/span&gt; 4 &lt;span class="nt"&gt;--vm&lt;/span&gt; 4 &lt;span class="nt"&gt;--vm-bytes&lt;/span&gt; 1024M &lt;span class="nt"&gt;--timeout&lt;/span&gt; 10s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have specified:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  CPU load equivalent to 8 CPU cores. &lt;/li&gt;
&lt;li&gt;  4 I/O concurrent operations. &lt;/li&gt;
&lt;li&gt;  1024 MB of 4 virtual memory workload.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Solution &amp;amp; Explaination:&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Set the interval for monitoring (in seconds)&lt;/span&gt;
&lt;span class="nv"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5

&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c"&gt;# Get CPU usage and average load&lt;/span&gt;
  &lt;span class="nv"&gt;cpu_usage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;top &lt;span class="nt"&gt;-n&lt;/span&gt; 1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'Cpu(s):'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print 100 - $8}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;avg_load&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uptime&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $8, $9, $10}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

  &lt;span class="c"&gt;# Get memory usage&lt;/span&gt;
  &lt;span class="nv"&gt;mem_total&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;free &lt;span class="nt"&gt;-m&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;Mem | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $2}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;mem_used&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;free &lt;span class="nt"&gt;-m&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;Mem | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $3}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;mem_free&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;free &lt;span class="nt"&gt;-m&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;Mem | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $4}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;mem_usage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$mem_used&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;$mem_total&lt;/span&gt; &lt;span class="k"&gt;))&lt;/span&gt;

  &lt;span class="c"&gt;# Get network statistics&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Network Packets:"&lt;/span&gt;
  &lt;span class="c"&gt;# Iterate over each interface&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;interface &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;ifconfig | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'flags'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $1}'&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="nt"&gt;-f1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c"&gt;# Get RX packets and bytes&lt;/span&gt;
    &lt;span class="nv"&gt;packets_transferred&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;ifconfig &lt;span class="nv"&gt;$interface&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'RX packets'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;


    &lt;span class="c"&gt;# Print the interface name and transfer the data&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$interface&lt;/span&gt;&lt;span class="s2"&gt; : &lt;/span&gt;&lt;span class="nv"&gt;$packets_transferred&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;done&lt;/span&gt;

  &lt;span class="c"&gt;# Get system uptime&lt;/span&gt;
  &lt;span class="nv"&gt;uptime_hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;uptime&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;, &lt;span class="s1"&gt;'{sub(".*up ",x,$1);print $1,$2}'&lt;/span&gt;


  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"CPU Usage: &lt;/span&gt;&lt;span class="nv"&gt;$cpu_usage&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Average Load: &lt;/span&gt;&lt;span class="nv"&gt;$avg_load&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Memory Usage: &lt;/span&gt;&lt;span class="nv"&gt;$mem_usage&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"System Uptime: &lt;/span&gt;&lt;span class="nv"&gt;$uptime_hours&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;echo


  sleep&lt;/span&gt; &lt;span class="nv"&gt;$interval&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Code explanation:&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Getting the CPU usage:&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;top &lt;span class="nt"&gt;-n&lt;/span&gt; 1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'Cpu(s):'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print 100 - $8}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Running the &lt;code&gt;top&lt;/code&gt; and grepping details regarding the CPU. The top command will show the details regarding the tasks, CPU details, Swap, and Physical Memory in the system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Getting the Average system load:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In addition to vmstat and sar commands, we can use &lt;code&gt;uptime&lt;/code&gt; command to get concise details about the system. &lt;code&gt;uptime&lt;/code&gt; command will output the current time, how long the system has been running, how many users are currently logged on, and the system load averages for the past 1, 5 and 15 minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fgs56qq99zwqafbfo2ev3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fgs56qq99zwqafbfo2ev3.png" alt="uptime" width="800" height="118"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;avg_load&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uptime&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $8, $9, $10}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am simply manipulating the output to only fetch the required average system load from &lt;code&gt;uptime&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Later in the script, I manipulated the same &lt;code&gt;uptime&lt;/code&gt; output to get the current uptime. I am using some &lt;strong&gt;RegEX&lt;/strong&gt; to accommodate different uptime. i.e. 15 days, 12 hours, 2 minutes, and 45 seconds&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;uptime_hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;uptime&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;, &lt;span class="s1"&gt;'{sub(".*up ",x,$1);print $1,$2}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Getting the Memory usage:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;free&lt;/code&gt; is another useful command to get detailed output regarding the memory available, used, and free on the system. You can think of it as a more concise version of &lt;code&gt;vmstat -s&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F92ok5ptqh4w67jkz0fez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F92ok5ptqh4w67jkz0fez.png" alt="free" width="800" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am manipulating the string returned by &lt;code&gt;free&lt;/code&gt; to get the precise memory currently being used.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The output&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here's the output, I am printing out the CPU usage, Memory Usage, or System usage for now. We can extend the bash code and use Push notification services such as &lt;a href="https://pushover.net/" rel="noopener noreferrer"&gt;pushover&lt;/a&gt;, &lt;a href="https://www.proofpoint.com/us/products/email-protection/open-source-email-solution" rel="noopener noreferrer"&gt;sendmail&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fg4lyt9nid538hla4awev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fg4lyt9nid538hla4awev.png" alt="Output" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Additional Performance Monitoring Tools:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I would just want to list some additional GUI tools which can help you monitor performance of your linux server better: &lt;/p&gt;

&lt;p&gt;1.&lt;code&gt;stacer&lt;/code&gt;:&lt;br&gt;
GUI for CPU/Memory and other things&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fm4mesyb9kd1yxwum6p4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fm4mesyb9kd1yxwum6p4j.png" alt="stacer" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.&lt;code&gt;saidar&lt;/code&gt;:&lt;br&gt;
similar to &lt;code&gt;atop&lt;/code&gt; or &lt;code&gt;htop&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fgiwy6zb4jk44iw6u5i0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fgiwy6zb4jk44iw6u5i0g.png" alt="saidar" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.&lt;code&gt;cpu-x&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;My personal favorite as it gives very precise details on the CPU, memory and Disk usage and feels familiar to use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ffqlexevhvm1ut3iifrt7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffqlexevhvm1ut3iifrt7.png" alt="cpu-x" width="478" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also run the &lt;code&gt;stress&lt;/code&gt; command that I ran in the beginning to benchmark and stress test the CPU directly inside the &lt;code&gt;cpu-x&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fert54zdx75zlybnhahs5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fert54zdx75zlybnhahs5.png" alt="cpu-x" width="475" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This article effectively explores various Linux process monitoring tools. From command-line utilities offering detailed insights to GUI tools providing a visual representation, you're equipped to choose the tools that best suit your needs. The provided script example demonstrates the practical application of these tools and opens doors for further customization with push notifications.&lt;/p&gt;

&lt;p&gt;Feel free to ask any questions or share your preferred monitoring tools and techniques! Let's keep the discussion going!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>devjournal</category>
      <category>beginners</category>
    </item>
    <item>
      <title>System Design: Consistency Patterns</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Wed, 25 Sep 2024 15:27:12 +0000</pubDate>
      <link>https://dev.to/decoders_lord/system-design-consistency-patterns-521</link>
      <guid>https://dev.to/decoders_lord/system-design-consistency-patterns-521</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.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%2Fmee7ldtas9j72wg4y8wc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmee7ldtas9j72wg4y8wc.jpg" alt="Distributed Systems" width="615" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;TL;DR:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Distributed systems store data across multiple servers for better performance and scalability. This introduces challenges in keeping data consistent across all servers. Consistency patterns determine how updates are propagated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong Consistency: Ensures all servers have the latest data, but can be slow and resource-intensive. Used in file systems, databases, and financial services.&lt;/li&gt;
&lt;li&gt;Weak Consistency: Prioritizes availability over perfect data accuracy. May have temporary inconsistencies. Used in VoIP, multiplayer games, and cache servers.&lt;/li&gt;
&lt;li&gt;Eventual Consistency: All servers will eventually have the same data, but reads may return outdated data temporarily. Used in CDNs, email systems, and social media platforms.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Distributed Systems&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You probably know by now that the website or data we access daily does not necessarily reside on a single server. Everything in today's world mostly works on &lt;strong&gt;Distributed Systems&lt;/strong&gt; meaning that data is scattered across several servers/nodes, these servers can be within the same country or across multiple countries. Distributed System solves problems such as fault tolerance, Scalability, and reliability.&lt;/p&gt;

&lt;p&gt;Consider an e-commerce website with a global customer base. To provide fast and reliable service, the website's data is distributed across multiple servers.&lt;/p&gt;

&lt;p&gt;However, this distribution can introduce challenges related to data consistency. For instance, imagine two customers, Alice and Bob, trying to purchase the last item of a popular product. If Alice places an order on Server A, the system might initially show the item as in stock. However, before the updated stock information is propagated to Server B, Bob could also place an order, leading to a situation where both customers believe they've successfully purchased the same item.&lt;/p&gt;

&lt;p&gt;When Bob later discovers the item is out of stock, it can negatively impact the customer experience and erode trust in the company. This scenario highlights the importance of consistency in distributed systems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F3batyzm4kg6oi8xzq0j3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F3batyzm4kg6oi8xzq0j3.png" alt="Distributed System" width="800" height="869"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;"Consistency Patterns"&lt;/strong&gt; will determine how the state is propagated within the distributed systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Consistency Patterns&lt;/strong&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Strong Consistency&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fixiibdkzv8hy5mkfuko3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fixiibdkzv8hy5mkfuko3.png" alt="Strong Consistency" width="456" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the name suggests, strong consistency prioritizes data consistency over system availability. This pattern is essential for applications where accuracy and reliability are paramount, even if it comes at the cost of performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Challenges of Strong Consistency:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Performance:&lt;/strong&gt; Ensuring strong consistency can lead to increased latency and slower response times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Intensive:&lt;/strong&gt; Implementing strong consistency mechanisms can be computationally expensive, consuming significant system resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Applications of Strong Consistency:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;File Systems:&lt;/strong&gt; File systems typically require strong consistency to ensure data integrity and prevent corruption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relational Database Management Systems (RDBMS):&lt;/strong&gt; RDBMSs often implement strong consistency to maintain data accuracy and prevent inconsistencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Financial Services:&lt;/strong&gt; Banking systems and financial transactions demand strong consistency to prevent errors and ensure accurate record-keeping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distributed Protocols:&lt;/strong&gt; Protocols like &lt;a href="https://martinfowler.com/articles/patterns-of-distributed-systems/paxos.html" rel="noopener noreferrer"&gt;Paxos&lt;/a&gt; and two-phase commit (2PC) are designed to achieve strong consistency in distributed systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Weak Consistency&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fk4e16oe1iyjs58eehs1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fk4e16oe1iyjs58eehs1f.png" alt="Weak Consistency" width="712" height="762"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the name suggests, weak consistency prioritizes availability and fault tolerance over strict data consistency. This pattern is suitable for services where data accuracy is less critical than ensuring the system remains accessible and operational.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Challenges of Weak Consistency:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Loss:&lt;/strong&gt; Data might be lost or corrupted due to inconsistencies between nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Conflicts:&lt;/strong&gt; Conflicting updates to the same data can occur, leading to inconsistencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Applications of Weak Consistency:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Voice over IP (VoIP):&lt;/strong&gt; While audio quality is important, occasional glitches or brief interruptions are often tolerated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiplayer Games:&lt;/strong&gt;
Real-time updates and responsiveness are prioritized over absolute consistency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Streams:&lt;/strong&gt; Slight delays or buffering are acceptable for a smooth viewing experience.
Cache Servers: Caches may contain stale data, but the goal is to provide fast access to frequently requested information.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Eventual Consistency:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fwjfolwc3wfjcm2ujsle3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fwjfolwc3wfjcm2ujsle3.png" alt="Eventual Consistency" width="765" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Eventual consistency is a relaxed consistency model that guarantees that all replicas of data will eventually converge to the same value if no new updates are made. In other words, while reads may return stale data temporarily, the system will eventually reach a consistent state.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Challenges of Eventual Consistency:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Debugging:&lt;/strong&gt; Identifying and resolving inconsistencies can be challenging, especially in complex distributed systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Loss:&lt;/strong&gt; In rare cases, data loss can occur due to network failures or synchronization issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Experience:&lt;/strong&gt; Stale data can negatively impact user experience, especially in applications that require real-time updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Applications of Eventual Consistency:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Content Delivery Networks (CDNs):&lt;/strong&gt; CDNs distribute content across multiple servers to improve performance and availability. Eventual consistency allows for quick updates to be propagated, but users might see slightly outdated content temporarily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email Systems:&lt;/strong&gt; Email delivery systems often use eventual consistency to ensure that emails are eventually delivered to their recipients, even if there are temporary network delays or server failures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Social Media Platforms:&lt;/strong&gt; Social media feeds often rely on eventual consistency to display updates quickly, even if a user's recent posts might not appear immediately on other users' timelines.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Choosing the right consistency pattern depends on your application's needs. Strong consistency guarantees accuracy but can be slow. Weak consistency offers high availability but may have temporary inconsistencies. Eventual consistency balances these concerns, ensuring data eventually becomes consistent. Understanding these patterns helps design efficient and reliable distributed systems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>systemdesign</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Popver API VS dialog Modal : Same Same but Different</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Tue, 24 Sep 2024 18:08:36 +0000</pubDate>
      <link>https://dev.to/decoders_lord/popver-api-vs-dialog-modal-same-same-but-different-2ig7</link>
      <guid>https://dev.to/decoders_lord/popver-api-vs-dialog-modal-same-same-but-different-2ig7</guid>
      <description>&lt;p&gt;I was reading through some tech news blogs and stumbled upon the heading &lt;a href="https://web.dev/blog/popover-api" rel="noopener noreferrer"&gt;Popover API lands in Baseline&lt;/a&gt;. I was confused, during my recent dive into front-end development, I recently with a very hard time getting accustomed to using  Elements in HTML. While going over the blog I was constantly confused as to how was I using the  element up until now. &lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Choose &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modal popups requiring user focus&lt;/li&gt;
&lt;li&gt;Accessibility and keyboard interaction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choose &lt;code&gt;popover&lt;/code&gt; for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non-modal popups with light-dismissal&lt;/li&gt;
&lt;li&gt;Easy implementation with minimal code&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element
&lt;/h2&gt;

&lt;p&gt;According to the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog" rel="noopener noreferrer"&gt;MDN The Dialog element&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The  HTML element represents a modal or non-modal dialog box or other interactive component, such as a dismissible alert, inspector, or subwindow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A  is generally used and displayed over the content when the website needs to draw the attention of the user to something important. i.e. Subscribing to a newsletter, requesting(more like forcing) to disable the adblocker, or accepting terms and conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element as Modal
&lt;/h2&gt;

&lt;p&gt;As you might have come across multiple times on multiple websites, some of these popups will be drawn on your entire screen while blurring the background or disabling the background and focusing the user only on the task at hand, the user must either dismiss(only if allowed) the popup or enter the required information for it to go away. This behavior is called the ' element as a modal'. These Modal  elements are shown at the top layer of the page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//To open dialog as a modal.&lt;/span&gt;

&lt;span class="nx"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showModal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// To close the dialog.&lt;/span&gt;

&lt;span class="nx"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; element when shown using the &lt;code&gt;showModal()&lt;/code&gt; method can be dismissed using the &lt;code&gt;esc&lt;/code&gt; key. Keyboard users expect such behaviour which needs to be maintained and is provided by the browser. If multiple modal dialogs are open, only the last dialog will be closed using the &lt;code&gt;esc&lt;/code&gt; key.&lt;/p&gt;

&lt;h2&gt;
  
  
   element as non-modal
&lt;/h2&gt;

&lt;p&gt;You might not always want to stop the user's natural flow of using your webpage, to stop doing everything else and focus on what you want to show but still your content, such as a toast notification, a cookie consent, or general tooltip info. should appear at the top layer of the page, above any other content that can or can not be interacted with by the user. These types of pop-ups are called non-modal pop-ups. Users can dismiss these manually or generally time and will disappear on their own. These non-modal dialogs are still shown at the top layer of the page but their priority can be controlled using the z-index and the modal  element will take a higher z-index than this and will make this non-accessible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//To open dialog as a modal.&lt;/span&gt;

&lt;span class="nx"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// To close the dialog.&lt;/span&gt;

&lt;span class="nx"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code Example
&lt;/h2&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/psevak/embed/GRbPdqg?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Some Issues
&lt;/h2&gt;

&lt;p&gt;I had hard time grasping the working and usage of non-modal  elements. According to me the non-modal  element behaved inconsistently and needed Javascript code to handle situations such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There's no light dismissal functionality. Clicking outside the  model will not close the .&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;esc&lt;/code&gt; key does not dismiss the  and needs Javascript to handle that scenario.&lt;/li&gt;
&lt;li&gt;need to manage z-index manually if you want to draw the  on top layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To my surprise &lt;code&gt;popover API&lt;/code&gt; answered or fixed these issues and more....&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;popover&lt;/code&gt; API
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;popover&lt;/code&gt; are attribute that can be added to any HTML attribute. Here's an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;popovertarget=&lt;/span&gt;&lt;span class="s"&gt;"mypopover"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Toggle the popover&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mypopover"&lt;/span&gt; &lt;span class="na"&gt;popover&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Popover content&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Main difference between &lt;code&gt;popover&lt;/code&gt; and &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element
&lt;/h2&gt;

&lt;p&gt;The main difference between the &lt;code&gt;popover&lt;/code&gt; and &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; elements is that &lt;code&gt;popover&lt;/code&gt; is always non-modal. The &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element comes with a &lt;code&gt;role=dialog&lt;/code&gt; attribute this &lt;code&gt;role&lt;/code&gt; attribute is attached to various HTML elements and behaves in a certain way. i.e. &lt;code&gt;h1&lt;/code&gt; has a &lt;code&gt;heading&lt;/code&gt; role &lt;code&gt;a&lt;/code&gt; has an anchor/Link role. This role is used to determine and help assistive technologies such as screen readers to determine the elements. However, the &lt;code&gt;popover&lt;/code&gt; is an attribute to an HTML element as it has no default &lt;code&gt;role&lt;/code&gt; attached to it. This helps the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; in the above example to be hidden until the button is clicked.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;popover&lt;/code&gt; attribute can be used with minimal code and while it can be controlled using Javascript it is not required at all times like the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;popover&lt;/code&gt; can have 2 characteristics:&lt;br&gt;
1.&lt;code&gt;popover=auto&lt;/code&gt;: Has functionality for light-dismissal and requires no JS interaction.&lt;br&gt;
2.&lt;code&gt;popover=manual&lt;/code&gt;: Needs Javascript interaction such as clicking a button or timer to explicitly close it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;popover&lt;/code&gt; is always shown at the top-layer no need to set z-index explicitly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code Example:
&lt;/h2&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/psevak/embed/YzoBvVW?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You can see I can achieve the same behavior with almost no Javascript code. Designing and managing various &lt;code&gt;popover&lt;/code&gt; is much easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some Design considerations
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;popover&lt;/code&gt; can have &lt;code&gt;: backdrop&lt;/code&gt; set using CSS which can be used to blur or grey out the background of the &lt;code&gt;popover&lt;/code&gt; but that does not take-away the light-dismissal functionality of it, and still user can click outside if the pop-up and interact with other elements of your web-page. You should be very careful while determining when to choose &lt;code&gt;popover&lt;/code&gt; over &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The main thing to consider here is: is the component being displayed the only thing that should have focus at the moment? can user be allowed to interact with anything else? &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, the  element and the popover API offer versatile options for creating interactive popups in your web applications. By understanding their distinct characteristics and use cases, you can make informed decisions to enhance user experience and streamline your development process.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.logrocket.com/comparing-popover-api-dialog-element/" rel="noopener noreferrer"&gt;Comparing the Popover API and the  element&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hidde.blog/dialog-modal-popover-differences/" rel="noopener noreferrer"&gt;Dialogs and popovers seem similar. How are they different?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/blog/popover-api" rel="noopener noreferrer"&gt;Popover API lands in Baseline&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>devjournal</category>
      <category>programming</category>
    </item>
    <item>
      <title>Salesforce Automation: Flow</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Mon, 23 Sep 2024 15:00:53 +0000</pubDate>
      <link>https://dev.to/decoders_lord/salesforce-automation-flow-248h</link>
      <guid>https://dev.to/decoders_lord/salesforce-automation-flow-248h</guid>
      <description>&lt;p&gt;I had a challenging task in front of me. I had recently worked on a user story in one of my sprints and one of my colleagues pinged me today telling me that there is a better and faster way to do this. Let me go over it with you to help you understand too.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;TL;DR:&lt;/strong&gt;
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem:&lt;/strong&gt; Needed to send automated emails based on Opportunity stage changes and owner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Initial Approach:&lt;/strong&gt; Writing Apex code triggers - complex and time-consuming.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Solution:&lt;/strong&gt; Using Salesforce Flow - more efficient and requires minimal coding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flow Steps:&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;Create Record-Triggered Flow for Opportunity object.&lt;/li&gt;
&lt;li&gt;Add "Decision" element to check for "Closed Won" stage.&lt;/li&gt;
&lt;li&gt;Create Email Templates for different scenarios.&lt;/li&gt;
&lt;li&gt;Use "Send Email Alert" action instead of "Send Email" due to recipient limitations.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Problem statement&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As a user/agent I need to send the update regarding the newly created opportunity to the opportunity owner. I need to email the opportunity owner regarding the current stage of the opportunity and who updated the stage. If the stage has been set to "Closed won" the owner should receive a congratulatory email with the opportunity amount mentioned in the email.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;My initial approach&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Being a traditional web developer my instinct falls towards coding out the solution. I quickly laid out the following solution and mailed my colleague to check if that was the correct approach or not.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an apex trigger for after insert and after update on the opportunity.&lt;/li&gt;
&lt;li&gt;Check for the current stage of the opportunity and determine which "email to be sent out"&lt;/li&gt;
&lt;li&gt;Set the email body and subject. &lt;/li&gt;
&lt;li&gt;Fetch the relative opportunity and their respective ownerId.&lt;/li&gt;
&lt;li&gt;Set the message ToAddress to the opportunity owner email address.&lt;/li&gt;
&lt;li&gt;send the email.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I knew there was some sharpening needed to my logic, so I approached my colleague. However, to my surprise, he responded with a laugh and said there is a much easier way that require almost no coding. &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Salesforce Flow Automation&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Salesforce could automate many tasks by using triggers, Process builders, and Flow. &lt;/p&gt;

&lt;p&gt;Here are the type of flows available in salesforce and when we can use them.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;REFERENCE: &lt;a href="https://trailhead.salesforce.com/content/learn/modules/flow-basics/get-started-with-flows" rel="noopener noreferrer"&gt;Trailhead FLow Builder Basics&lt;/a&gt;&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F8e1gwf8veg3tkif84cxc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8e1gwf8veg3tkif84cxc.png" alt="Flow Basics" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Renewed Approach: Record-Trigger Flow&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;1.Based on the options provided I quickly understood that I need to create &lt;strong&gt;Record-Trigger&lt;/strong&gt; flow and configure it as below: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fwfbvhnzkj0t0q23un9hv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fwfbvhnzkj0t0q23un9hv.png" alt="Configure Start" width="800" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Object field: let us specify which object the flow needs to be triggered on.&lt;/li&gt;
&lt;li&gt;We can trigger the flow: I have selected when &lt;strong&gt;"A record is created or updated"&lt;/strong&gt; as I need to send the email when the Opportunity is created and updated. &lt;/li&gt;
&lt;li&gt;Entry Condition: We can define entry condition which can determine whether to continue with the trigger or not. I can define conditions such as not triggering this flow if the opportunity amount is less than $1000.&lt;/li&gt;
&lt;li&gt;Optimize the flow: Basically lets you select whether you want to trigger the flow &lt;code&gt;before&lt;/code&gt; or &lt;code&gt;after&lt;/code&gt; the object is created/updated. For sending emails it is advised to select &lt;code&gt;after&lt;/code&gt; trigger.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2.I need to introduce a &lt;strong&gt;"decision"&lt;/strong&gt; in the flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F9iiy2mnwlrh5m0amrveo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F9iiy2mnwlrh5m0amrveo.png" alt="flow decision" width="800" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the &lt;strong&gt;"Outcomes"&lt;/strong&gt; section you can define which outcome should fire which event or flow. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Default outcome"&lt;/strong&gt; is something that will be followed if no other match is found.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"closed won"&lt;/strong&gt; I have introduced a new outcome here and determined based on the current stage of the opportunity in the conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3.Create Email Template &lt;strong&gt;"Classic Email Template"&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F2e889iimrisacc6chrvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2e889iimrisacc6chrvb.png" alt="Image description" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fp9f9kfjhkhnmykrmcjrl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fp9f9kfjhkhnmykrmcjrl.png" alt="Image description" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;We hit a snag!!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We need to understand the 2 ways we can send an email using the Flow. &lt;/p&gt;

&lt;p&gt;1.Using the Flow Action's &lt;strong&gt;"Send email Core Action"&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F1wwvs3jwek33quyv6pxy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F1wwvs3jwek33quyv6pxy.png" alt="Image description" width="625" height="810"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the easiest and quickest way to send an email. However, Salesforce has a strict rule to include &lt;strong&gt;"Recipient ID"&lt;/strong&gt; when using Email Template. and &lt;strong&gt;"Recipient ID"&lt;/strong&gt; can only be &lt;strong&gt;"Lead, Contact or person account"&lt;/strong&gt;, while I want to send the email to Opportunity owner.&lt;/p&gt;

&lt;p&gt;2.Using the &lt;strong&gt;"Email Alert"&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjfjuo46p564jvv0y8n8x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjfjuo46p564jvv0y8n8x.png" alt="Image description" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"Email Alerts" are part of Salesforce Process automation and can be set up on any type or object, even custom objects. We can also define the Email template we want to use and the and can also select Recipients. Thus, getting rid of the limit we faced in the Flow action and can directly use the Email alert in the flow. We need to create another action for "Closed won opportunity" selecting the "Closed won email template" and adding recipient as above.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Continue the flow creation:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;4.We can now go back to the flow we were working on and can now add &lt;strong&gt;"Send Email Alert"&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fynxbpojsv2w0ks6066kn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fynxbpojsv2w0ks6066kn.png" alt="Image description" width="643" height="811"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is also a straightforward way to send an email alert. We just need to make sure to select &lt;strong&gt;"Record ID"&lt;/strong&gt; so that it can be used inside the &lt;strong&gt;"Email Template Merge Fields"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;And that's it, at the end, your flow should look something like the below: &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F80vqh0tx4jl4c8z14sv2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F80vqh0tx4jl4c8z14sv2.png" alt="Image description" width="793" height="712"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;-Make sure you debug and save the flow. You also need to activate the flow to make sure the record change will trigger this flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Output&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, Whenever you Create a new opportunity and/or update the stage on the current opportunity you receive an email like below: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fdegv8tcu2x8zyh4z4e5l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fdegv8tcu2x8zyh4z4e5l.png" alt="Image description" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fns01nr45ip2nw67lg6g3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fns01nr45ip2nw67lg6g3.png" alt="Image description" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Salesforce Flow offers a powerful and low-code solution for automating tasks like sending emails based on record changes. By leveraging Flows, you can streamline processes and improve efficiency compared to traditional coding methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Reference:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;1.&lt;a href="https://trailhead.salesforce.com/content/learn/modules/flow-basics/get-started-with-flows" rel="noopener noreferrer"&gt;Flow Builder Basics Trailhead&lt;/a&gt;&lt;br&gt;
2.&lt;a href="https://youtu.be/t64XFNilvE0?si=Kc3YsruZX_0euGTN" rel="noopener noreferrer"&gt;Salesforce Geek on Youtube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>devjournal</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Leetcode: 624. Maximum Distance in Arrays</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Sat, 21 Sep 2024 02:55:16 +0000</pubDate>
      <link>https://dev.to/decoders_lord/leetcode-624-maximum-distance-in-arrays-20hi</link>
      <guid>https://dev.to/decoders_lord/leetcode-624-maximum-distance-in-arrays-20hi</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Problem Statement&lt;/strong&gt; &lt;a href="https://leetcode.com/problems/maximum-distance-in-arrays/description/" rel="noopener noreferrer"&gt;624. Maximum Distance in Arrays&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;You are given m arrays, where each array is sorted in ascending order.&lt;/p&gt;

&lt;p&gt;You can pick up two integers from two different arrays (each array picks one) and calculate the distance. We define the distance between two integers a and b to be their absolute difference |a - b|.&lt;/p&gt;

&lt;p&gt;Return the maximum distance.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;My Thought Process&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As the subarrays are sorted in ascending order, the first element will always be smallest and the last element will always be the largest. I came up with below algorithm:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mark the first element of the first subarray as min. and the last element of the first subarray as max.&lt;/li&gt;
&lt;li&gt;iterate over the array and check if the current subarray's first element is smaller than our min and the last element of the current subarray is higher than our max. replace min and max accordingly.&lt;/li&gt;
&lt;li&gt;return the difference between max and min.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My algorithm mainly succeeded but failed for the test case like below. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[[1,4],[0,5]]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;as you can see for our algorithm we are replacing min and max based on the current subarray and if both min and max elements exist in the same array we are returning incorrect answers as the problem statement specifically asks to choose elements from &lt;strong&gt;2 Different arrays&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I updated my algorithm as below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mark the first element of the first subarray as min. and the last element of the first subarray as max.&lt;/li&gt;
&lt;li&gt;iterate over the array and mark the current subarray's first element as localMin and the last element as localMax.&lt;/li&gt;
&lt;li&gt;find the difference between localMax and min, the difference between max and localMin. this will give us 2 absolute differences between 2 separate subarrays. &lt;code&gt;i.e. for [[1,2,3],[4,5]] this will be 4 and 1 respectively&lt;/code&gt; we need to select the maximum difference between these 2.&lt;/li&gt;
&lt;li&gt;find the maximum between the above calculated max difference and the previously calculated result. set the result to whichever is higher. &lt;/li&gt;
&lt;li&gt;return the result.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Output&lt;/strong&gt;
&lt;/h2&gt;


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


&lt;p&gt;&lt;a href="https://media2.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%2Fkruiv23ddkhtx5k0qydm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkruiv23ddkhtx5k0qydm.png" alt="624. Maximum Distance in Arrays" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Time and Space complexity&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time Complexity:&lt;/strong&gt; we iterate over all the elements in the array and can directly access the first and last elements and don't need to iterate inside the subarrays. so the time complexity will be &lt;code&gt;O(n)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity:&lt;/strong&gt; &lt;code&gt;O(1)&lt;/code&gt; as we do not need any additional space. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>leetcode</category>
      <category>devjournal</category>
      <category>programming</category>
    </item>
    <item>
      <title>DevOps: Understanding Process Monitoring on Linux</title>
      <dc:creator>Priyank Sevak</dc:creator>
      <pubDate>Thu, 19 Sep 2024 15:22:04 +0000</pubDate>
      <link>https://dev.to/decoders_lord/devops-understanding-process-monitoring-on-linux-42e0</link>
      <guid>https://dev.to/decoders_lord/devops-understanding-process-monitoring-on-linux-42e0</guid>
      <description>&lt;p&gt;As a DevOps engineer, ensuring system stability and performance is crucial. Occasionally, processes can go rogue, causing resource bottlenecks or unexpected behavior. Identifying these problematic processes requires effective monitoring techniques. Here's where Bash scripting and process monitoring tools like &lt;code&gt;ps&lt;/code&gt; and &lt;code&gt;lsof&lt;/code&gt; come in handy!&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Understanding Linux Process:&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;In Linux, everything that you run/use is a type of file. As soon as you start your system, the kernel creates an &lt;code&gt;init&lt;/code&gt; process, which every other process forks from.&lt;/p&gt;

&lt;p&gt;We need a forked system call to create/fork a new process. These new processes can be created as a child of an existing process. &lt;/p&gt;

&lt;p&gt;Suppose we have an existing child process. The child process will let the kernel know by setting its terminal status to &lt;strong&gt;0&lt;/strong&gt;. The parent needs to acknowledge the termination of the child process using something called a wait call. After all, we need the parent process to know that a child process has died. This exact operation can lead us to 2 possible issues: &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1.Orphan process:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;What happens if the parent process is exited/terminated before the child process? The children's process is left an orphan and is transferred over to the &lt;code&gt;init&lt;/code&gt; process and marked as &lt;strong&gt;"orphan"&lt;/strong&gt;. These processes now wait for &lt;code&gt;wait call&lt;/code&gt; from init to be terminated.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2.Zombie process: 🧟&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;What is a zombie? someone who is mindlessly running trying to eat human brains!! A MANACE. A zombie process is something similar, A process has gone zombie when the child process is terminated but the parent process has not called for &lt;code&gt;wait call&lt;/code&gt; yet. &lt;/p&gt;

&lt;p&gt;A zombie process' resources are freed up. However, the process still appears in the &lt;code&gt;ps&lt;/code&gt; table. You can't manually kill the zombie process, the entry of this process is cleared when the parent process eventually makes the &lt;code&gt;wait call&lt;/code&gt;.(Just like a real-world zombie you need to shoot it twice, in our case the second bullet needs to come from the parent process). &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Command use and output:&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Linux provides us with an in-built package called &lt;code&gt;procps&lt;/code&gt; which contains useful tools such as &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;iostat&lt;/code&gt;, etc. to help us in performance and process monitoring. I will discuss a couple of them here which are used for performance monitoring.&lt;/p&gt;

&lt;p&gt;1.&lt;code&gt;ps&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;ps aux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2F2a85dlqgngkhbnvz8uef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2a85dlqgngkhbnvz8uef.png" alt="Image description" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;a&lt;/code&gt; - list all processes even owned by other users&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;u&lt;/code&gt; - list more details regarding the process&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;x&lt;/code&gt; - list process that doesn't have TTY associated with them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2.&lt;code&gt;top&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Do you want to know which thread is consuming how much CPU, and memory? Which user or group executed the thread? &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;top&lt;/code&gt; command provides a dynamic real-time view of a running system. It can display a various type of information, such as from list of tasks currently being managed, Memory and CPU utilized by the current process, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fj6spwmuk47xd7xprsqa2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fj6spwmuk47xd7xprsqa2.png" alt="Image description" width="800" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;as displayed above running &lt;code&gt;top&lt;/code&gt; would list:&lt;br&gt;
The top part of the top command displays a summary of the current process running on the kernel.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PID (Process ID) - The task's unique process ID.&lt;/li&gt;
&lt;li&gt;USER - Task owner's username.&lt;/li&gt;
&lt;li&gt;PR - Scheduling priority of the task.&lt;/li&gt;
&lt;li&gt;NI - Nice value - A bit confusing but it simply shows the priority of the task within the same autogroup. A positive value means lower priority and a negative value means higher priority.&lt;/li&gt;
&lt;li&gt;VIRT - Virtual memory size - The total amount of virtual memory used by the task.&lt;/li&gt;
&lt;li&gt;RES - Resident memory size - Non-swapped physical memory a task is currently using. &lt;/li&gt;
&lt;li&gt;SHR - Shared memory size - Part of RES which can be utilized by other process.&lt;/li&gt;
&lt;li&gt;S - Process status.

&lt;ul&gt;
&lt;li&gt;   D - Uninterruptible sleep&lt;/li&gt;
&lt;li&gt;   I - Idle&lt;/li&gt;
&lt;li&gt;   R - Running&lt;/li&gt;
&lt;li&gt;   S - Sleeping&lt;/li&gt;
&lt;li&gt;   T - Stopped by job control signal&lt;/li&gt;
&lt;li&gt;   t - Stopped by debugger during trace&lt;/li&gt;
&lt;li&gt;   Z - Zombie&lt;/li&gt;
&lt;li&gt;   %CPU usage&lt;/li&gt;
&lt;li&gt;   %MEMORY usage&lt;/li&gt;
&lt;li&gt;   TIME - CPU time.&lt;/li&gt;
&lt;li&gt;   COMMAND - Command name or command line.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Everything is a file&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;One of the core principles of Linux is that everything is treated as a file. This means that not only traditional files like documents and images but also devices, network connections, and even processes are represented as files within the operating system. This unified approach simplifies system management and provides a consistent interface for interacting with various system components. By treating everything as a file, Linux allows for a more flexible and efficient way to handle and manipulate different types of resources.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lsof&lt;/code&gt; helps us to narrow down current open files (running process) and we can even sort it based on the ports, user, ipv4, ipv6, etc. The best way to learn about them is to use them. Here's the best resource I found: &lt;a href="https://neverendingsecurity.wordpress.com/2015/04/13/lsof-commands-cheatsheet/" rel="noopener noreferrer"&gt;lsof cheatsheet&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Real world example:&lt;/strong&gt;
&lt;/h1&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Problem statement:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine your server experiences performance issues. Users complain about slow applications, and resource usage is through the roof. You suspect a single process is to blame, but pinpointing it can feel like searching for a needle in a haystack.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Assumptions &amp;amp; lab setup&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before I go over the solution. Just as part of the setup in the lab environment, I have created a python code that runs infinitely generating some random numbers using the code below, This is just to create a process that is actually eating up a bunch of resources:&lt;br&gt;
&lt;/p&gt;

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

def calculate_something_complex():
    # Simulate a computationally intensive task
    result = 0
    for i in range(10000000):
        result += random.random()
    return result

def long_running_task():
    while True:
        result = calculate_something_complex()
        print(result)
        time.sleep(1)

if __name__ == "__main__":
    long_running_task()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before going any further we must define a basic flow of the solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Determine how to find which is the process eating up most of the resources? - using &lt;code&gt;top&lt;/code&gt; will be a very straightforward approach as it is purposefully used to list processes that are using most of the resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We do not only need the process ID but also list the files it is running to determine what can be the root cause. - &lt;code&gt;lsof&lt;/code&gt; is your answer to do this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We also need to be able to perform this task multiple times and probably automated based on a CRON job. - Writing a bash file that can be executed easily is a good option.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Solution &amp;amp; Explaination:&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Here's the code I came up with to get the CPU-intensive task and list the open files under that PID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

find_cpu_hog() {
top -b -n 1 | grep -A99 PID | grep -v COMMAND | head -n 1 | awk '{print $1}'

}

list_open_files() {
  pid="$1"
  lsof -p "$pid"
}

main() {
  cpu_hog_pid=$(find_cpu_hog)
  echo "$cpu_hog_pid"   

  if [ -z "$cpu_hog_pid" ]; then
    echo "No high CPU processes found."
    exit 0
  fi

  list_open_files "$cpu_hog_pid"
}

main

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

&lt;/div&gt;



&lt;p&gt;I believe the most important code above is&lt;/p&gt;

&lt;p&gt;&lt;code&gt;top -b -n 1 | grep -A99 PID | grep -v COMMAND | head -n 1 | awk '{print $1}'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Basically, what I am trying to do is get the top and manipulate it's result to get the process Id. Here's how in detail:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;top -b -n 1&lt;/code&gt;: this will get the CPU intensive process by running the top command in a batch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;grep -A99 PID&lt;/code&gt;: &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fsjabmll9bptnvgfnvkkn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fsjabmll9bptnvgfnvkkn.png" alt="Image description" width="800" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;if you have ran the &lt;code&gt;top&lt;/code&gt; command before you know that the top provides a very useful info. such as uptime, tasks, %CPU usage etc. read more here: &lt;a href="https://www.redhat.com/sysadmin/interpret-top-output" rel="noopener noreferrer"&gt;What the first five lines of Linux’s top command tell you&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;So to omit that data and only get the process table I am performing a &lt;code&gt;grep&lt;/code&gt; on PID and by -A99 I am getting everything after that.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;grep -v COMMAND&lt;/code&gt;: To omit the first line of the heading in the process table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;head -n 1&lt;/code&gt;: getting only the first line, Most CPU-intensive process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;awk '{print $1}'&lt;/code&gt;: getting the first argument of the output, PID. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running the above code with the Python script running in the background I get the below result. Looking at the output we can determine that we have a Python code running which is CPU-intensive, we can also pinpoint the user who is performing this. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fwbj0xkxptpwxa7o9czcn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fwbj0xkxptpwxa7o9czcn.png" alt="Image description" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Corrections and comments are welcome.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/priyanksevak" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>linux</category>
      <category>devjournal</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
