Practical Example: Building Dynamic Log Messages

🏷️ Working with Strings In-Depth / String Formatting


🎯 Context Introduction

Logging is one of the most common tasks in any system. Whether you're monitoring servers, debugging applications, or tracking deployment pipelines, you'll constantly need to generate log messages that change based on runtime conditions. Hardcoding every log message is impractical and messy. Instead, you can build dynamic log messages using Python's string formatting techniques. This example will show you how to create flexible, readable, and reusable log messages that adapt to different scenarios.


βš™οΈ The Problem: Static vs. Dynamic Logging

Imagine you have a script that checks the status of multiple services. Without dynamic formatting, you'd write something like:

  • Static approach: Print "Service database is running" and "Service web_server is down". This works but becomes repetitive and error-prone when you have dozens of services.

  • Dynamic approach: Use a template like "Service {name} is {status}" and fill in the blanks. One line of code handles all services.


πŸ› οΈ Building Your First Dynamic Log Message

Let's start with a simple example using f-strings (the most modern and readable method in Python 3.6+).

Step 1: Define your variables

  • service_name = "nginx"
  • status_code = 200
  • message = "OK"

Step 2: Create the log template

  • Use an f-string: f"Service: {service_name} | Status: {status_code} | Message: {message}"

Step 3: See the result

  • The output becomes: Service: nginx | Status: 200 | Message: OK

Now, if you change the variables to service_name = "postgresql", status_code = 500, message = "Connection timeout", the same line produces: Service: postgresql | Status: 500 | Message: Connection timeout


πŸ“Š Comparison: Different String Formatting Methods

All three methods below produce the same output. Choose the one that fits your style and Python version.

Method Syntax Example Best For
f-strings (Python 3.6+) f"User {user} logged in at {time}" Readability and speed
.format() method "User {} logged in at {}".format(user, time) Older codebases or dynamic templates
% formatting (old style) "User %s logged in at %s" % (user, time) Legacy systems or simple substitutions

πŸ•΅οΈ Real-World Scenario: Multi-Level Logging

Let's build a practical logging function that handles different severity levels and includes timestamps.

Define a log template:

  • "[{timestamp}] [{level}] {service}: {action} - {details}"

Create variables for each log entry:

  • timestamp = "2025-04-07 10:30:00"
  • level = "INFO"
  • service = "api-gateway"
  • action = "Request received"
  • details = "GET /users from IP 192.168.1.1"

Generate the log message:

  • Using an f-string: f"[{timestamp}] [{level}] {service}: {action} - {details}"
  • Output: [2025-04-07 10:30:00] [INFO] api-gateway: Request received - GET /users from IP 192.168.1.1

Now, for an error scenario, simply change the variables:

  • level = "ERROR"
  • action = "Connection failed"
  • details = "Timeout after 30s"
  • Output: [2025-04-07 10:30:00] [ERROR] api-gateway: Connection failed - Timeout after 30s

🧩 Adding Conditional Logic to Log Messages

Sometimes you need to include extra information only when certain conditions are met. You can embed expressions directly inside f-strings.

Example: Include a warning flag only if status is critical

  • status = "critical"
  • log_message = f"Disk usage at 95% {'⚠️ ACTION REQUIRED' if status == 'critical' else ''}"
  • Output: Disk usage at 95% ⚠️ ACTION REQUIRED

If status were "normal", the output would simply be: Disk usage at 95%


πŸ”„ Formatting Numbers and Alignments in Logs

Logs often contain numbers that need consistent formatting (e.g., memory usage, response times).

Format a float to two decimal places:

  • response_time = 0.34567
  • f"Response time: {response_time:.2f} seconds"
  • Output: Response time: 0.35 seconds

Align text for readable columns:

  • f"{'Service':<15} {'Status':<10} {'Uptime':<10}"
  • f"{'nginx':<15} {'Running':<10} {'72h':<10}"
  • Output (aligned):
  • Service Status Uptime
  • nginx Running 72h

🧰 Putting It All Together: A Reusable Log Builder

Here's a complete pattern you can use in your scripts. No code blocksβ€”just the logic explained.

