<?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: Abdulsalaam Noibi</title>
    <description>The latest articles on DEV Community by Abdulsalaam Noibi (@clericcoder).</description>
    <link>https://dev.to/clericcoder</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%2F960475%2F2de25dbe-272f-42fc-9d45-e9a673d05c95.jpeg</url>
      <title>DEV Community: Abdulsalaam Noibi</title>
      <link>https://dev.to/clericcoder</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/clericcoder"/>
    <language>en</language>
    <item>
      <title>My Portfolio is Alive: Built with React, Cloud Run, and Gemini 3.0</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Wed, 14 Jan 2026 13:19:05 +0000</pubDate>
      <link>https://dev.to/clericcoder/my-portfolio-is-alive-built-with-react-cloud-run-and-gemini-30-4ea4</link>
      <guid>https://dev.to/clericcoder/my-portfolio-is-alive-built-with-react-cloud-run-and-gemini-30-4ea4</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/new-year-new-you-google-ai-2025-12-31"&gt;New Year, New You Portfolio Challenge Presented by Google AI&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;Hi, I'm a Full Stack Developer with a passion for Cloud Architecture and Applied AI. For 2026, my goal wasn't just to update my CSS; I wanted to transform my portfolio from a static digital business card into an &lt;strong&gt;intelligent agent&lt;/strong&gt; that actively helps me get hired.&lt;/p&gt;

&lt;p&gt;I believe the future of web development is "Agentic"—where applications don't just display data but perform tasks. This portfolio is my proof of concept for that future, marking my transition from standard frontend development to building &lt;strong&gt;AI-First Cloud Applications&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Portfolio
&lt;/h2&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__cloud-run"&gt;
  &lt;iframe height="600px" src="https://portfolio-v2-1093096103222.us-central1.run.app"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;Note: If the embed above doesn't load immediately, please &lt;a href="https://portfolio-v2-1093096103222.us-central1.run.app" rel="noopener noreferrer"&gt;click here to view the live app&lt;/a&gt;&lt;/strong&gt;. &lt;strong&gt;Be sure to try the &lt;code&gt;Recruiter Mode&lt;/code&gt; button in the bottom right corner!)&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;I architected this application as a production-grade microservice, moving away from simple static hosting to a containerized environment on Google Cloud.&lt;/p&gt;

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

&lt;p&gt;I integrated &lt;strong&gt;Google's Gemini 3 Pro Preview&lt;/strong&gt; model directly into the React frontend using the &lt;code&gt;@google/generative-ai&lt;/code&gt; SDK.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recruiter Match:&lt;/strong&gt; When a user pastes a Job Description, I send a structured prompt to Gemini containing my portfolio data and the JD. The AI analyzes the fit and returns a formatted report explaining &lt;em&gt;why&lt;/em&gt; I am the right candidate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The PDF Generator:&lt;/strong&gt; I implemented a feature where Gemini generates a persuasive, custom cover letter in real-time, which is then compiled into a PDF using &lt;code&gt;jsPDF&lt;/code&gt; for the recruiter to download.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. The Infrastructure (Cloud Run)
&lt;/h3&gt;

&lt;p&gt;Instead of a basic static site, I built a custom Docker container:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stage 1:&lt;/strong&gt; Node.js builds the React artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 2:&lt;/strong&gt; Nginx (Alpine) serves the static files. I configured Nginx with &lt;code&gt;gzip&lt;/code&gt; compression and aggressive caching headers to ensure a perfect Lighthouse performance score.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment:&lt;/strong&gt; I used &lt;strong&gt;Google Cloud Build&lt;/strong&gt; to automate the container creation and deployed it to &lt;strong&gt;Google Cloud Run&lt;/strong&gt; as a serverless service.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. The Design
&lt;/h3&gt;

