/

Django Integration

Django Integration

Integrate ByteHide Logs with Django using middleware to automatically track requests, user actions, and errors across your entire application.

Setup

Install the Django integration:

Bash
pip install bytehide-logs[django]

Add the ByteHide logging middleware to your Django settings:

Python
# settings.py

MIDDLEWARE = [
    # ... other middleware ...
    'bytehide_logs.django.ByteHideLoggingMiddleware',
]

# Configure ByteHide Logs
from bytehide_logs import Log, LogSettings
from datetime import timedelta

settings = LogSettings(
    duplicate_suppression_window=timedelta(seconds=5),
    mask_sensitive_data=["password", "token", "api_key"]
)

Log.configure(settings)

# Application metadata
Log.add_meta_context("service", "django-app")
Log.add_meta_context("environment", os.environ.get("ENVIRONMENT", "development"))

Middleware Setup

The middleware automatically:

  • Tracks incoming requests with correlation IDs
  • Logs request processing time
  • Captures user information
  • Handles errors and exceptions
  • Cleans up context after request
Python
# settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    # ... other apps ...
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'bytehide_logs.django.ByteHideLoggingMiddleware',  # Add here
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
]

Request Tracking

The middleware automatically logs all requests:

Python
# Middleware automatically logs:
# - Request method and path
# - Client IP address
# - Correlation ID
# - Response status code
# - Request duration

To access the correlation ID in your views:

Python
from django.http import JsonResponse
from bytehide_logs import Log

def my_view(request):
    """View with access to correlation ID."""
    # Correlation ID is available from request
    correlation_id = getattr(request, 'correlation_id', None)
    
    Log.with_context("view", "my_view") \
        .with_correlation_id(correlation_id) \
        .info("Processing view")
    
    return JsonResponse({"message": "Success"})

User Identification

Identify authenticated Django users automatically:

Python
# views.py
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from bytehide_logs import Log, AuthUser

@login_required
def user_profile(request):
    """View with authenticated user tracking."""
    user = request.user
    
    # Identify user in logs
    auth_user = AuthUser(
        id=str(user.id),
        email=user.email
    )
    Log.identify(auth_user)
    
    Log.with_tags("user", "profile").info("Viewing user profile")
    
    return JsonResponse({
        "user_id": user.id,
        "email": user.email
    })

Model Operations Logging

Log database operations:

Python
# models.py
from django.db import models
from bytehide_logs import Log

class User(models.Model):
    """User model with logging."""
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=100)
    
    def save(self, *args, **kwargs):
        """Save with logging."""
        is_new = not self.pk
        
        if is_new:
            Log.with_tags("model", "user", "create") \
                .with_context("email", self.email) \
                .info("Creating user")
        else:
            Log.with_tags("model", "user", "update") \
                .with_context("user_id", self.id) \
                .with_context("email", self.email) \
                .info("Updating user")
        
        super().save(*args, **kwargs)
        
        if is_new:
            Log.with_tags("model", "user", "create", "success") \
                .with_context("user_id", self.id) \
                .info("User created")
    
    def delete(self, *args, **kwargs):
        """Delete with logging."""
        Log.with_tags("model", "user", "delete") \
            .with_context("user_id", self.id) \
            .info("Deleting user")
        
        super().delete(*args, **kwargs)
        
        Log.with_tags("model", "user", "delete", "success") \
            .info("User deleted")

Signal Handling

Use Django signals with logging:

Python
# signals.py
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.contrib.auth.models import User
from bytehide_logs import Log

@receiver(post_save, sender=User)
def user_created(sender, instance, created, **kwargs):
    """Log user creation."""
    if created:
        Log.with_tags("user", "created") \
            .with_context("user_id", instance.id) \
            .with_context("email", instance.email) \
            .info("User created via signal")

@receiver(post_delete, sender=User)
def user_deleted(sender, instance, **kwargs):
    """Log user deletion."""
    Log.with_tags("user", "deleted") \
        .with_context("user_id", instance.id) \
        .info("User deleted via signal")

Exception Handling

Log exceptions in views:

Python
# views.py
from django.http import JsonResponse
from bytehide_logs import Log
from django.views.decorators.http import require_http_methods

@require_http_methods(["POST"])
def process_payment(request):
    """Process payment with error handling."""
    try:
        data = request.POST
        
        Log.with_tags("payment", "process").info("Processing payment")
        
        # Validate data
        if not data.get("amount"):
            raise ValueError("Amount is required")
        
        # Process payment
        result = charge_card(
            card_token=data.get("token"),
            amount=int(data.get("amount"))
        )
        
        Log.with_tags("payment", "success") \
            .with_context("transaction_id", result.id) \
            .with_context("amount", data.get("amount")) \
            .info("Payment processed successfully")
        
        return JsonResponse({
            "transaction_id": result.id,
            "status": "success"
        })
        
    except ValueError as e:
        Log.warning("Payment validation failed", exception=e)
        return JsonResponse({"error": str(e)}, status=400)
        
    except Exception as e:
        Log.error("Payment processing failed", exception=e)
        return JsonResponse({"error": "Payment failed"}, status=500)

Complete Django Example

