<?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: rezoMoon</title>
    <description>The latest articles on DEV Community by rezoMoon (@reza_moon).</description>
    <link>https://dev.to/reza_moon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4116291%2F96e0fa2f-a4f9-44b6-9edd-2b92c2007f00.jpg</url>
      <title>DEV Community: rezoMoon</title>
      <link>https://dev.to/reza_moon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/reza_moon"/>
    <language>en</language>
    <item>
      <title>Under the Hood of Python Logging: The 4 Core Building Blocks (Part 3)</title>
      <dc:creator>rezoMoon</dc:creator>
      <pubDate>Sat, 19 Sep 2026 14:52:17 +0000</pubDate>
      <link>https://dev.to/reza_moon/under-the-hood-of-python-logging-the-4-core-building-blocks-part-3-j1b</link>
      <guid>https://dev.to/reza_moon/under-the-hood-of-python-logging-the-4-core-building-blocks-part-3-j1b</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📌 &lt;em&gt;This article is Part 3 of a multi-part series: "Logging in Django: From Basics to Production".&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Check out the previous parts: &lt;a href="https://dev.to/reza_moon/logging-in-django-from-basics-to-production-part-1-why-logging-2m03"&gt;Part 1: Why Logging?&lt;/a&gt; | &lt;a href="https://dev.to/reza_moon/logging-in-django-from-basics-to-production-part-2-python-logging-fundamentals-230c"&gt;Part 2: Python Logging Fundamentals&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Architectural Building Blocks of Logging in Python
&lt;/h1&gt;