&lt;p&gt;To reflect the AI nature of the site, I built a "Living Neural Network" background using &lt;code&gt;tsparticles&lt;/code&gt;. The nodes connect dynamically as you move your mouse, visualizing the concept of "connecting the dots" between my skills and the job requirements. I used &lt;code&gt;Framer Motion&lt;/code&gt; for "Liquid UI" transitions, ensuring the AI analysis results spring onto the screen organically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools Used:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google AI Studio:&lt;/strong&gt; For prompt engineering and model selection (&lt;code&gt;gemini-3-pro-preview&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Cloud Run:&lt;/strong&gt; For hosting the containerized application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code AI Agents:&lt;/strong&gt; I utilized AI agents to scaffold the initial components and Nginx configurations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'm Most Proud Of
&lt;/h2&gt;

&lt;p&gt;I am most proud of the &lt;strong&gt;Instant Cover Letter Generator&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Most portfolios leave the hard work to the recruiter. My portfolio does the work for them. By combining Generative AI with client-side file manipulation, I turned a standard "Contact Me" interaction into a tangible productivity tool. It demonstrates that I don't just know how to use an API—I know how to solve real user problems with it.&lt;/p&gt;

&lt;p&gt;I'm also proud of the &lt;strong&gt;"Safe Mode" Nginx configuration&lt;/strong&gt; I developed. Getting React Router to work correctly with Docker/Nginx on Cloud Run (handling 404s on refresh) was a challenge but architecting a solid &lt;code&gt;conf.d&lt;/code&gt; injection strategy makes the app incredibly robust.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Powered by Google Gemini &amp;amp; Cloud Run&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
    <item>
      <title>Great Opportunity</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Wed, 07 Jan 2026 11:24:13 +0000</pubDate>
      <link>https://dev.to/clericcoder/great-opportunity-237m</link>
      <guid>https://dev.to/clericcoder/great-opportunity-237m</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/devteam" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&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%2Forganization%2Fprofile_image%2F1%2Fd908a186-5651-4a5a-9f76-15200bc6801f.jpg" alt="The DEV Team" width="800" height="800"&gt;
      &lt;div class="ltag__link__user__pic"&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%2Fuser%2Fprofile_image%2F264%2Fb75f6edf-df7b-406e-a56b-43facafb352c.jpg" alt="" width="400" height="400"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/devteam/join-the-new-year-new-you-portfolio-challenge-3000-in-prizes-feedback-from-google-ai-team-4e7g" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Join the New Year, New You Portfolio Challenge: $3,000 in Prizes + Feedback from Google AI Team (For Winners and Runner Ups!)&lt;/h2&gt;
      &lt;h3&gt;Jess Lee for The DEV Team ・ Jan 1&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devchallenge&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#googleaichallenge&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#career&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#gemini&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>career</category>
      <category>gemini</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Sun, 08 Dec 2024 09:46:15 +0000</pubDate>
      <link>https://dev.to/clericcoder/-fm8</link>
      <guid>https://dev.to/clericcoder/-fm8</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/clericcoder" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F960475%2F2de25dbe-272f-42fc-9d45-e9a673d05c95.jpeg" alt="clericcoder"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/clericcoder/mastering-trace-analysis-with-span-links-using-opentelemetry-and-signoz-a-practical-guide-52hm" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Mastering Trace Analysis with Span Links using OpenTelemetry and Signoz (A Practical Guide, Part 1)&lt;/h2&gt;
      &lt;h3&gt;Abdulsalaam Noibi ・ Oct 23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#python&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Mastering Trace Analysis with Span Links using openTelemetry and Signoz (A Practical Guide,Part 2)</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Thu, 24 Oct 2024 11:17:17 +0000</pubDate>
      <link>https://dev.to/clericcoder/mastering-trace-analysis-with-span-links-using-opentelemetry-and-signoz-a-practical-guidepart-2-1amc</link>
      <guid>https://dev.to/clericcoder/mastering-trace-analysis-with-span-links-using-opentelemetry-and-signoz-a-practical-guidepart-2-1amc</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/clericcoder/mastering-trace-analysis-with-span-links-using-opentelemetry-and-signoz-a-practical-guide-52hm"&gt;In the previous tutorial, we learnt how to use span links to track interactions within distributed systems&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this tutorial, we will look at how to implement Best Practices for Using Span Links and Advanced Use Cases&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Using Span Links in OpenTelemetry
&lt;/h2&gt;

&lt;p&gt;When dealing with complex distributed systems, choosing the right tracing strategy is essential for maintaining clarity and performance. &lt;/p&gt;

&lt;p&gt;In OpenTelemetry, the two primary tools at your disposal are parent-child relationships and span links. Let’s explore when and how to use span links effectively, especially in comparison to the more common parent-child relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. When to Use Span Links and Parent-Child Relationships
&lt;/h3&gt;

&lt;p&gt;Understanding when to use span links as opposed to parent-child traces is crucial for correctly mapping how your services communicate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parent-Child Relationship: The Standard Tracing Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Parent-child relationships in tracing are straightforward. If one service calls another, the trace creates a direct parent-child link between the two spans. The child span is dependent on the parent span, clearly showing the flow of operations.&lt;/p&gt;

&lt;p&gt;This model works well in &lt;strong&gt;synchronous operations&lt;/strong&gt;, where one task directly triggers another, and they follow a linear progression, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A user request triggers a function.&lt;/li&gt;
&lt;li&gt;The function calls a database.&lt;/li&gt;
&lt;li&gt;The database returns a response.&lt;/li&gt;
&lt;li&gt;Each of these actions would be a child span of the previous one, forming a neat, sequential trace.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Span Links&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In real-world systems, especially those using microservices or asynchronous processes, not all operations follow this neat, hierarchical flow. This is where span links become valuable.&lt;/p&gt;

&lt;p&gt;A span link allows you to connect two spans that may not follow a direct cause-and-effect pattern. For example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Asynchronous Tasks&lt;/strong&gt;: A message queue may send a request to a processing service, but you might also want to connect that request to the original service that triggered it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Batch Jobs&lt;/strong&gt;: You may have a system that processes data in batches, where multiple child jobs are linked back to a single trigger event, but these jobs don’t execute sequentially.&lt;/p&gt;

&lt;h3&gt;
  
  
  Processes Where Span Links Add Value:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Decoupled or Asynchronous Systems:&lt;/strong&gt;&lt;br&gt;
Where one process kicks off another, but there’s no direct call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiple Parents:&lt;/strong&gt; If multiple processes contribute to one result (e.g., data from several services aggregates into one report), span links allow you to connect all related spans.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Correlated Events:&lt;/strong&gt; Span links are ideal when you need to associate spans from different traces, such as when a failure in one service causes an error in another indirectly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Processes that makes Span Links Redundant:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Synchronous Operations:&lt;/strong&gt; If the relationship between tasks is direct and synchronous, span links can clutter your trace visualization without adding real value. In this case, stick to parent-child relationships for simplicity.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use Sampling Strategies with Span Links to optimize Tracing Performance:
&lt;/h3&gt;

&lt;p&gt;In high-traffic systems, not every span or link needs to be captured. &lt;strong&gt;Sampling&lt;/strong&gt; is a strategy where only a portion of the traces are recorded, ensuring you capture enough data for analysis without overwhelming your system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Head-Based Sampling:&lt;/strong&gt; This captures traces at the entry point (head) of your system. You can apply this to key services, ensuring span links are only created for high-priority or important traces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tail-Based Sampling:&lt;/strong&gt; This samples traces based on the outcome, such as capturing only traces that result in errors. You can use this to ensure span links are used in cases that are most likely to need deep investigation, such as failures.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Naming and Structuring Span Links for Clarity
&lt;/h3&gt;

&lt;p&gt;Good naming conventions and structured traces are important in order to have perfect observability data, especially when span links are involved.The name of a span should clearly describe what it represents. This becomes more important when using span links, as the relationship between spans is not always visually obvious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistent Naming Conventions:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use a consistent pattern for span names, such as including the &lt;strong&gt;service name, function, or action.&lt;/strong&gt; For example, a span for a payment processing service might be named &lt;code&gt;payment-service.processPayment&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indicate the Role of Linked Spans:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your span names, indicate the role of the linked span if relevant. For example, user-authentication.request could be linked to &lt;code&gt;session-creation.init&lt;/code&gt;, making the connection between them clear.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Group Related Spans:&lt;/strong&gt; group spans logically For instance, if multiple microservices contribute to one larger process, ensure that the span links and naming help identify which service is responsible for each part.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Document Link Reasons:&lt;/strong&gt; If possible, document why a span link exists, either in the trace itself (via metadata) or in your documentation. This can be as simple as a brief comment in the tracing code explaining the relationship between two spans.&lt;/p&gt;
&lt;h3&gt;
  
  
  Advanced Use Cases Error Tracking for using Span Links in your Applications
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How to Use Span Links to Trace Error Flows Between Services&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you're managing a complex web application with numerous microservices,each microservice is responsible for a different part of the user experience. &lt;/p&gt;

&lt;p&gt;A user might place an order, which triggers a payment service, an inventory service, and a shipping service. If an error occurs somewhere in this chain, it’s crucial to know where it happened and how it impacted other services. This is where span links come in.&lt;/p&gt;

&lt;p&gt;Span links allow you to connect traces that aren't in a direct parent-child relationship, but still have contextual relevance.using span links for error tracking, you can correlate the error in one service with the subsequent impact on other services, even if they don’t share a direct relationship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Case:&lt;/strong&gt; Let’s say your payment service encounters an error while trying to process a transaction, and this failure indirectly impacts the shipping service. Using a span link, you can create a relationship between the error span from the payment service and the span of the shipping service that detected the issue. &lt;/p&gt;

&lt;p&gt;This helps you visualize the flow of the error across services and understand its ripple effects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Example for Capturing and Linking Error Spans Across Microservices&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s look at how you might capture these errors using OpenTelemetry and create span links between them. Here’s a simple example using Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from opentelemetry import trace

# Initialize tracer
tracer = trace.get_tracer("order-service")

# Create a span in the payment service
with tracer.start_as_current_span("payment-processing") as payment_span:
    try:
        # Simulate a payment process that raises an error
        process_payment()
    except Exception as e:
        payment_span.record_exception(e)
        payment_span.set_status(trace.Status(trace.StatusCode.ERROR, str(e)))

        # Capture the error trace and create a span link
        error_link = trace.Link(payment_span.get_span_context())

# Now in the shipping service, you can link this error trace
with tracer.start_as_current_span("shipping-service", links=[error_link]) as shipping_span:
    # Handle the impact of the payment error here
    process_shipping()

&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%2F5jzhkgzxz8y9zj76tegr.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%2F5jzhkgzxz8y9zj76tegr.jpg" alt="Capturing Error using L&amp;lt;br&amp;gt;
Span Links" width="721" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explanation of the above code snippet&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The payment-processing span captures the error when the payment fails.&lt;br&gt;
A span link &lt;code&gt;(error_link)&lt;/code&gt; is created using the context of the payment-processing span.&lt;/p&gt;

&lt;p&gt;This link is then added to the shipping-service span, allowing you to trace how the payment error affects the shipping process.&lt;/p&gt;

&lt;p&gt;You can use tools like &lt;strong&gt;SigNoz&lt;/strong&gt; to visualize these errors, making it much simpler to identify the root cause of issues.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing Span Links in Complex Microservice Architectures
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Real-world Use Case: Using Span Links to Track Customer Interactions Across a Multi-Service Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s take a real-world scenario. Imagine an e-commerce platform where customer actions, like placing an order, are handled by several services: &lt;strong&gt;Order Service, Inventory Service, Payment Service, and Shipping Service.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A user placing a single order can generate multiple spans, one for each service.&lt;/p&gt;

&lt;p&gt;Now, these spans are usually arranged in a parent-child relationship, where the Order Service might be the parent of the Payment Service and so forth. But what if you want to track a more complex relationship? &lt;/p&gt;

&lt;p&gt;For example, if the Inventory Service independently checks stock levels after a payment confirmation, it’s not a direct child of the Payment Service. A span link allows you to connect these services directly, creating a more accurate picture of how your services interact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Span Links is important in Complex Architectures&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Span links give you the flexibility to capture these non-linear interactions, providing a comprehensive view of user actions that span across services. This is especially useful for troubleshooting user experiences, like a delayed shipment due to an inventory check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Span Links Enhance Observability in Serverless or Event-Driven Systems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In serverless or event-driven systems, services often interact in a decoupled manner events trigger actions without the services having direct knowledge of one another.&lt;/p&gt;

&lt;p&gt;For example, an event from a Payment Service might trigger an Inventory Update Service through an event bus. Since these services don’t have a parent-child relationship, tracing them with traditional methods can be challenging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How To Use Span Links for Serverless&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Span links can act as the glue between these disjointed services. When an event is generated from one service and consumed by another, you can create a span link that connects the original event's span with the consuming service’s span. &lt;/p&gt;

&lt;p&gt;This way, even if your serverless functions are running independently, you can still get the full story of an interaction.&lt;/p&gt;

&lt;p&gt;Example: Let’s say your Payment Service sends a message to a queue after processing a payment, and this message triggers a Stock Update Function in a serverless architecture. &lt;/p&gt;

&lt;p&gt;Here is a code snippet on how you could link these spans&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# In the Payment Service
payment_span = tracer.start_span("payment-succeeded")
# Send message to queue with payment_span's context

# In the Stock Update Function triggered by the message
stock_update_span = tracer.start_span(
    "stock-update",
    links=[trace.Link(payment_span.get_span_context())]
)

&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%2Fqd0042kipfui0o26evtl.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%2Fqd0042kipfui0o26evtl.png" alt="Tracing the flow of payment Processing" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this setup, you can trace the flow from the payment processing to the stock update, even though they operate asynchronously. &lt;/p&gt;

&lt;p&gt;When visualized, it becomes clear how different parts of your serverless application interact, improving your ability to diagnose bottlenecks or unexpected delays.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is this approach important for Observability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Traditional monitoring might show you that a stock update was slow, but with span links, you can trace that delay back to the specific payment event that triggered it. &lt;/p&gt;

&lt;p&gt;This level of insight is invaluable for optimizing your system and ensuring a smooth user experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recap of Key Learnings:
&lt;/h3&gt;

&lt;p&gt;Span links are a powerful underutilized feature of OpenTelemetry that can significantly enhance trace correlation in distributed systems. &lt;/p&gt;

&lt;p&gt;But what exactly does that mean, and why should you care?&lt;/p&gt;

&lt;p&gt;Imagine your application as a network of different services and processes, all communicating and working together to fulfill user requests.you will often encounter scenarios where a straightforward parent-child relationship between traces doesn’t quite capture the complexity of what’s happening.&lt;/p&gt;

&lt;p&gt;For instance, what if a background job is processing events triggered by a user action, or multiple services are working together asynchronously? This is where span links comes in to solve the challenge easily.&lt;/p&gt;

&lt;p&gt;So, what are the benefits of using span links?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Relating Spans Beyond Parent-Child Constraints:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Span links allow you to connect traces across services without being bound by the typical hierarchical structure of parent and child spans. &lt;/p&gt;

&lt;p&gt;This is particularly useful when you want to relate events that occur concurrently or share a common context but don’t have a direct parent-child relationship. For example, linking a trace from a user-facing service to a background process can give you a more holistic view of how user actions impact system performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It helps to improve Debugging and Troubleshooting:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;With span links, you gain a richer perspective on how different services interact, especially during complex workflows. By seeing which spans are related through links, you can identify bottlenecks, error patterns, or performance issues that might be difficult to spot otherwise. This makes span links a powerful tool for debugging issues that span multiple services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It provides Better Visibility in Asynchronous Systems:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;For applications that rely on asynchronous processing, such as those using message queues or event-driven architectures, span links are invaluable. &lt;/p&gt;

&lt;p&gt;They allow you to trace the lifecycle of a task or message as it flows through different services. This can help you understand the impact of a single event across your entire system, making it easier to optimize and refine your processes.&lt;/p&gt;

&lt;p&gt;In short, span links allow you to create a more connected and meaningful picture of your application’s behavior, leading to better observability and a deeper understanding of how your distributed systems operate.&lt;/p&gt;

&lt;p&gt;By leveraging span links effectively, you can enhance trace correlation, making troubleshooting faster and providing a more complete view of your system's performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Links to Relevant OpenTelemetry Documentation for Span Links
&lt;/h3&gt;

&lt;p&gt;For those looking to go deeper into the official guidance on span links and related concepts, the following resources will be valuable for your research:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://opentelemetry.io/docs/specs/otel/trace/api/" rel="noopener noreferrer"&gt;OpenTelemetry Span Links Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the go-to reference for understanding how to create and manage span links. It covers the API specifications for linking spans, with examples in various supported programming languages. It’s a great starting point for understanding the technical details of how span links work under the hood.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://opentelemetry.io/docs/concepts/context-propagation/" rel="noopener noreferrer"&gt;OpenTelemetry Context Propagation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Understanding context propagation is key to making the most of span links, and this documentation provides a thorough overview of how context is managed across traces. It’s especially helpful if you’re looking to ensure consistency in your tracing data across distributed services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://opentelemetry.io/docs/concepts/sampling/" rel="noopener noreferrer"&gt;OpenTelemetry Sampling Strategies&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When implementing span links, it's crucial to know how sampling affects your traces. This section of the documentation provides detailed guidance on how to configure different sampling strategies, helping you strike the right balance between data granularity and performance.&lt;/p&gt;

&lt;p&gt;These links are valuable resources for both reference and practical application, making them essential for anyone serious about mastering OpenTelemetry's tracing capabilities. Bookmark these resources and use them as a guide as you build out more complex observability setups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;If you have questions or further explanation, kindly share them in the comments sections.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>opensource</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
    <item>
      <title>Mastering Trace Analysis with Span Links using OpenTelemetry and Signoz (A Practical Guide, Part 1)</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Wed, 23 Oct 2024 14:00:04 +0000</pubDate>
      <link>https://dev.to/clericcoder/mastering-trace-analysis-with-span-links-using-opentelemetry-and-signoz-a-practical-guide-52hm</link>
      <guid>https://dev.to/clericcoder/mastering-trace-analysis-with-span-links-using-opentelemetry-and-signoz-a-practical-guide-52hm</guid>
      <description>&lt;h2&gt;
  
  
  Purpose of This Tutorial
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The purpose of this Tutorial is to provide a practical and easy-to-understand guide on span links in OpenTelemetry.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It aims to help developers, especially those working with complex and asynchronous systems, understand what span links are, how they differ from traditional parent-child relationships in tracing, and why they are valuable for better trace correlation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;By the end of this guide, you will gain the skills needed to effectively use span links to track interactions within distributed systems, leading to improved observability and debugging.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Brief Introduction to Distributed Tracing
&lt;/h2&gt;

&lt;p&gt;In the past, Applications were typically monolithic, meaning every process or feature is executed as a single unit on one server.Monitoring such applications was straightforward.&lt;/p&gt;

&lt;p&gt;For Example: if something went wrong, you could look at logs from that server to identify the problem. However, the rise of microservices changed this simplicity.&lt;/p&gt;

&lt;p&gt;Now, modern applications are often made up of dozens or even hundreds of smaller, independent services that work together. For example: when you use a mobile app to place an order, there might be separate services to handle user authentication, process payments, manage inventory, and send confirmation emails.&lt;/p&gt;

&lt;p&gt;These services don’t always live on the same server and can even communicate over the internet, which adds complexity to tracking what happens when you interact with an application.&lt;/p&gt;

&lt;p&gt;This is where distributed tracing comes in. Think of distributed tracing as a way to follow a single request as it travels through various services in a complex application.It tracks the journey of a request through a complex system. &lt;/p&gt;

&lt;p&gt;In modern applications, requests often travel through multiple services, each running on different machines. Distributed tracing helps us visualize this journey, making it easier to identify bottlenecks and errors.&lt;/p&gt;

&lt;p&gt;It’s like a detective’s map that connects the dots between each step of the process, showing you how long each part took and where any issues occurred. When you look at a trace, you see a timeline of how your request moved through different services, making it easier to identify slowdowns, errors, or failures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Repo&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/Noibisjunior/Span-Links-in-OpenTelemetry" rel="noopener noreferrer"&gt;Here’s the code repo for this tutorial&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The Role of OpenTelemetry in Modern Observability
&lt;/h3&gt;

&lt;p&gt;OpenTelemetry is a key player in enabling this kind of visibility. It’s an open-source observability framework that allows developers to collect data like logs, metrics, and traces from their applications.It serve as a toolset for capturing detailed information about what’s happening inside your services.&lt;/p&gt;

&lt;p&gt;In the world of modern observability, OpenTelemetry helps you understand the performance and health of your distributed applications. It acts like a bridge that gathers data from various services and sends it to tools like &lt;strong&gt;SigNoz&lt;/strong&gt;, where you can visualize what’s going on. This makes OpenTelemetry invaluable for identifying bottlenecks, tracking down errors, and ensuring that your applications run smoothly.&lt;/p&gt;

&lt;p&gt;By using OpenTelemetry with distributed tracing, you can get a full picture of how your applications behave, making it easier to diagnose issues and improve the user experience.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Significance of spans as a building blocks for tracing in OpenTelemetry
&lt;/h3&gt;

&lt;p&gt;As software, especially distributed systems grow in complexity, understanding their inner workings becomes a challenging task. That's where OpenTelemetry's spans come in to solve the challenge easily.&lt;/p&gt;
&lt;h3&gt;
  
  
  What Are Spans?
&lt;/h3&gt;

&lt;p&gt;A span is a fundamental unit of work in OpenTelemetry’s tracing system.It is a single operation or event that occurs within your application. &lt;/p&gt;

&lt;p&gt;It captures what happened during that operation, how long it took, and any relevant details, like whether it succeeded or failed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For example, imagine your application processes a user request:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the request comes in, OpenTelemetry creates a span that represents the request being received.&lt;/li&gt;
&lt;li&gt;If the request then triggers a database query, another span is created to represent that database interaction.&lt;/li&gt;
&lt;li&gt;If the app calls another service, another span tracks that.&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%2Funbby9xtip2m5t85f70e.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%2Funbby9xtip2m5t85f70e.jpg" alt="Architectural Diagram showing how span works" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key attributes of a span:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Name: A descriptive label for the operation (e.g., "Get User Data").&lt;/li&gt;
&lt;li&gt;Start and End Timestamps: The time the operation began and ended.&lt;/li&gt;
&lt;li&gt;Parent Span: The span that initiated this operation.&lt;/li&gt;
&lt;li&gt;Tags: Additional metadata (e.g., HTTP status code, error messages).&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  How Spans Work Together to Create Traces
&lt;/h3&gt;

&lt;p&gt;Individually, spans are useful, but they are effective when they work together to form a trace. &lt;/p&gt;

&lt;p&gt;A trace is a collection of spans that represents the entire journey of a request or operation as it flows through your system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s go back to our user request example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The trace begins when the request enters the system, and a root span is created.As the request triggers the database query, the database interaction span is linked to the root span, showing that it’s part of the same process.&lt;/p&gt;

&lt;p&gt;Additional spans for calling other services get added to the trace.By looking at this trace, you can see the big picture of how the request traveled through different parts of your system. It helps you understand not just what happened, but how different parts of your application are connected.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Are Spans Important?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pinpointing Problems&lt;/strong&gt;: Spans help you zoom in on where things go wrong. If a request is slow, spans can tell you whether it’s the database query, the network call, or some other part of the process that’s causing the delay. You can see which span took longer than expected, making it easier to find bottlenecks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Building Context&lt;/strong&gt;: Each span contains contextual information like start time, end time, and custom labels (attributes). This data provides insights into what was happening at a particular moment in your system, like the specific user ID involved in a request or the query that was executed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Creating Relationships&lt;/strong&gt;: Spans have relationships with one another, often in a parent-child structure. The root span is the parent, and subsequent spans are its children. This structure helps you see the order in which events occurred and how they depend on one another. It’s like looking at a family tree of operations in your app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging Distributed Systems&lt;/strong&gt;: For applications with microservices (where different services handle different parts of a request), spans are especially crucial. They help you track a request as it moves between services, even if those services are running on different servers or in different data centers. This is key for understanding complex interactions between services.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Understanding Span Links in OpenTelemetry
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What Are Span Links?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the world of distributed systems, where multiple services work together to handle a user request, tracing is like a detective's map, it shows the path a request takes as it moves through these services. Each activity in this journey is called a span, and a complete journey is called a trace.&lt;/p&gt;

&lt;p&gt;Traditionally, spans are connected using parent-child relationships. Imagine these like a family tree: a parent span initiates a process (like making a request to another service), and child spans represent the activities that happen as a result (like the service processing the request). This is a straightforward way to represent a request’s flow.&lt;/p&gt;

&lt;p&gt;But what happens when two spans are related, yet they don’t fit perfectly into that parent-child hierarchy? This is where span links comes in.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;span link&lt;/strong&gt; allows you to connect two spans that are related but don’t have a direct parent-child relationship. It  is like a “reference” or “shortcut” between two activities in a distributed system. &lt;/p&gt;

&lt;p&gt;For example, let’s say you have a user making a request that triggers multiple independent processes, like sending an email and writing to a database. These processes aren’t child activities of each other; they happen side by side. Using a span link, you can indicate that the email sending span and the database writing span are related to the same initial user request, even though they aren’t directly connected in the parent-child concept.&lt;/p&gt;
&lt;h3&gt;
  
  
  How Span Links Differ from Parent-Child Relationships
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Parent-Child Relationship&lt;/strong&gt;: it is a straightforward chain of events. A user sends a request (parent), which triggers the creation of a record in a database (child). The child span wouldn’t exist without the parent span, making it a direct consequence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Span Links&lt;/strong&gt;: These are more like drawing dotted lines between activities that are related in some context but don’t follow a direct chain of actions. They provide a way to say, “These things are related, even though one didn’t directly cause the other.” Span links are ideal for representing parallel activities or events that interact but aren’t strictly hierarchical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importance of Span Links in Complex and Asynchronous Systems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Span links are particularly valuable in complex and asynchronous systems, where the flow of events doesn’t always follow a clear parent-child path. Here are some scenarios of how it can be used practically;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Asynchronous Workflows:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a user request that starts with a background job (like generating a report). The initial request finishes, but the report generation continues in the background.&lt;/p&gt;

&lt;p&gt;With the implementation of span links, you can relate the initial request span to the background job span, even though they don’t follow a direct parent-child pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Microservice Communication:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;In a microservices architecture, services often communicate with each other in ways that aren’t strictly hierarchical. &lt;/p&gt;

&lt;p&gt;For instance, a user action could trigger multiple services to process different parts of the data simultaneously. Span links allow you to track these independent and related spans as part of a broader workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Batch Processing:&lt;/strong&gt; If you’re processing batches of data where each item in the batch generates its own spans, you can use span links to connect these spans back to the original batch process. &lt;/p&gt;

&lt;p&gt;This makes it easier to trace the entire lifecycle of a batch and understand how individual items relate back to the main process.&lt;/p&gt;
&lt;h3&gt;
  
  
  Prerequisites: Tools and Libraries required to Configure Span Links using OpenTelemetry and Signoz
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;OpenTelemetry SDK: The OpenTelemetry SDK (Software Development Kit) is your toolkit for gathering observability data like traces, metrics, and logs from your application.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It acts as a bridge between your code and observability systems, making it possible to collect detailed information about how your application is running.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Imagine OpenTelemetry as a “camera” that captures snapshots of your application's operations. By integrating the SDK into your app, you’re positioning this camera to record what’s happening behind the scenes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’ll need to install the SDK in your application’s programming language (e.g., Python, Java, JavaScript). &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(2) SigNoz Setup: SigNoz is an open-source observability tool that allows you to visualize and analyze the data you collect with OpenTelemetry.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Think of SigNoz as the “control room” where you view the footage captured by your OpenTelemetry setup. It’s where you have a clear picture of traces and metrics in your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’ll need to set up a SigNoz instance, which involves deploying it on your local machine or on a server, usually using Docker or Kubernetes. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SigNoz helps transform the raw data into visualizations, like graphs and charts, making it easier to understand what's happening inside your application.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Basic Knowledge of Traces, Spans, and Instrumenting Code:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Traces:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In simple terms, a trace is like a “story” of what happens when a user or a request interacts with your application. It captures all the actions that occur as a result of that interaction, from the initial request to all the services and databases that might be involved.&lt;/p&gt;

&lt;p&gt;Imagine a user clicking a button on your website. A trace would record every step of what happens next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spans:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spans are the “chapters” within a trace's story. Each span represents a specific operation or task that takes place as part of a trace.&lt;/p&gt;

&lt;p&gt;For instance, if the trace captures the entire process of a user request, a span could represent a single step, like querying the database or calling an external API.&lt;/p&gt;

&lt;p&gt;Each span has a start and end time, giving you precise details about how long each step took. This makes it easier to pinpoint any slowdowns or errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instrumenting Code with OpenTelemetry:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instrumentation is the process of adding code to your application to collect observability data. By instrumenting your code with OpenTelemetry, this typically involves adding a few lines of code where you want to create traces and spans. &lt;/p&gt;

&lt;p&gt;For example, you might instrument a database query to see how long it takes or instrument a user login process to track its performance.&lt;/p&gt;

&lt;p&gt;The OpenTelemetry SDK makes this easier by providing libraries and functions that you can integrate directly into your code. Think of it like attaching trackers to parts of a machine to monitor how they work together.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating Span Links in Python: Step-by-Step Example
&lt;/h3&gt;

&lt;p&gt;Let’s look at a basic example in Python. We’ll use the OpenTelemetry SDK to create two spans and link them together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from opentelemetry import trace
from opentelemetry.trace import Link
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter

# Set up the tracer provider and span exporter

trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
span_processor = SimpleSpanProcessor(ConsoleSpanExporter())
trace.get_tracer_provider().add_span_processor(span_processor)

# Create the first span, simulating some work being done 

with tracer.start_as_current_span("span_one") as span_one:
    span_one.add_event("Processing order")
 order_id = "12345" # Imagine this as an order ID we're processing

# Create a second span with a link to the first span 

with tracer.start_as_current_span("span_two", links=[Link(span_one.get_span_context())]) as span_two:
        span_two.add_event("Updating order status")

# Simulate some additional work here

  print("Order ID: {order_id} has been updated.")

print("Tracing complete")

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation of the Above Python Code Snippet&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Set Up the Tracer Provider:&lt;br&gt;
The above code snippet begins with a &lt;code&gt;tracer provider&lt;/code&gt;, which manages the creation of spans.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is essential for OpenTelemetry to know how to handle spans.We also configure a &lt;code&gt;SimpleSpanProcessor&lt;/code&gt; and &lt;code&gt;ConsoleSpanExporter&lt;/code&gt; to print span data to the console. This helps us see what type of spans that are being created and how they’re linked&lt;br&gt;
.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;(2) Create the First Span (span_one):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;tracer.start_as_current_span method&lt;/code&gt;, we create a span called &lt;code&gt;span_one&lt;/code&gt;. This could represent any action, like processing an order.&lt;/p&gt;

&lt;p&gt;Inside this span, we add an event &lt;code&gt;Processing order&lt;/code&gt; to indicate what’s happening at that particular point in time.&lt;/p&gt;

&lt;p&gt;We also simulate an order ID &lt;code&gt;(order_id = "12345")&lt;/code&gt; that would be used in the next span.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(3) Create the Second Span with a Link &lt;code&gt;(span_two)&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here, we initiated another span called &lt;code&gt;span_two&lt;/code&gt; to represent a different, but related action—like updating the status of the order.&lt;br&gt;
Notice the links parameter.We use &lt;code&gt;Link(span_one.get_span_context())&lt;/code&gt; to create a link between span_two and span_one. &lt;/p&gt;

&lt;p&gt;This tells OpenTelemetry, "While these actions aren't parent-child, they are related."&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;span_two&lt;/code&gt;, we added another event, &lt;code&gt;Updating order status&lt;/code&gt;, and simulate some work like updating an order status in a database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(4) Output:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you run this code, you’ll see output in the console from the &lt;code&gt;ConsoleSpanExporter&lt;/code&gt; that shows both spans, along with the link between them. This helps visualize how these two spans relate to each other in a trace.&lt;/p&gt;
&lt;h3&gt;
  
  
  Common Errors to watch out for and How to Troubleshoot the Errors.
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;(1) Missing Span Contexts:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error:&lt;/strong&gt; If you try to create a link without calling &lt;code&gt;span_one.get_span_context()&lt;/code&gt;, you’ll get an error because OpenTelemetry requires a valid span context to create a link.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Always ensure that you are passing a span context when creating a link. Use the &lt;code&gt;.get_span_context()&lt;/code&gt; method of an active span.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(2) Linking Unstarted or Ended Spans:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error:&lt;/strong&gt; If you attempt to create a link to a span that hasn’t been started or has already ended, you might run into issues where the link is not recognized.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Make sure that the span you’re linking to is active when you create the link. Creating links with spans that have already ended can cause unexpected behavior in how traces are displayed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(3) Performance Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance Issue&lt;/strong&gt;: Linking too many spans can increase the overhead of trace data, leading to performance degradation in high-traffic systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Use links selectively. Only link spans when there is a meaningful relationship that you need to visualize or analyze. For high-traffic environments, you can use OpenTelemetry’s sampling options to reduce the amount of trace data being captured.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuring SigNoz for Span Link Visualization
&lt;/h3&gt;

&lt;p&gt;When working with distributed systems, understanding how different parts of your system communicate is crucial. &lt;strong&gt;Span links in OpenTelemetry&lt;/strong&gt; play a vital role in connecting traces that may not have a direct parent-child relationship, providing a clearer picture of how requests flow through your services. &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%2Fsnf21ich3v34yl5kuw7b.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%2Fsnf21ich3v34yl5kuw7b.jpg" alt="Architectural Diagram showing the relationship of different span triggered by the users" width="729" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Visualizing Span Links Matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine your application has a payment service that triggers a notification service when a payment is successful. While these services interact, they might not share a direct parent-child relationship. &lt;/p&gt;

&lt;p&gt;Span links allow you to relate these interactions, showing that the payment triggered the notification. Visualizing these links helps you see the bigger picture of how independent services correlate in real time.&lt;/p&gt;

&lt;p&gt;By setting up SigNoz to visualize these span links, you can gain deeper insights into your application's behavior. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s how you can configure SigNoz to Capture and View Span Links&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Ensure SigNoz is Properly Installed&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To begin, make sure you have SigNoz installed and running on your local environment or in a cloud setup. SigNoz can be deployed using Docker for easy setup. &lt;/li&gt;
&lt;li&gt;If you haven’t done this yet, follow the official SigNoz installation guide for your operating system [&lt;a href="https://signoz.io/docs/introduction" rel="noopener noreferrer"&gt;https://signoz.io/docs/introduction&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;Once installed, access the SigNoz UI by navigating to &lt;a href="http://localhost:3301" rel="noopener noreferrer"&gt;http://localhost:3301&lt;/a&gt; in your web browser. This interface is where you’ll configure settings and visualize your trace data, including span links.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Configure OpenTelemetry SDK to include your Span Links&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next step is to ensure that your OpenTelemetry SDK is configured to send span link data to SigNoz.In your application's code, you’ll need to add span links as part of your tracing logic.&lt;/p&gt;

&lt;p&gt;Here’s a code snippet in Python programming language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from opentelemetry import trace
from opentelemetry.trace import SpanKind, Link
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter

# Set up the tracer provider and add a span processor

trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)

# Configure the exporter to send spans to SigNoz using the OTLP exporter

otlp_exporter = OTLPSpanExporter(endpoint="http://localhost:4317", insecure=True)
span_processor = BatchSpanProcessor(otlp_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)

# Create two spans, linking the second span to the context of the first

with tracer.start_as_current_span("parent_span") as parent_span:

# Simulate some logic for the parent_span
    print("Parent span is active")

# Get the context of the parent span
parent_context = parent_span.get_span_context()

# Create a linked span and add a link to the parent span's context

with tracer.start_as_current_span(
        "linked_span",
        links=[Link(parent_context)]
    ) as linked_span:

 # Simulate some logic for the linked_span
        print("Linked span is active")

# Ensure all spans are flushed before exiting the application

trace.get_tracer_provider().shutdown()

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation of the above python code snippet&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;We started by configuring the &lt;code&gt;TracerProvider&lt;/code&gt; to handle tracing in our application and set up a span processor.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;OTLPSpanExporter&lt;/code&gt; is used to send spans to SigNoz’s backend using the &lt;strong&gt;OTLP protocol.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;http://localhost:4317&lt;/code&gt; with the appropriate SigNoz endpoint if you are not running SigNoz locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Secondly, Creating Spans and Links:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;parent_span&lt;/code&gt; is created first, representing an initial operation (e.g., a user request).We extract the context of the parent_span using &lt;code&gt;get_span_context()&lt;/code&gt;, which allows us to link another span to it.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;linked_span&lt;/code&gt; is then created, and a Link is added to reference the &lt;code&gt;parent_span&lt;/code&gt;’s context. This signifies that while the &lt;code&gt;linked_span&lt;/code&gt; is not a direct child of parent_span, it is related to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lastly, Sending Data to SigNoz:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The span data is processed using the &lt;code&gt;BatchSpanProcessor&lt;/code&gt;, which ensures that span data is sent to SigNoz efficiently.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;trace.get_tracer_provider().shutdown()&lt;/code&gt; is called at the end to ensure that any remaining spans are flushed and exported before the program exits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Update SigNoz Configuration for Tracing Data&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To ensure that SigNoz captures span links, you might need to change some settings in your SigNoz collector configuration file. &lt;/li&gt;
&lt;li&gt;The collector acts as a middleman that receives trace data from &lt;strong&gt;OpenTelemetry&lt;/strong&gt; and sends it to &lt;strong&gt;SigNoz’s backend.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Locate the OpenTelemetry Collector configuration file, often named &lt;strong&gt;otel-collector-config.yaml&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Add or update the processors and exporters sections to ensure trace data is correctly forwarded. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;processors:
  batch:
    timeout: 5s

exporters:
  otlp:
    endpoint: "signoz-backend:4317"
    insecure: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp]

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Visualize Span Links in SigNoz&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once your application is sending trace data with span links to SigNoz, you can visualize these links by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opening the Trace Explorer in the SigNoz UI.&lt;/li&gt;
&lt;li&gt;Search for traces related to the services you’re monitoring (e.g., the payment service and the notification service).&lt;/li&gt;
&lt;li&gt;In the trace details view, you’ll see a graphical representation of spans, including any links between spans. Linked spans will appear as additional connections between nodes that don’t share a direct parent-child line.&lt;/li&gt;
&lt;li&gt;This visualization helps you see how requests flow through your system, even when the services don’t have a strict hierarchical relationship.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Adjust Your View for Clarity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to have perfect visualization, you need to take note of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use filters in SigNoz to narrow down trace data to specific services or time periods.&lt;/li&gt;
&lt;li&gt;Create custom dashboards to track specific span links if you’re frequently monitoring certain interactions.&lt;/li&gt;
&lt;li&gt;Set up alerts in SigNoz to notify you when linked spans indicate potential issues, such as delays between related services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Next Steps&lt;/strong&gt;&lt;br&gt;
In this tutorial, we learnt how to use span links to track interactions within distributed systems&lt;/p&gt;