Python
# views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from bytehide_logs import Log, AuthUser
import uuid

@require_http_methods(["POST"])
def user_login(request):
    """User login view with logging."""
    try:
        username = request.POST.get("username")
        password = request.POST.get("password")
        
        Log.with_tags("auth", "login") \
            .with_context("username", username) \
            .info("Login attempt")
        
        # Authenticate user
        user = authenticate(request, username=username, password=password)
        
        if user is not None:
            # Login successful
            login(request, user)
            
            # Identify user in logs
            auth_user = AuthUser(
                id=str(user.id),
                email=user.email
            )
            Log.identify(auth_user)
            
            Log.with_tags("auth", "login", "success").info("Login successful")
            
            return redirect('dashboard')
        else:
            # Login failed
            Log.with_tags("auth", "login", "failed") \
                .with_context("username", username) \
                .warning("Login failed - invalid credentials")
            
            return JsonResponse({"error": "Invalid credentials"}, status=401)
            
    except Exception as e:
        Log.with_tags("auth", "login", "error") \
            .error("Login error", exception=e)
        return JsonResponse({"error": "Login error"}, status=500)

@require_http_methods(["POST"])
def user_logout(request):
    """User logout view."""
    Log.with_tags("auth", "logout").info("Logout initiated")
    
    logout(request)
    
    Log.with_tags("auth", "logout", "success").info("Logout completed")
    Log.logout()
    
    return redirect('login')

@login_required
def user_profile(request):
    """User profile view."""
    user = request.user
    
    # Identify user
    auth_user = AuthUser(id=str(user.id), email=user.email)
    Log.identify(auth_user)
    
    Log.with_tags("user", "profile") \
        .with_context("user_id", user.id) \
        .info("Accessing user profile")
    
    return render(request, 'profile.html', {
        'user': user
    })

@login_required
@require_http_methods(["PUT"])
def update_profile(request):
    """Update user profile."""
    try:
        import json
        data = json.loads(request.body)
        user = request.user
        
        Log.with_tags("user", "profile", "update") \
            .with_context("user_id", user.id) \
            .with_context("fields", list(data.keys())) \
            .info("Updating user profile")
        
        # Update user fields
        if 'email' in data:
            user.email = data['email']
        if 'first_name' in data:
            user.first_name = data['first_name']
        if 'last_name' in data:
            user.last_name = data['last_name']
        
        user.save()
        
        Log.with_tags("user", "profile", "update", "success") \
            .with_context("user_id", user.id) \
            .info("User profile updated")
        
        return JsonResponse({"status": "success"})
        
    except Exception as e:
        Log.error("Profile update failed", exception=e)
        return JsonResponse({"error": "Update failed"}, status=500)

@login_required
@require_http_methods(["POST"])
def process_order(request):
    """Process user order."""
    try:
        import json
        data = json.loads(request.body)
        user = request.user
        
        correlation_id = str(uuid.uuid4())
        
        Log.with_tags("order", "process") \
            .with_context("user_id", user.id) \
            .with_context("order_total", data.get("total")) \
            .with_correlation_id(correlation_id) \
            .info("Processing order")
        
        # Validate cart
        Log.with_tags("order", "validation") \
            .with_correlation_id(correlation_id) \
            .info("Validating order")
        validate_order(data)
        
        # Process payment
        Log.with_tags("order", "payment") \
            .with_correlation_id(correlation_id) \
            .info("Processing payment")
        payment = process_payment(data)
        
        # Create order record
        Log.with_tags("order", "create") \
            .with_context("order_id", payment.id) \
            .with_correlation_id(correlation_id) \
            .info("Creating order record")
        
        Log.with_tags("order", "complete") \
            .with_context("order_id", payment.id) \
            .with_correlation_id(correlation_id) \
            .info("Order processed successfully")
        
        return JsonResponse({
            "order_id": payment.id,
            "correlation_id": correlation_id
        })
        
    except Exception as e:
        Log.error("Order processing failed", exception=e)
        return JsonResponse({"error": "Order failed"}, status=500)

URL Configuration

Log API endpoints:

Python
# urls.py
from django.contrib import admin
from django.urls import path
from bytehide_logs import Log

# Log URL configuration
Log.info("Configuring Django URLs")

urlpatterns = [
    path('admin/', admin.site.urls),
    path('auth/login/', views.user_login, name='login'),
    path('auth/logout/', views.user_logout, name='logout'),
    path('api/profile/', views.user_profile, name='profile'),
    path('api/profile/update/', views.update_profile, name='update_profile'),
    path('api/order/process/', views.process_order, name='process_order'),
]

Best Practices

Always identify authenticated users:

Python
user = request.user
if user.is_authenticated:
    auth_user = AuthUser(id=str(user.id), email=user.email)
    Log.identify(auth_user)

Use correlation IDs for multi-step operations:

Python
correlation_id = getattr(request, 'correlation_id', None)
Log.with_correlation_id(correlation_id).info("Processing step")

Log model operations for audit trails:

Python
def save(self, *args, **kwargs):
    Log.with_tags("model", self.__class__.__name__).info("Saving model")
    super().save(*args, **kwargs)

Next Steps

Previous
Flask