Define a function that accepts parameters:

  • function build_log(level, service, action, details, timestamp=None)
  • Inside, set timestamp to current time if not provided.
  • Return f"[{timestamp}] [{level.upper()}] {service}: {action} - {details}"

Usage examples:

  • build_log("info", "database", "Query executed", "SELECT * FROM users, 42 rows returned")
  • Output: [2025-04-07 10:30:00] [INFO] database: Query executed - SELECT * FROM users, 42 rows returned

  • build_log("error", "web_server", "SSL handshake failed", "Certificate expired on 2025-03-01")

  • Output: [2025-04-07 10:30:00] [ERROR] web_server: SSL handshake failed - Certificate expired on 2025-03-01

βœ… Key Takeaways

  • Dynamic log messages save time and reduce errors by reusing templates.
  • f-strings are the most readable and efficient method for modern Python.
  • You can embed expressions, conditionals, and formatting directly inside f-strings.
  • Consistent formatting (timestamps, alignment, number precision) makes logs easier to parse.
  • A reusable log builder function keeps your code clean and maintainable.

πŸ“š Next Steps

  • Experiment with adding log rotation or file output to your dynamic logger.
  • Try combining string formatting with exception handling to log errors with full tracebacks.
  • Explore Python's built-in logging module for production-grade loggingβ€”it uses the same formatting principles under the hood.

This example shows how to build log messages that change based on variable values using Python string formatting.

πŸ“˜ Example 1: Simple Variable Insertion with f-strings

This example inserts a single variable into a log message using an f-string.

error_code = 404
log_message = f"Error: HTTP {error_code} - Page not found"
print(log_message)

πŸ“€ Output: Error: HTTP 404 - Page not found


πŸ“˜ Example 2: Inserting Multiple Variables into a Log Message

This example inserts multiple variables into a single log message.

user = "engineer_jane"
action = "deployed"
service = "api-gateway"
log_message = f"User {user} {action} {service} successfully"
print(log_message)

πŸ“€ Output: User engineer_jane deployed api-gateway successfully


πŸ“˜ Example 3: Including Timestamps in Log Messages

This example adds a formatted timestamp to a log message for tracking when events occur.

from datetime import datetime

timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
event = "database connection established"
log_message = f"[{timestamp}] INFO: {event}"
print(log_message)

πŸ“€ Output: [2025-03-20 14:30:45] INFO: database connection established


πŸ“˜ Example 4: Conditional Log Messages with f-strings

This example builds a log message that changes based on a condition check.

response_time_ms = 2500
threshold_ms = 2000

if response_time_ms > threshold_ms:
    severity = "WARNING"
    message = f"Response time {response_time_ms}ms exceeds threshold {threshold_ms}ms"
else:
    severity = "OK"
    message = f"Response time {response_time_ms}ms within limits"

log_message = f"[{severity}] {message}"
print(log_message)

πŸ“€ Output: [WARNING] Response time 2500ms exceeds threshold 2000ms


πŸ“˜ Example 5: Building a Multi-Line Log Entry with Dictionary Data

This example formats a structured log entry containing multiple fields from a dictionary.

log_data = {
    "user": "engineer_bob",
    "action": "rollback",
    "service": "payment-service",
    "duration_sec": 12.5,
    "success": False
}

log_entry = f"""
--- Deployment Log ---
User:     {log_data['user']}
Action:   {log_data['action']}
Service:  {log_data['service']}
Duration: {log_data['duration_sec']}s
Status:   {'FAILED' if not log_data['success'] else 'SUCCESS'}
--- End Log ---
"""
print(log_entry)

πŸ“€ Output: \n--- Deployment Log ---\nUser: engineer_bob\nAction: rollback\nService: payment-service\nDuration: 12.5s\nStatus: FAILED\n--- End Log ---\n


Comparison Table: String Formatting Methods for Log Messages

Method Syntax Best For Example
f-string f"..." Simple variable insertion f"User {name}"
.format() "{}".format() Reusing placeholders "{} {}".format(a, b)
%-formatting "%s" % var Legacy code compatibility "Error %d" % code
Template strings Template("$var") User-supplied format strings Template("$name")

🎯 Context Introduction