&lt;p&gt;In the next &lt;a href="https://dev.to/clericcoder/mastering-trace-analysis-with-span-links-using-opentelemetry-and-signoz-a-practical-guidepart-2-1amc"&gt;tutorial&lt;/a&gt;, we will learn the Best Practices for Using Span Links and Advanced Use Cases&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>python</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>#DEVResolutions2024</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Thu, 11 Jan 2024 06:53:56 +0000</pubDate>
      <link>https://dev.to/clericcoder/devresolutions2024-11f1</link>
      <guid>https://dev.to/clericcoder/devresolutions2024-11f1</guid>
      <description>&lt;h2&gt;
  
  
  Professional Goals:
&lt;/h2&gt;

&lt;p&gt;Happy 2024!&lt;/p&gt;

&lt;p&gt;1a.My #DEVResolutions2024 is become a Top 1% Back end Developer &lt;/p&gt;

&lt;p&gt;2b.Get A Technical Writing Job&lt;/p&gt;

&lt;p&gt;2a. Action Steps: I  am currently taking a  back end developer course on Udemy&lt;/p&gt;

&lt;p&gt;2b. I am already prepared for this Job,Here is my Writing Portfolio clericcoder.hashnode.dev&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Timeline: 6 months to achieve my Back end Mastery&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Personal Aspirations:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Aspiration: I am aspiring to work at Andela as a a Software Engineer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why it Matters: This Aspiration is important to me because it would make me achieve my career Goals&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  DEV Community Contributions:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Contribution Goal: I would contribute to the dev community by writing Articles based on my back end developer journey (my learning process)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Collaboration Plans: I am looking forward to collaborate with other Developer Community on Social Media (Twitter,Reddit).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>5 Essential Tips for Junior Developers: Advice I Wish I Knew When I Started</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Fri, 12 May 2023 07:37:40 +0000</pubDate>
      <link>https://dev.to/clericcoder/5-essential-tips-for-junior-developers-advice-i-wish-i-knew-when-i-started-4f23</link>
      <guid>https://dev.to/clericcoder/5-essential-tips-for-junior-developers-advice-i-wish-i-knew-when-i-started-4f23</guid>
      <description>&lt;p&gt;I wish I knew these advices when I started as a Junior developer 😮🙌 &lt;/p&gt;