&lt;p&gt;To transform logging from a simple statement into a robust and flexible pipeline, Python builds its logging framework around 4 core modular components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logger: The entry point for dispatching events and capturing logs.&lt;/li&gt;
&lt;li&gt;Handler: Determines the destination and routes log events (console, files, sockets, databases).&lt;/li&gt;
&lt;li&gt;Formatter: Architects the message layout, converting raw event metadata into human-readable text or structured formats (such as JSON).&lt;/li&gt;
&lt;li&gt;Filter: Provides granular, programmatic control for refining events or injecting extra context.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's examine these components inside a complete end-to-end pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Define logger and assign an identity
&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my_app&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 2. Create a formatter to structure the output
&lt;/span&gt;&lt;span class="n"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%(asctime)s - %(name)s - %(levelname)s - %(message)s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 3. Define handler and specify the destination (Console)
&lt;/span&gt;&lt;span class="n"&gt;console_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;console_handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;console_handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 4. Attach handler to the logger
&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;console_handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 5. Emit logs at various severity levels
&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Debug log - ignored by handler&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Info message - displayed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error message - displayed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deep Dive: How the Pipeline Works
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Logger Identity (&lt;code&gt;getLogger&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;By calling &lt;code&gt;logging.getLogger("my_app")&lt;/code&gt; , you create or retrieve a specific logger instance. The logger name functions as its identifier across the system, immediately revealing which component or service initiated the event during root-cause analysis.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Threshold Control: Logger Level vs. Handler Level
&lt;/h4&gt;

&lt;p&gt;Notice these two lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;console_handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Levels are evaluated at two separate checkpoints:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, the logger evaluates whether the message meets its minimum threshold ( &lt;code&gt;DEBUG&lt;/code&gt; ). If it does, the event is packaged and passed along to attached handlers.&lt;/li&gt;
&lt;li&gt;Next, the handler independently verifies whether the event meets its own threshold ( &lt;code&gt;INFO&lt;/code&gt; ). &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because our logger threshold is &lt;code&gt;DEBUG&lt;/code&gt; but the handler requires &lt;code&gt;INFO&lt;/code&gt; , the &lt;code&gt;DEBUG&lt;/code&gt; message is dropped by the handler and never appears in console output.&lt;/p&gt;

&lt;p&gt;Note: The inverse is also true: if the logger is set to a higher threshold (e.g., &lt;code&gt;ERROR&lt;/code&gt;) while the handler is set to &lt;code&gt;DEBUG&lt;/code&gt;, the logger rejects incoming lower-level events immediately. The handler never receives them.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. LogRecord and Formatter Internals
&lt;/h4&gt;

&lt;p&gt;Whenever you invoke a logging method, Python dynamically instantiates an internal &lt;code&gt;LogRecord&lt;/code&gt; object. This object packages raw execution metadata, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exact millisecond timestamp (&lt;code&gt;created&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Source file line number (&lt;code&gt;lineno&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Executing thread identifier (&lt;code&gt;threadName&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The actual raw log message&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Formatter takes this LogRecord object, translates the requested attributes, and shapes the final string representation based on your format definition.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Final Destinations via Handlers
&lt;/h4&gt;

&lt;p&gt;The standard &lt;code&gt;StreamHandler&lt;/code&gt; writes events directly to standard console streams (like &lt;code&gt;sys.stderr&lt;/code&gt;). You can attach multiple handlers to a single logger simultaneously. For example, a single event can be logged to &lt;code&gt;stdout&lt;/code&gt; via &lt;code&gt;StreamHandler&lt;/code&gt; while errors are persistently written to disk using &lt;code&gt;RotatingFileHandler&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Power of Filters
&lt;/h3&gt;

&lt;p&gt;Filters do far more than simple severity checks. They give you programmatic access to the event lifecycle for two essential production needs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Data Masking (PII Protection): Sanitizing sensitive parameters—such as passwords, tokens, API keys, or personal identifiable information—before logs leave memory.&lt;/li&gt;
&lt;li&gt;Context Injection: Injecting contextual fields (e.g., &lt;code&gt;request_id&lt;/code&gt;,&lt;code&gt;tenant_id&lt;/code&gt;) directly into the &lt;code&gt;LogRecord&lt;/code&gt; so every downstream handler and formatter can include them automatically.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Understanding Propagation and Hierarchical Trees
&lt;/h3&gt;

&lt;p&gt;Loggers follow a dot-delimited hierarchy similar to packages or file system directories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parent: &lt;code&gt;app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Child: &lt;code&gt;app.api&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Grandchild: &lt;code&gt;app.api.auth&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default, propagate = True. When an event hits a child logger, it is processed by the child's handlers and then passed up the tree to the parent's handlers.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Duplicate Log Problem
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;

&lt;span class="c1"&gt;# Parent logger writing to console
&lt;/span&gt;&lt;span class="n"&gt;parent_logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parent_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parent_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;parent_handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PARENT -&amp;gt; %(message)s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;parent_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent_handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Child logger with its own console handler
&lt;/span&gt;&lt;span class="n"&gt;child_logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app.api&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;child_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;child_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;child_handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CHILD -&amp;gt; %(message)s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;child_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child_handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Emit event via child
&lt;/span&gt;&lt;span class="n"&gt;child_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Service initialized.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Console Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CHILD -&amp;gt; Service initialized.
PARENT -&amp;gt; Service initialized.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The message was printed twice because propagation passed the event up to parent_logger.&lt;/p&gt;

&lt;h4&gt;
  
  
  Fixing Duplicate Logs
&lt;/h4&gt;

&lt;p&gt;To restrict event handling strictly to the child logger without bubbling up to ancestors, disable propagation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;child_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;propagate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;propagate = False&lt;/code&gt;, the output is clean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CHILD -&amp;gt; Service initialized.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents wasted I/O, duplicate log entries, and bloated storage costs in production.&lt;/p&gt;




&lt;h3&gt;
  
  
  What to expect in this series:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/reza_moon/logging-in-django-from-basics-to-production-part-1-why-logging-2m03"&gt;Part 1: Why Logging? (The philosophy, MTTR, and real-world scenarios)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.toLINK_TO_PART_2"&gt;Part 2: Python Logging Fundamentals: Root Logger, Levels &amp;amp; Module Namespaces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Part 3: Deep Dive into Architecture: Loggers, Handlers, Filters &amp;amp; Propagation (Current)&lt;/li&gt;
&lt;li&gt;Part 4: Production Django Logging: Dictionaries, JSON Formatting, and Cloud Setups&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;💬 Discussion:&lt;br&gt;&lt;br&gt;
Have you ever run into unexpected duplicate logs in production caused by propagation? How do you currently handle sensitive data masking in your logs? Let's discuss below!&lt;/p&gt;

</description>
      <category>python</category>
      <category>logging</category>
      <category>backend</category>
      <category>django</category>
    </item>
    <item>
      <title>Logging in Django: From Basics to Production (Part 2: Python Logging Fundamentals)</title>
      <dc:creator>rezoMoon</dc:creator>
      <pubDate>Fri, 18 Sep 2026 11:12:04 +0000</pubDate>
      <link>https://dev.to/reza_moon/logging-in-django-from-basics-to-production-part-2-python-logging-fundamentals-230c</link>
      <guid>https://dev.to/reza_moon/logging-in-django-from-basics-to-production-part-2-python-logging-fundamentals-230c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📌 &lt;em&gt;This article is Part 2 of a multi-part series: *&lt;/em&gt;"Logging in Django: From Basics to Production"*&lt;em&gt;.&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;If you missed Part 1, check it out here: &lt;a href="https://dev.to/reza_moon/logging-in-django-from-basics-to-production-part-1-why-logging-2m03"&gt;Part 1: Why Logging?&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Think of a logging system as a data pipeline—by setting up and configuring that pipeline properly, you can seamlessly manage and direct your application's logs.&lt;/p&gt;

&lt;p&gt;Before diving into the code details, let's examine two real-world log outputs to understand exactly what we are aiming for in Python and Django applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world Output in a Python Service:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-09-03 18:55:01,234 - root - INFO - Application started successfully.
2026-09-03 18:55:02,512 - my_project.utils - DEBUG - Connecting to Redis cache at 127.0.0.1:6379
2026-09-03 18:55:02,589 - my_project.utils - INFO - Cache connection established.
2026-09-03 18:55:10,102 - my_project.api - ERROR - Failed to parse incoming payload.
Traceback (most recent call last):
  File "/home/user/project/data_processor.py", line 42, in parse_payload
    data = json.loads(payload)
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
2026-09-03 18:55:35,401 - root - INFO - Periodic cleanup completed: 14 stale sessions purged.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Standard Output in the Django Framework:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[2026-09-03 18:50:22,104] INFO [django.server:164] "GET /api/v1/products/ HTTP/1.1" 200 4520
[2026-09-03 18:51:05,312] WARNING [django.request:228] Forbidden (Permission Denied): /api/v1/admin/dashboard/
[2026-09-03 18:52:14,891] ERROR [django.request:241] Internal Server Error: /api/v1/checkout/
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;What Information Do These Lines Give Us?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Timestamp: Exactly down to the millisecond when the event occurred.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Log Level: Is this a routine notification, a warning, or a critical failure requiring immediate intervention?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Origin (Logger Name / File / Line): Exactly which file, function, or module dispatched the event.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Event Description &amp;amp; Traceback: What happened, and what was the state of the execution context?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the core elements you must consider when designing and configuring your logging setup. But how do we produce such structured logs, and what options, controls, and configurations are available under the hood?&lt;/p&gt;

&lt;p&gt;Let’s start with the simplest possible approach.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Your First Log in Python and the Concept of "Root"&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Python’s built-in logging system uses a modular, object-oriented pipeline composed of several components.&lt;/p&gt;

&lt;p&gt;To record logs, we import the standard &lt;code&gt;logging&lt;/code&gt; module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# level/basic.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your First Log in Python!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this code produces the following console output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO:root:Your First Log in Python!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Why was &lt;code&gt;INFO:root:&lt;/code&gt; prefixed to the message?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Log Level (&lt;code&gt;INFO&lt;/code&gt;): Defines the severity and nature of the event.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Logger Name (&lt;code&gt;root&lt;/code&gt;): Loggers in Python follow a hierarchical tree structure. When you directly invoke helper functions like &lt;code&gt;logging.info()&lt;/code&gt;, the event is passed to the top node of this tree: the Root Logger.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Understanding Log Levels and Their Numeric Values&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In Python, you can categorize events into distinct severity levels and handle each level differently depending on your system requirements.&lt;/p&gt;

&lt;p&gt;There are 5 standard log levels:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3j358ll1o4twvr4k0b12.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3j358ll1o4twvr4k0b12.png" alt=" " width="799" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Level Filtering: Why Did We Specify &lt;code&gt;level=logging.INFO&lt;/code&gt;?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The default threshold for the Python logger is &lt;code&gt;WARNING&lt;/code&gt; (numeric value 30). The logging engine only processes and outputs messages whose numeric severity is greater than or equal to the configured threshold.&lt;/p&gt;

&lt;p&gt;Consider this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Info log - ignored&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Warning log - ignored&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error log - will be displayed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only the last line is printed. Because &lt;code&gt;ERROR&lt;/code&gt; (40) satisfies the threshold, any level lower than 40 is suppressed.&lt;br&gt;
Configuration Strategies&lt;/p&gt;

&lt;p&gt;While &lt;code&gt;basicConfig&lt;/code&gt; works for simple single-file scripts, it is not sufficient for production systems.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;&lt;strong&gt;Quick Setup via &lt;code&gt;basicConfig&lt;/code&gt; (Scripts &amp;amp; Testing)&lt;/strong&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%(asctime)s - %(levelname)s - %(name)s - %(filename)s:%(lineno)d - %(message)s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;filemode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app.log&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Standard Enterprise Approach: Module Namespaces (&lt;code&gt;__name__&lt;/code&gt;)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In modular applications, you should never log everything directly to the root logger. Instead, each module should declare its own independent logger tied to Python's module namespace using &lt;code&gt;__name__&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# users/services.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;

&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_user_profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Processing profile for user: %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Business logic fetching user profile
&lt;/span&gt;        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully fetched profile for user: %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# logger.exception automatically attaches the traceback
&lt;/span&gt;        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to process profile for user: %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;_&lt;br&gt;
Why is this pattern critical?_&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When called inside &lt;code&gt;users/services.py, __name__&lt;/code&gt; automatically resolves to the logger name &lt;code&gt;users.services&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In larger systems, this hierarchy allows granular control. For example, you can selectively set loggers under &lt;code&gt;billing.*&lt;/code&gt; to output at &lt;code&gt;DEBUG&lt;/code&gt; level while keeping third-party libraries or stable core modules at &lt;code&gt;INFO&lt;/code&gt; or &lt;code&gt;WARNING&lt;/code&gt;.&lt;br&gt;
&lt;em&gt;&lt;strong&gt;What to expect in this series:&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Part 1: &lt;em&gt;&lt;strong&gt;Why Logging?&lt;/strong&gt;&lt;/em&gt; (The philosophy, MTTR, and real-world scenarios)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 2:&lt;em&gt;** Python Logging Fundamentals**&lt;/em&gt;: Loggers, Handlers, Formatters &amp;amp; Structured Logging (Current)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Part 3: &lt;em&gt;*&lt;em&gt;Mastering Django &lt;code&gt;LOGGING&lt;/code&gt; Configuration in Production *&lt;/em&gt;&lt;/em&gt;(Log rotation, correlation IDs, and security considerations)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;💬 Discussion:&lt;/p&gt;

&lt;p&gt;Do you configure distinct log levels per module in your projects, or do you still rely on global logger settings? Let's discuss in the comments below!&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>backend</category>
      <category>logging</category>
    </item>
    <item>
      <title>Logging in Django: From Basics to Production (Part 1: Why Logging?)</title>
      <dc:creator>rezoMoon</dc:creator>
      <pubDate>Wed, 09 Sep 2026 09:48:27 +0000</pubDate>
      <link>https://dev.to/reza_moon/logging-in-django-from-basics-to-production-part-1-why-logging-2m03</link>
      <guid>https://dev.to/reza_moon/logging-in-django-from-basics-to-production-part-1-why-logging-2m03</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📌 &lt;em&gt;This article is Part 1 of a multi-part series: *&lt;/em&gt;"Logging in Django: From Basics to Production"*&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Have you ever worked with logs in your applications and code?&lt;/p&gt;

&lt;p&gt;It doesn't matter what programming language or framework you are using; a crucial part of your application is related to logs and logging.&lt;/p&gt;

&lt;p&gt;Here, I will share with you my own challenges regarding logging and implementing a logging system in a project.&lt;/p&gt;

&lt;p&gt;Before diving into logging in Django, we need to have a proper understanding of the concept and importance of logs.&lt;/p&gt;

&lt;p&gt;Imagine you are designing and working on an enterprise-level system that is expected to scale exponentially with an increasing user base. Or, on the other hand, you might have an application with fewer than a hundred users running with minimal features.&lt;/p&gt;

&lt;p&gt;In either case, &lt;strong&gt;you still need a logging system!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With the logging system you implement, you should be able to access the required log content through the simplest process and in the shortest time possible, allowing you to resolve your system's issues quickly.&lt;/p&gt;

&lt;p&gt;What information to actually record in your logs is another point that must be chosen with care. By having an appropriate logging system, you can ensure a secure and reliable application.&lt;/p&gt;

&lt;p&gt;Another primary objective of logging is optimizing &lt;strong&gt;MTTR (Mean Time To Recovery/Repair)&lt;/strong&gt;, which refers to the average time it takes for a system to return to a stable state after an incident or failure occurs.&lt;/p&gt;




&lt;h3&gt;
  
  
  Two Scenarios on Why Logs Matter
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Asynchronous and Multi-service Systems
&lt;/h4&gt;

&lt;p&gt;Imagine a user places an order. The request hits the web framework, spawns a background worker task (like Celery), and simultaneously calls a payment gateway. The transaction fails mid-way: the user's account has been debited, but access or fulfillment hasn't been granted. &lt;/p&gt;

&lt;p&gt;Without structured logging, tracing across multiple systems simultaneously is nearly impossible. However, by injecting a unique identifier (&lt;strong&gt;Correlation ID / Trace ID&lt;/strong&gt;) across all processing stages, you can reconstruct the entire request lifecycle within seconds and pinpoint the exact bottleneck.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Failure Management in Third-Party APIs
&lt;/h4&gt;

&lt;p&gt;Imagine your SMS provider or authentication service suddenly starts returning &lt;code&gt;502 Bad Gateway&lt;/code&gt; errors. With an optimized logging system that captures response metadata, monitoring platforms can immediately detect this anomalous error rate spike. Without creating unnecessary noise or &lt;strong&gt;alert fatigue&lt;/strong&gt;, automated alerts are triggered for the engineering team before more users are impacted.&lt;/p&gt;




&lt;p&gt;In this series of articles, we will first start with the core Python logging module (&lt;code&gt;logging&lt;/code&gt;), log level strategies, and structured logging. In the upcoming parts, we will dive deep into dedicated &lt;code&gt;LOGGING&lt;/code&gt; configurations and production best practices in Django.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to expect in this series:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 1:&lt;/strong&gt; Why Logging? (The philosophy, MTTR, and real-world scenarios) &lt;em&gt;(Current)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 2:&lt;/strong&gt; Python Logging Fundamentals: Loggers, Handlers, Formatters &amp;amp; Structured Logging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 3:&lt;/strong&gt; Mastering Django &lt;code&gt;LOGGING&lt;/code&gt; Configuration in Production (Log rotation, correlation IDs, and security considerations)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;💬 &lt;strong&gt;Join the Discussion:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Have you ever faced a production incident that was saved (or made worse) by your logging setup? Share your experience in the comments below!&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>backend</category>
      <category>logging</category>
    </item>
  </channel>
</rss>