Logging is one of the most common tasks in any system. Whether you're monitoring servers, debugging applications, or tracking deployment pipelines, you'll constantly need to generate log messages that change based on runtime conditions. Hardcoding every log message is impractical and messy. Instead, you can build dynamic log messages using Python's string formatting techniques. This example will show you how to create flexible, readable, and reusable log messages that adapt to different scenarios.


βš™οΈ The Problem: Static vs. Dynamic Logging

Imagine you have a script that checks the status of multiple services. Without dynamic formatting, you'd write something like:

  • Static approach: Print "Service database is running" and "Service web_server is down". This works but becomes repetitive and error-prone when you have dozens of services.

  • Dynamic approach: Use a template like "Service {name} is {status}" and fill in the blanks. One line of code handles all services.


πŸ› οΈ Building Your First Dynamic Log Message

Let's start with a simple example using f-strings (the most modern and readable method in Python 3.6+).

Step 1: Define your variables

  • service_name = "nginx"
  • status_code = 200
  • message = "OK"

Step 2: Create the log template

  • Use an f-string: f"Service: {service_name} | Status: {status_code} | Message: {message}"

Step 3: See the result

  • The output becomes: Service: nginx | Status: 200 | Message: OK

Now, if you change the variables to service_name = "postgresql", status_code = 500, message = "Connection timeout", the same line produces: Service: postgresql | Status: 500 | Message: Connection timeout


πŸ“Š Comparison: Different String Formatting Methods

All three methods below produce the same output. Choose the one that fits your style and Python version.

Method Syntax Example Best For
f-strings (Python 3.6+) f"User {user} logged in at {time}" Readability and speed
.format() method "User {} logged in at {}".format(user, time) Older codebases or dynamic templates
% formatting (old style) "User %s logged in at %s" % (user, time) Legacy systems or simple substitutions

πŸ•΅οΈ Real-World Scenario: Multi-Level Logging

Let's build a practical logging function that handles different severity levels and includes timestamps.

Define a log template:

  • "[{timestamp}] [{level}] {service}: {action} - {details}"

Create variables for each log entry:

  • timestamp = "2025-04-07 10:30:00"
  • level = "INFO"
  • service = "api-gateway"
  • action = "Request received"
  • details = "GET /users from IP 192.168.1.1"

Generate the log message:

  • Using an f-string: f"[{timestamp}] [{level}] {service}: {action} - {details}"
  • Output: [2025-04-07 10:30:00] [INFO] api-gateway: Request received - GET /users from IP 192.168.1.1

Now, for an error scenario, simply change the variables:

  • level = "ERROR"
  • action = "Connection failed"
  • details = "Timeout after 30s"
  • Output: [2025-04-07 10:30:00] [ERROR] api-gateway: Connection failed - Timeout after 30s

🧩 Adding Conditional Logic to Log Messages

Sometimes you need to include extra information only when certain conditions are met. You can embed expressions directly inside f-strings.

Example: Include a warning flag only if status is critical

  • status = "critical"
  • log_message = f"Disk usage at 95% {'⚠️ ACTION REQUIRED' if status == 'critical' else ''}"
  • Output: Disk usage at 95% ⚠️ ACTION REQUIRED

If status were "normal", the output would simply be: Disk usage at 95%


πŸ”„ Formatting Numbers and Alignments in Logs

Logs often contain numbers that need consistent formatting (e.g., memory usage, response times).

Format a float to two decimal places:

  • response_time = 0.34567
  • f"Response time: {response_time:.2f} seconds"
  • Output: Response time: 0.35 seconds

Align text for readable columns:

  • f"{'Service':<15} {'Status':<10} {'Uptime':<10}"
  • f"{'nginx':<15} {'Running':<10} {'72h':<10}"
  • Output (aligned):
  • Service Status Uptime
  • nginx Running 72h

🧰 Putting It All Together: A Reusable Log Builder

Here's a complete pattern you can use in your scripts. No code blocksβ€”just the logic explained.

Define a function that accepts parameters:

  • function build_log(level, service, action, details, timestamp=None)
  • Inside, set timestamp to current time if not provided.
  • Return f"[{timestamp}] [{level.upper()}] {service}: {action} - {details}"