&lt;p&gt;Here are, 5 advices that a junior developer should inherit 🙂💯&lt;/p&gt;

&lt;p&gt;As a fresher or junior developer struggle in making decisions or be confident on what we do.&lt;/p&gt;

&lt;p&gt;Follow this advice given by my Seniors that you can inherit if you are a beginner:&lt;/p&gt;

&lt;p&gt;1 Don't be afraid to ask questions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's better to ask and clarify something you don't understand than to struggle on your own and potentially make mistakes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2 Learn to debug: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debugging skills are essential for any developer. Practice using debugging tools and techniques to help you identify and fix issues in your code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3 Write clean, organized code: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Good coding practices, such as using clear and descriptive names for variables and functions and using proper indentation, will make your code easier to read and maintain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4 Learn how to use version control: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version control systems, such as Git, are essential for tracking changes to your code and collaborating with others. Make sure to learn how to use them effectively.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5 Focus on learning the fundamentals: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It's easy to get caught up in learning the latest technologies, but it's important to have a strong foundation in the fundamentals of computer science and programming. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure to spend time learning core concepts such as algorithms, data structures, and software design.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kindly share the advice you wish you knew when you started as a junior software developer in the comment section.&lt;br&gt;
👇👇👇&lt;/p&gt;

</description>
      <category>newbie</category>
      <category>discuss</category>
      <category>codenewbie</category>
      <category>developers</category>
    </item>
    <item>
      <title>How Streams works in Nodejs</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Sat, 06 May 2023 21:53:54 +0000</pubDate>
      <link>https://dev.to/clericcoder/how-streams-works-in-nodejs-580d</link>
      <guid>https://dev.to/clericcoder/how-streams-works-in-nodejs-580d</guid>
      <description>&lt;p&gt;If you enjoy this topic, you will probably like my articles, tweets, and stuff. If you're wondering, check out my &lt;a href="https://www.youtube.com/channel/UCJQmbtiMOaWro6ZCstnkhkg" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt;, and don't forget to subscribe and follow since I'm offering programming and motivating tools and information to help you achieve your dreams.&lt;/p&gt;

&lt;p&gt;Streams are a powerful feature in Node.js that allows developers to efficiently handle large amounts of data by reading and writing data in chunks. This approach is particularly useful when dealing with large files or data sets, as it allows for more efficient handling of data.&lt;/p&gt;

&lt;p&gt;One of the main advantages of using streams is that they are memory-efficient. Instead of loading an entire file or data set into memory at once, streams read and write data in smaller chunks. This means that you can work with large files or data sets without having to worry about running out of memory.&lt;/p&gt;

&lt;p&gt;Another advantage of using streams is that they allow for real-time processing of data. For example, you can use streams to process data as it is being uploaded to a server, rather than having to wait for the entire file to be uploaded before processing it. This is particularly useful for video and audio streaming, as it allows for smooth, seamless playback.&lt;/p&gt;

&lt;p&gt;In Node.js, streams are implemented using the stream module. There are several different types of streams, including readable streams, writable streams, and duplex streams.&lt;/p&gt;

&lt;p&gt;A readable stream, such as a file stream, can be used to read data from a source. An example of reading from a file using a readable stream is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fs = require('fs');
const stream = fs.createReadStream('largefile.txt');

stream. On('data', (chunk) =&amp;gt; {
  // process the data in chunk
});

stream. On('end', () =&amp;gt; {
  console.log('Finished reading the file');
});

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

&lt;/div&gt;



&lt;p&gt;A writable stream, such as a file stream, can be used to write data to a destination. An example of writing to a file using a writable stream is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fs = require('fs');
const stream = fs.createWriteStream('largefile.txt');

stream. Write('Hello World');
stream. End();

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

&lt;/div&gt;



&lt;p&gt;A duplex stream, such as a socket, can be used to read and write data to a source and destination. An example of using a duplex stream is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const net = require('net');
const stream = net.createConnection({
  port: 80
});

stream. On('data', (chunk) =&amp;gt; {
  console.log(chunk.toString());
});

stream. Write('GET / HTTP/1.1\r\n\r\n');

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

&lt;/div&gt;



&lt;p&gt;In conclusion, streams are a powerful feature in Node.js that allows developers to efficiently handle large amounts of data by reading and writing data in chunks. &lt;/p&gt;

&lt;p&gt;This allows for more efficient handling of data, such as video and audio streaming, and can also be used to handle large files and data sets.&lt;/p&gt;

&lt;p&gt;If you enjoy this topic, you will probably like my articles, tweets, and stuff. If you're wondering, check out &lt;a href="https://www.youtube.com/channel/UCJQmbtiMOaWro6ZCstnkhkg" rel="noopener noreferrer"&gt;my YouTube channel&lt;/a&gt; and don't forget to subscribe and follow since I'm offering programming and motivating tools and information to help you achieve your dreams.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>backend</category>
    </item>
    <item>
      <title>Understanding the Concept of Decentralized Social Media and how Bluesky fits into it. (Part 1)</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Thu, 27 Apr 2023 11:36:19 +0000</pubDate>
      <link>https://dev.to/clericcoder/understanding-the-concept-of-decentralized-social-media-and-how-bluesky-fits-into-itpart-1-219p</link>
      <guid>https://dev.to/clericcoder/understanding-the-concept-of-decentralized-social-media-and-how-bluesky-fits-into-itpart-1-219p</guid>
      <description>&lt;h3&gt;
  
  
  Hey before reading this article Kindly follow me on &lt;a href="https://twitter.com/Clericcoder" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Social media has become an integral part of our daily lives, with billions of users around the world sharing their thoughts, experiences, and ideas online. However, the centralized nature of most social media platforms has led to concerns about data privacy, censorship, and the concentration of power in the hands of a few large corporations. &lt;/p&gt;

&lt;p&gt;Decentralized social media offers a potential solution to these problems, and Bluesky is one project that is working to make this a reality.&lt;/p&gt;

&lt;h2&gt;
  
  
  I. Definition of Decentralized Social Media:
&lt;/h2&gt;

&lt;p&gt;Decentralized social media refers to a social media platform that operates using a decentralized network of nodes, rather than relying on a centralized server or data center. &lt;/p&gt;

&lt;p&gt;This means that users have more control over their data and the content they share, as well as greater protection against censorship and data breaches. &lt;/p&gt;

&lt;p&gt;In a decentralized social media network, users connect directly with each other through peer-to-peer communication, rather than relying on a centralized intermediary.&lt;/p&gt;