Usage examples:

  • build_log("info", "database", "Query executed", "SELECT * FROM users, 42 rows returned")
  • Output: [2025-04-07 10:30:00] [INFO] database: Query executed - SELECT * FROM users, 42 rows returned

  • build_log("error", "web_server", "SSL handshake failed", "Certificate expired on 2025-03-01")

  • Output: [2025-04-07 10:30:00] [ERROR] web_server: SSL handshake failed - Certificate expired on 2025-03-01

βœ… Key Takeaways

  • Dynamic log messages save time and reduce errors by reusing templates.
  • f-strings are the most readable and efficient method for modern Python.
  • You can embed expressions, conditionals, and formatting directly inside f-strings.
  • Consistent formatting (timestamps, alignment, number precision) makes logs easier to parse.
  • A reusable log builder function keeps your code clean and maintainable.

πŸ“š Next Steps

  • Experiment with adding log rotation or file output to your dynamic logger.
  • Try combining string formatting with exception handling to log errors with full tracebacks.
  • Explore Python's built-in logging module for production-grade loggingβ€”it uses the same formatting principles under the hood.

Interactive Views

You are currently in πŸ“š All-in-One mode. Use the tabs at the top to switch to πŸ“– Theory Only or πŸ’» Code Only views.

This example shows how to build log messages that change based on variable values using Python string formatting.

πŸ“˜ Example 1: Simple Variable Insertion with f-strings

This example inserts a single variable into a log message using an f-string.

error_code = 404
log_message = f"Error: HTTP {error_code} - Page not found"
print(log_message)

πŸ“€ Output: Error: HTTP 404 - Page not found


πŸ“˜ Example 2: Inserting Multiple Variables into a Log Message

This example inserts multiple variables into a single log message.

user = "engineer_jane"
action = "deployed"
service = "api-gateway"
log_message = f"User {user} {action} {service} successfully"
print(log_message)

πŸ“€ Output: User engineer_jane deployed api-gateway successfully


πŸ“˜ Example 3: Including Timestamps in Log Messages

This example adds a formatted timestamp to a log message for tracking when events occur.

from datetime import datetime

timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
event = "database connection established"
log_message = f"[{timestamp}] INFO: {event}"
print(log_message)

πŸ“€ Output: [2025-03-20 14:30:45] INFO: database connection established


πŸ“˜ Example 4: Conditional Log Messages with f-strings

This example builds a log message that changes based on a condition check.

response_time_ms = 2500
threshold_ms = 2000

if response_time_ms > threshold_ms:
    severity = "WARNING"
    message = f"Response time {response_time_ms}ms exceeds threshold {threshold_ms}ms"
else:
    severity = "OK"
    message = f"Response time {response_time_ms}ms within limits"

log_message = f"[{severity}] {message}"
print(log_message)

πŸ“€ Output: [WARNING] Response time 2500ms exceeds threshold 2000ms


πŸ“˜ Example 5: Building a Multi-Line Log Entry with Dictionary Data

This example formats a structured log entry containing multiple fields from a dictionary.

log_data = {
    "user": "engineer_bob",
    "action": "rollback",
    "service": "payment-service",
    "duration_sec": 12.5,
    "success": False
}

log_entry = f"""
--- Deployment Log ---
User:     {log_data['user']}
Action:   {log_data['action']}
Service:  {log_data['service']}
Duration: {log_data['duration_sec']}s
Status:   {'FAILED' if not log_data['success'] else 'SUCCESS'}
--- End Log ---
"""
print(log_entry)

πŸ“€ Output: \n--- Deployment Log ---\nUser: engineer_bob\nAction: rollback\nService: payment-service\nDuration: 12.5s\nStatus: FAILED\n--- End Log ---\n


Comparison Table: String Formatting Methods for Log Messages

Method Syntax Best For Example
f-string f"..." Simple variable insertion f"User {name}"
.format() "{}".format() Reusing placeholders "{} {}".format(a, b)
%-formatting "%s" % var Legacy code compatibility "Error %d" % code
Template strings Template("$var") User-supplied format strings Template("$name")