&lt;h2&gt;
  
  
  II. Brief Overview of Bluesky:
&lt;/h2&gt;

&lt;p&gt;Bluesky is a decentralized social media project that is currently being developed by a team within Twitter. The aim of Bluesky is to create a decentralized social media protocol that would allow users to have more control over their data and the content they share online. &lt;/p&gt;

&lt;p&gt;The project is still in the early stages of development, and it remains to be seen what form it will eventually produce. However, the team behind Bluesky is working to build a decentralized, secure, and scalable platform while also addressing the challenges of governance, data privacy, and user experience. &lt;/p&gt;

&lt;p&gt;With Bluesky, Twitter aims to create a more open and interoperable social media ecosystem that empowers users to control their own data and participate in the development of the platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  II. What is Decentralized social media?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The current state of social media:
&lt;/h3&gt;

&lt;p&gt;Social media has become an integral part of our lives, with billions of users around the world sharing their thoughts, experiences, and ideas online. &lt;/p&gt;

&lt;p&gt;However, the current state of social media is marked by a few large centralized platforms that have significant control over the content and data that users share. &lt;/p&gt;

&lt;p&gt;These centralized platforms often face criticism for their handling of user data and privacy, as well as concerns about censorship, fake news, and political polarization.&lt;/p&gt;

&lt;h2&gt;
  
  
  The drawbacks of centralized social media:
&lt;/h2&gt;

&lt;p&gt;Centralized social media platforms rely on a centralized server or data center to store and manage user data, content, and interactions. &lt;/p&gt;

&lt;p&gt;This centralization creates several drawbacks, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The concentration of power and control in the hands of a few large corporations, leading to concerns about data privacy and censorship.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A lack of transparency and accountability in decision-making processes, which can lead to inconsistent or biased policies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The risk of data breaches and cyber-attacks, which can compromise user data and security.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The inability to control the flow and dissemination of content, leading to concerns about fake news, misinformation, and manipulation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The benefits of decentralized social media:
&lt;/h2&gt;

&lt;p&gt;Decentralized social media offers several potential benefits over centralized platforms, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Increased control and ownership over user data, allowing users to decide who has access to their data and how it is used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A more open and transparent governance model, allowing users to participate in decision-making processes and ensuring greater accountability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improved security and privacy, with data stored across a decentralized network of nodes, rather than in a single data center.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Greater freedom of expression, with less risk of censorship or content moderation by a central authority.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  III. How Does Decentralized Social Media Work?
&lt;/h2&gt;

&lt;p&gt;Decentralized social media platforms operate using a decentralized network of nodes, protocols, and technologies. Here are some of the key components of decentralized social media:&lt;/p&gt;

&lt;h3&gt;
  
  
  Decentralized networks and protocols:
&lt;/h3&gt;

&lt;p&gt;Decentralized social media networks operate using a peer-to-peer (P2P) architecture, rather than relying on a centralized server or data center. &lt;/p&gt;

&lt;p&gt;This means that users connect directly with each other, without intermediaries. The network is often built on a decentralized protocol, which is a set of rules and procedures that govern how nodes interact with each other. &lt;/p&gt;

&lt;p&gt;These protocols can be designed to be open, transparent, and interoperable, allowing different platforms and communities to connect and communicate with each other.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distributed ledgers and blockchain technology:
&lt;/h3&gt;

&lt;p&gt;Distributed ledger technology (DLT), including blockchain, plays a critical role in decentralized social media. DLT is a type of database that is distributed across a network of nodes, with each node storing a copy of the data. &lt;/p&gt;

&lt;p&gt;This decentralized storage system ensures that data cannot be easily tampered with or deleted, and allows for greater transparency and accountability. Blockchain, in particular, is a type of DLT that uses cryptography to create an immutable and transparent record of transactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Peer-to-peer communication:
&lt;/h3&gt;

&lt;p&gt;In a decentralized social media network, users communicate directly with each other using peer-to-peer communication. This means that data is transmitted directly between users, rather than through a central server. P2P communication can be facilitated by a range of technologies, including messaging protocols, voice and video communication tools, and content sharing platforms. P2P communication allows for greater privacy and security, as well as faster and more efficient data transfer.&lt;/p&gt;

&lt;p&gt;Please stay tuned for Part Two&lt;br&gt;
Kindly follow me on &lt;a href="https://twitter.com/Clericcoder" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>opensource</category>
      <category>discuss</category>
      <category>socialmedia</category>
    </item>
    <item>
      <title>Multer vs Cloudinary: Which Solution Reigns Supreme for Your File Upload Needs?</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Wed, 19 Apr 2023 20:55:58 +0000</pubDate>
      <link>https://dev.to/clericcoder/multer-vs-cloudinary-which-solution-reigns-supreme-for-your-file-upload-needs-4if0</link>
      <guid>https://dev.to/clericcoder/multer-vs-cloudinary-which-solution-reigns-supreme-for-your-file-upload-needs-4if0</guid>
      <description>&lt;p&gt;Multer and Cloudinary are two popular tools used for managing media assets in web applications. Multer is a middleware for handling multipart/form data, which is primarily used for uploading files in Node.js. &lt;/p&gt;

&lt;p&gt;On the other hand, Cloudinary is a cloud-based image and video management platform that provides an end-to-end solution for storing, managing, manipulating, and delivering media assets.&lt;/p&gt;

&lt;p&gt;This article aims to provide a detailed comparison between Multer and Cloudinary, highlighting their strengths and weaknesses and providing recommendations on when to use each solution. &lt;/p&gt;

&lt;p&gt;We'll explore the features, benefits, and limitations of both tools to help you decide which solution is best suited for your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definition of multer and its purpose
&lt;/h2&gt;

&lt;p&gt;Multer is a middleware for handling multipart/form data, which is primarily used for uploading files in Node.js. It parses the request and extracts the uploaded files, making them available in the request object for further processing.&lt;/p&gt;

&lt;p&gt;To use Multer, you need to install it via npm and require it in your Node.js application. You can then create a Multer instance and specify the destination folder where uploaded files should be stored. &lt;/p&gt;

&lt;p&gt;Multer also provides options for limiting the size and number of files that can be uploaded.&lt;/p&gt;

&lt;p&gt;When a file is uploaded, Multer stores it on disk and generates a unique name for it. You can then access the uploaded file in your request handler and perform further processing on it, such as resizing, renaming, or copying it to another location.&lt;/p&gt;

&lt;p&gt;However, Multer has some limitations. First, it's limited to storing uploaded files on disk, which may not be scalable for larger applications or for applications with multiple servers. &lt;/p&gt;

&lt;p&gt;Second, it doesn't provide advanced image or video manipulation capabilities, such as resizing, cropping, or optimizing media assets. &lt;/p&gt;

&lt;p&gt;Finally, Multer requires additional configuration and management to handle the uploaded files, which may add complexity to your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definition of Cloudinary and its purpose
&lt;/h2&gt;

&lt;p&gt;Cloudinary is a cloud-based image and video management platform that provides an end-to-end solution for storing, managing, manipulating, and delivering media assets. &lt;/p&gt;

&lt;p&gt;Its purpose is to simplify the process of managing media assets in web applications while providing advanced features and capabilities.&lt;/p&gt;

&lt;p&gt;To use Cloudinary, you need to sign up for an account and integrate it into your web application using one of its APIs or SDKs. &lt;/p&gt;

&lt;p&gt;You can then upload media assets to Cloudinary, which automatically stores and manages them in the cloud. Cloudinary provides advanced capabilities for manipulating, optimizing, and delivering media assets to end-users across different platforms and devices.&lt;/p&gt;

&lt;p&gt;One of the key benefits of Cloudinary is its scalability. Since media assets are stored in the cloud, you can easily scale up or down depending on your storage and bandwidth requirements. &lt;/p&gt;

&lt;p&gt;This makes it an ideal solution for applications with varying traffic and storage needs.&lt;/p&gt;

&lt;p&gt;Another benefit of Cloudinary is its advanced media management capabilities. Cloudinary provides features like automatic image and video optimization, responsive design, content delivery, metadata extraction, backup and recovery, and more. &lt;/p&gt;

&lt;p&gt;It also supports various image and video formats and provides advanced capabilities like face detection, object recognition, and background removal.&lt;/p&gt;

&lt;p&gt;In addition, Cloudinary provides a comprehensive set of APIs and tools for developers to integrate and customize the platform based on their specific needs. &lt;/p&gt;

&lt;p&gt;It also offers a free tier with limited features and paid plans based on usage and storage requirements, making it accessible to developers of all sizes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison between Multer and Cloudinary
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Features of Multer include
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Parses and handles multipart/form-data&lt;/li&gt;
&lt;li&gt;Stores uploaded files on disk&lt;/li&gt;
&lt;li&gt;Supports limiting the size and number of files&lt;/li&gt;
&lt;li&gt;Provides basic file manipulation capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Features of Cloudinary include
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Cloud-based image and video management platform&lt;/li&gt;
&lt;li&gt;Stores, manages and optimizes media assets in the cloud&lt;/li&gt;
&lt;li&gt;Provides advanced image and video manipulation capabilities&lt;/li&gt;
&lt;li&gt;Supports various image and video formats&lt;/li&gt;
&lt;li&gt;Provides APIs and tools for integration and customization&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to use Multer versus Cloudinary:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Multer:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When you have simple file uploading needs and want to store uploaded files on disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you want to limit the size and number of files that can be uploaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you want to perform basic file manipulation, such as renaming or copying files.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloudinary:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When you need to manage large amounts of media assets and want to store them in the cloud.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you need advanced image and video manipulation capabilities, such as resizing, cropping, and optimizing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you need to support various image and video formats and deliver them to different platforms and devices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you want a scalable solution that can handle varying storage and bandwidth requirements.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical use case for Multer and Cloudinary
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Multer:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A blog application that allows users to upload images for their posts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An e-commerce website that allows vendors to upload product images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A job board that allows applicants to upload their resumes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloudinary:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A photo-sharing application that allows users to upload, manage, and share their photos&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A video-streaming application that needs to transcode and deliver videos to different devices&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An e-learning platform that needs to deliver high-quality images and videos to students across different devices and platforms&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Multer is a simple middleware for handling file uploads in Node.js, while Cloudinary is a cloud-based image and video management platform that provides advanced media management capabilities. &lt;/p&gt;

&lt;p&gt;Multer is suitable for simple file uploading needs, while Cloudinary is ideal for managing large amounts of media assets, optimizing images and videos, and delivering them across different platforms and devices.&lt;/p&gt;

&lt;p&gt;If you need to handle simple file uploads and store uploaded files on disk, Multer is a good choice. &lt;/p&gt;

&lt;p&gt;On the other hand, if you need to manage large amounts of media assets, optimize them for delivery, and deliver them across different platforms and devices, Cloudinary is a better choice.&lt;/p&gt;

&lt;p&gt;For example, if you're building a blog application that allows users to upload images for their posts, Multer is a good choice. &lt;/p&gt;

&lt;p&gt;But if you're building a photo-sharing application that needs to manage large amounts of photos, optimize them for delivery, and deliver them across different platforms and devices, Cloudinary is a better choice.&lt;/p&gt;

&lt;p&gt;Ultimately, the choice between Multer and Cloudinary depends on your specific needs and requirements. &lt;/p&gt;

&lt;p&gt;I encourage further research and exploration of the two solutions to determine which one is the best fit for your application.&lt;/p&gt;

&lt;p&gt;If you enjoy reading this Article&lt;br&gt;
Kindly follow me on &lt;a href="//www.twitter.com/clericcoder"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>cloudinary</category>
      <category>cloud</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Revolutionize Your React App with Redux: A Beginner's Guide to Simplifying State Management(PART 2)</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Wed, 12 Apr 2023 13:24:21 +0000</pubDate>
      <link>https://dev.to/clericcoder/revolutionize-your-react-app-with-redux-a-beginners-guide-to-simplifying-state-managementpart-2-ffi</link>
      <guid>https://dev.to/clericcoder/revolutionize-your-react-app-with-redux-a-beginners-guide-to-simplifying-state-managementpart-2-ffi</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/clericcoder/revolutionize-your-react-app-with-redux-a-beginners-guide-to-simplifying-state-managementpart-1-1ef7"&gt;Here is a link to PART 1&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Reducer Function to handle each Action type and Update the Store Accordingly
&lt;/h2&gt;

&lt;p&gt;Reducers are called reducers because they are used in the reduce() function, which is used to reduce an array of values to a single value. In Redux, reducers are used to reduce the current state of the store to a new state based on the action that is dispatched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Reducer Function
&lt;/h2&gt;

&lt;p&gt;To create a reducer function in Redux, you need to follow a few conventions. First, the function should take two arguments: the current state and an action. Second, the function should return a new state based on the action that is dispatched.&lt;/p&gt;

&lt;p&gt;Here's an example of a simple reducer function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const initialState = {
  count: 0
};

function counterReducer(state = initialState, action) {
  switch (action. Type) {
    case 'INCREMENT':
      return { count: state. Count + 1 };
    case 'DECREMENT':
      return { count: state. Count - 1 };
    default:
      return state;
  }
}

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

&lt;/div&gt;



&lt;p&gt;In the above code snippet example, we're creating a reducer function called &lt;code&gt;counterReducer&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The function takes two arguments: the current state (which is initialized to an object with a count property set to 0) and an action. &lt;/p&gt;

&lt;p&gt;The function returns a new state based on the action that is dispatched.&lt;/p&gt;

&lt;p&gt;The reducer function uses a switch statement to handle different action types. In this example, we're handling two action types: INCREMENT and DECREMENT. &lt;/p&gt;

&lt;p&gt;When the INCREMENT action is dispatched, the function returns a new state object with the count property incremented by 1. Similarly, when the DECREMENT action is dispatched, the function returns a new state object with the count property decremented by 1. If any other action is dispatched, the function simply returns the current state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining Reducers
&lt;/h2&gt;

&lt;p&gt;In larger applications, multiple reducers may handle different parts of the state. To combine these reducers into a single reducer function that can be passed to the store, Redux provides a &lt;code&gt;combineReducers()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Here's an example of how to use &lt;code&gt;combineReducers()&lt;/code&gt; to combine multiple reducers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { combineReducers } from 'redux';

const counterInitialState = {
  count: 0
};

function counterReducer(state = counterInitialState, action) {
  switch (action. Type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

const todosInitialState = {
  items: []
};

function todosReducer(state = todosInitialState, action) {
  switch (action. Type) {
    case 'ADD_TODO':
      return { items: [...state. Items, action.payload] };
    case 'REMOVE_TODO':
      return { items: state.items.filter(todo =&amp;gt; todo.id !== action.payload) };
    default:
      return state;
  }
}

const rootReducer = combineReducers({
counter: counterReducer,
todos: todosReducer
});

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

&lt;/div&gt;



&lt;p&gt;In this example, we're creating two reducers: &lt;code&gt;counterReducer&lt;/code&gt; and &lt;code&gt;todosReducer&lt;/code&gt;. Each reducer handles a different part of the state. &lt;/p&gt;

&lt;p&gt;We're then using &lt;code&gt;combineReducers()&lt;/code&gt; to combine these reducers into a single reducer function called rootReducer. The resulting state object will have two properties: &lt;code&gt;counter&lt;/code&gt; and &lt;code&gt;todos&lt;/code&gt;, which correspond to the state handled by each reducer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Reducer in a React Component
&lt;/h2&gt;

&lt;p&gt;Once you've created a reducer function and combined it with other reducers using &lt;code&gt;combineReducers()&lt;/code&gt;, you can use the resulting reducer function in a React component using the &lt;code&gt;useReducer()&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;Here's an example of how to use the &lt;code&gt;useReducer()&lt;/code&gt; hook to manage state in a React component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useReducer } from 'react';

function Counter() {
  const [state, dispatch] = useReducer(counterReducer, { count: 0 });

  function handleIncrement() {
    dispatch({ type: 'INCREMENT' });
  }

  function handleDecrement() {
    dispatch({ type: 'DECREMENT' });
  }

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Count: {state. Count}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={handleIncrement}&amp;gt;Increment&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={handleDecrement}&amp;gt;Decrement&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;p&gt;In this example, we're using the &lt;code&gt;useReducer()&lt;/code&gt; hook to manage state in a component called Counter. We're passing the &lt;code&gt;counterReducer&lt;/code&gt; function as the first argument to &lt;code&gt;useReducer()&lt;/code&gt;, along with the initial state of the count (which is an object with a count property set to 0). &lt;/p&gt;

&lt;p&gt;We're then defining two functions &lt;code&gt;(handleIncrement() and handleDecrement())&lt;/code&gt; that dispatch the &lt;code&gt;INCREMENT&lt;/code&gt; and &lt;code&gt;DECREMENT&lt;/code&gt; actions, respectively. &lt;/p&gt;

&lt;p&gt;Finally, we're rendering the current count and two buttons that trigger the corresponding actions when clicked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a selector function to extract a specific piece of data from the store
&lt;/h2&gt;

&lt;p&gt;In Redux, selectors are functions that are used to extract data from the state in a structured way. Selectors are especially useful when the state is complex or when you want to derive new data from the state. &lt;/p&gt;

&lt;p&gt;In this section, we'll explain how to create and use selectors in a React application that uses Redux for state management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Selector Function
&lt;/h2&gt;

&lt;p&gt;To create a selector function, you can use the &lt;code&gt;createSelector()&lt;/code&gt; function from the reselect library. The &lt;code&gt;createSelector()&lt;/code&gt; function takes one or more input selectors and a transform function, and returns a memorized selector function.&lt;/p&gt;

&lt;p&gt;Here's an example of how to create a selector function that extracts the current count from the state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createSelector } from 'reselect';

const getCount = state =&amp;gt; state.counter.count;

export const countSelector = createSelector(
  [getCount],
  count =&amp;gt; count
);

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

&lt;/div&gt;



&lt;p&gt;In this example, we're using the &lt;code&gt;createSelector()&lt;/code&gt; function to create a memorized selector function called countSelector. &lt;/p&gt;

&lt;p&gt;The selector function takes an input selector called &lt;code&gt;getCount&lt;/code&gt;, which simply extracts the count property from the counter slice of the state. &lt;/p&gt;

&lt;p&gt;The transform function takes the count as input and returns it as output. The resulting &lt;code&gt;countSelector&lt;/code&gt; function can be used to extract the count from the state in an effective  way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Selector Function in &lt;code&gt;mapStateToProps()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Once you've created a selector function, you can use it in the &lt;code&gt;mapStateToProps()&lt;/code&gt; function to pass the data to the component as props. &lt;/p&gt;

&lt;p&gt;Here's an example of how to use the countSelector function in &lt;code&gt;mapStateToProps()&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;import { connect } from 'react-redux';
import { countSelector } from './selectors';

function Counter({ count, dispatch }) {
  // ...
}

function mapStateToProps(state) {
  return {
    count: countSelector(state)
  };
}

export default connect(mapStateToProps)(Counter);

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

&lt;/div&gt;



&lt;p&gt;In this example, we're using the &lt;code&gt;connect()&lt;/code&gt; function to connect a component called &lt;code&gt;Counter&lt;/code&gt; to the Redux store. We're importing the &lt;code&gt;countSelector&lt;/code&gt; function from a file called &lt;code&gt;selectors.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We're then defining a &lt;code&gt;mapStateToProps()&lt;/code&gt; function that maps the count property from the state to a prop called count in the component, using the &lt;code&gt;countSelector&lt;/code&gt; function to extract the count from the state. Finally, we're exporting the connected Counter component.&lt;/p&gt;

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

&lt;p&gt;Selectors are a powerful tool in Redux that enable you to extract data from the state in a structured and performant way. By using the &lt;code&gt;createSelector()&lt;/code&gt; function from the reselect library, you can create memorized selector functions that extract new data from the state or extract specific pieces of data from the state. By using selectors in conjunction with the &lt;code&gt;mapStateToProps()&lt;/code&gt; function, you can pass the data to your React components as props and render the data in your UI.&lt;/p&gt;

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

&lt;p&gt;we've  discussed how Redux can be useful for managing complex state in a React application, and covered the following topics in previous sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installing the necessary packages (redux, react-redux)&lt;/li&gt;
&lt;li&gt;Creating a Redux store and initializing it with initial state&lt;/li&gt;
&lt;li&gt;Creating actions and action creators to update the store&lt;/li&gt;
&lt;li&gt;Creating reducers to handle the actions and update the store&lt;/li&gt;
&lt;li&gt;Connecting a React component to the Redux store using the useReducer() hook.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to learn more about Redux and how to use it in a React application, here are some resources you might find helpful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://redux.js.org/" rel="noopener noreferrer"&gt;Redux documentation:&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://egghead.io/courses/getting-started-with-redux" rel="noopener noreferrer"&gt;Getting Started with Redux course on Egghead:&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://redux-toolkit.js.org/" rel="noopener noreferrer"&gt;Redux Toolkit documentation:&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/reduxjs/reselect" rel="noopener noreferrer"&gt;Reselect documentation:&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  THANKS FOR READING
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://twitter.com/Clericcoder" rel="noopener noreferrer"&gt;Connect with me on Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Revolutionize Your React App with Redux: A Beginner's Guide to Simplifying State Management(PART 1)</title>
      <dc:creator>Abdulsalaam Noibi</dc:creator>
      <pubDate>Wed, 05 Apr 2023 22:06:21 +0000</pubDate>
      <link>https://dev.to/clericcoder/revolutionize-your-react-app-with-redux-a-beginners-guide-to-simplifying-state-managementpart-1-1ef7</link>
      <guid>https://dev.to/clericcoder/revolutionize-your-react-app-with-redux-a-beginners-guide-to-simplifying-state-managementpart-1-1ef7</guid>
      <description>&lt;h2&gt;
  
  
  Explanation of Redux
&lt;/h2&gt;

&lt;p&gt;Let's imagine that you are playing a game with a group of people. In the game, you have a lot of different things you need to keep track of points, power-ups, and items you've collected.&lt;/p&gt;

&lt;p&gt;If you try to remember all of these things in your head, it can be really hard to keep track of everything. You might forget something important or get confused.&lt;/p&gt;

&lt;p&gt;Redux is like a scoreboard for the game. It keeps track of all of the different things you need to remember, so that you can easily see how many points you have, what power-ups you've collected, and what items you still need to find.&lt;/p&gt;

&lt;p&gt;Just like how a scoreboard helps you keep track of everything in a game, Redux helps you keep track of everything in your app or website. &lt;/p&gt;

&lt;p&gt;It organizes all of your data in one place, so that you can easily access it and make changes to it when you need to.&lt;/p&gt;

&lt;p&gt;And just like how a scoreboard can be used for any game, Redux can be used with any app or website, not just games. That's why it's so popular and useful!&lt;/p&gt;

&lt;h2&gt;
  
  
  Brief explanation of the key principle of Redux
&lt;/h2&gt;

&lt;p&gt;The key principles of Redux are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Store: This is like a Scoreboard, where all the information is stored.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Actions: These are like messages you send to the program, telling perform a certain function. For example, "Get specific data".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reducers: These are like helpers that know how to change the &lt;br&gt;
Scoreboard based on the messages you send. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, if you send the message "Add a new item to the Scoreboard!" The reducer knows how to put a new item in the Scoreboard.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Selectors: These are like helpers that help you find what you're looking for in the Scoreboard. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, if you want to find a particular item, a selector can help you find them quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redux Principles
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Store&lt;/strong&gt;: The store is the central place where all the data for a Redux application is kept. It's like a big container that holds all the information about what's going on in the application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This makes it easy to keep track of what's happening and to give the developer easy access to the information when it's needed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Actions&lt;/strong&gt;: Actions are messages that are sent to the store to update the data inside it. They describe something that has happened in the application, like a button being clicked or a form being submitted. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When an action is dispatched, it triggers a change in the store. For example, if the "Add to Cart" button is clicked on an online shopping website, an action might be dispatched to add the item to the cart.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reducers&lt;/strong&gt;: Reducers are functions that handle the changes in the store that are triggered by actions. They take the current state of the store and the action that was dispatched and then return a new state that reflects the change that was made. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, if an action was dispatched to add an item to the cart, the reducer would take the current state of the cart and add the new item to it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Selectors&lt;/strong&gt;: Selectors are functions that extract data from the store. They take the current state of the store and return a specific piece of data that is needed by the application. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, a selector might be used to extract the total price of all the items in the cart.&lt;/p&gt;

&lt;p&gt;Together, these four principles form the foundation of Redux and make it a powerful tool for managing the state of complex applications. &lt;/p&gt;

&lt;p&gt;By keeping all the data in a single place and using actions, reducers, and selectors to manage it, Redux makes it easy to keep track of what's going on in an application and to access the data when it's needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Redux in a React Application
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Installing the necessary packages (redux, react-redux)
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Redux
&lt;/h3&gt;

&lt;p&gt;The redux package is the core package for Redux. It provides the building blocks for creating a Redux store, dispatching actions, and handling state changes. To install redux, open up your terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//for npm users
npm install redux

//for yarn users
yarn add redux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  React-redux
&lt;/h3&gt;

&lt;p&gt;The react-redux package provides bindings between React and Redux. It allows you to connect your React components to a Redux store and access the store's state and dispatch methods. To install react-redux, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//for npm users
npm install react-redux

//for yarn users
yarn add react-redux

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Creating a Redux store and initializing it with initial state
&lt;/h3&gt;

&lt;p&gt;Once you've installed the necessary packages for Redux in your React application, the next step is to create a Redux store. &lt;/p&gt;

&lt;p&gt;The store is the central hub of your Redux application, responsible for managing your application's state&lt;/p&gt;

&lt;p&gt;To create a Redux store, we'll need to import the &lt;code&gt;createStore&lt;/code&gt; function from the &lt;code&gt;redux&lt;/code&gt; package. This function is responsible for creating a new Redux store instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createStore } from 'redux';

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

&lt;/div&gt;



&lt;p&gt;The next step is to create a reducer function. A reducer is a pure function that takes the current state and an action as arguments, and returns a new state. &lt;/p&gt;

&lt;p&gt;The reducer is responsible for handling state changes in your Redux application.&lt;/p&gt;

&lt;p&gt;Here's an example of a reducer function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const initialState = { count: 0 };

const counterReducer = (state = initialState, action) =&amp;gt; {
  switch (action. Type) {
    case 'INCREMENT':
      return { ...state, count: state. Count + 1 };
    case 'DECREMENT':
      return { ...state, count: state. Count - 1 };
    default:
      return state;
  }
};

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

&lt;/div&gt;



&lt;p&gt;In the above example, we're creating a reducer function called &lt;code&gt;counterReducer&lt;/code&gt;. The &lt;code&gt;initialState&lt;/code&gt; object contains the initial state of our application, with a &lt;code&gt;count&lt;/code&gt; property set to 0. &lt;/p&gt;

&lt;p&gt;The reducer function takes two arguments: &lt;code&gt;state&lt;/code&gt; and &lt;code&gt;action&lt;/code&gt;. If no state is passed in (i.e. on the first call to the reducer), the initial state is used.&lt;/p&gt;

&lt;p&gt;The reducer function uses a &lt;code&gt;switch&lt;/code&gt; statement to determine how to handle each action. &lt;/p&gt;

&lt;p&gt;In this example, we're handling two actions: &lt;code&gt;INCREMENT&lt;/code&gt; and &lt;code&gt;DECREMENT&lt;/code&gt;. When the &lt;code&gt;INCREMENT&lt;/code&gt; action is dispatched, we create a new state object with the count property incremented by 1.&lt;/p&gt;

&lt;p&gt;Similarly, when the &lt;code&gt;DECREMENT&lt;/code&gt; action is dispatched, we create a new state object with the count property decremented by 1. If the action type is not recognized, the current state is returned.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Using the &lt;code&gt;createStore&lt;/code&gt; function to create a store with the reducer and initial state
&lt;/h3&gt;

&lt;p&gt;Now that we've created our reducer function, we can use the &lt;code&gt;createStore&lt;/code&gt; function to create a new Redux store instance.&lt;/p&gt;

&lt;p&gt;We'll pass in our reducer function as the first argument, and our initial state as the second argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const store = createStore(counterReducer, initialState);

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

&lt;/div&gt;



&lt;p&gt;This will create a new Redux store instance with our counterReducer function as the reducer, and our initialState object as the initial state.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Creating actions and action creators to update the store
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Creating a set of action types as constants
&lt;/h4&gt;

&lt;p&gt;The first step in creating actions in Redux is to define a set of action types as constants. Action types are string constants that describe the type of action being performed. &lt;/p&gt;

&lt;p&gt;They are used to identify the action when it is dispatched to the store.&lt;/p&gt;

&lt;p&gt;Here's an example of defining a set of action types as constants:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const INCREMENT_COUNT = 'INCREMENT_COUNT';
export const DECREMENT_COUNT = 'DECREMENT_COUNT';

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating action creator functions to create actions of each type
&lt;/h3&gt;

&lt;p&gt;The next step is to create action creator functions. Action creators are functions that create actions of a specific type. They take any necessary data as arguments, and return an action object.&lt;/p&gt;

&lt;p&gt;Here's an example of creating action creator functions for our &lt;code&gt;INCREMENT_COUNT&lt;/code&gt; and &lt;code&gt;DECREMENT_COUNT&lt;/code&gt; actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function incrementCount() {
  return { type: INCREMENT_COUNT };
}

export function decrementCount() {
  return { type: DECREMENT_COUNT };
}

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

&lt;/div&gt;



&lt;p&gt;In the above example, we're creating two action creator functions: &lt;code&gt;incrementCount()&lt;/code&gt; and &lt;code&gt;decrementCount()&lt;/code&gt;. Each function returns an action object with a &lt;code&gt;type&lt;/code&gt; property set to the corresponding action type constant.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Dispatching actions to update the store
&lt;/h3&gt;

&lt;p&gt;Now that we've created our action types and action creators, we can dispatch them to update the store. We'll need to use the &lt;code&gt;dispatch()&lt;/code&gt; function provided by the Redux store to dispatch our actions.&lt;/p&gt;

&lt;p&gt;Here's an example of dispatching our &lt;code&gt;incrementCount()&lt;/code&gt; and &lt;code&gt;decrementCount()&lt;/code&gt; actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//importing from the action file
import { incrementCount, decrementCount } from './actions';

store. Dispatch(incrementCount());
store.dispatch(decrementCount());

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

&lt;/div&gt;



&lt;p&gt;In the above example, we're importing our action creator functions from a file called &lt;code&gt;actions.js&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We then dispatch the &lt;code&gt;incrementCount()&lt;/code&gt; and &lt;code&gt;decrementCount()&lt;/code&gt; actions to the store using the &lt;code&gt;dispatch()&lt;/code&gt; function provided by the Redux store.&lt;/p&gt;

&lt;p&gt;PART TWO WILL SOON BE PUBLISHED.&lt;br&gt;
PLEASE STAY TUNED&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
