You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask服务中Python Logger自定义字段不更新问题及优化咨询

Let me break down what's going wrong here, and show you a more robust way to add custom fields to your Flask logs.

First, the issue with your current code: While LoggerAdapter is supposed to merge the extra parameter you pass to info() with the initial extra dict, Flask's debug mode can interfere with your logging setup, or the adapter's merge logic isn't triggering correctly. That's why your data field is stuck on the initial value 0 instead of updating to 23.

Better Approach: Use a Custom Log Filter

Instead of relying on LoggerAdapter, a custom logging.Filter is more reliable and flexible—especially in Flask, where you might want to automatically include request-related context (like path, method, or client IP) alongside your custom data.

Here's a step-by-step implementation:

1. Create a Custom Filter

This filter will inject default values for custom fields, automatically add request context data when available, and respect any custom values you pass explicitly:

from flask import Flask, request, has_request_context
from flask_cors import CORS
import logging
import json

class CustomLogFilter(logging.Filter):
    def filter(self, record):
        # Set a default value for 'data' if none is provided
        if not hasattr(record, 'data'):
            record.data = 0
        
        # Add Flask request context fields when a request is active
        if has_request_context():
            record.request_path = request.path
            record.request_method = request.method
            record.remote_addr = request.remote_addr
        
        return True

2. Configure Your Logger Properly

Set up the logger with a valid JSON formatter, attach your custom filter, and clean up Flask's default handlers to avoid duplicate logs:

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

# Remove Flask's default handlers to prevent conflicting log output
for handler in logger.handlers[:]:
    logger.removeHandler(handler)

# Create a stream handler and attach our custom filter
ch = logging.StreamHandler()
ch.addFilter(CustomLogFilter())

# Fix the JSON formatter (fix syntax errors and add proper quotes for valid JSON)
formatter = logging.Formatter("""{
    "name": "%(name)s",
    "module_name": "%(module)s",
    "pid": %(process)d,
    "level": %(levelno)d,
    "level_name": "%(levelname)s",
    "msg": "%(message)s",
    "data": %(data)s,
    "time": "%(asctime)s",
    "src": {
        "file": "%(pathname)s",
        "line": %(lineno)d
    },
    "function": "%(funcName)s",
    "request_path": "%(request_path)s",
    "request_method": "%(request_method)s",
    "remote_addr": "%(remote_addr)s"
}""")

ch.setFormatter(formatter)
logger.addHandler(ch)

3. Use the Logger in Your Flask Routes

Now you can pass custom data directly via the extra parameter whenever you log:

app = Flask(__name__)
CORS(app)

@app.route('/home', methods=["GET"])
def home():
    logger.info("OK", extra={"data": 0})
    return "OK"

@app.route('/user', methods=["POST"])
def user_check():
    req_data = json.loads(request.data)
    logger.info("User check request received", extra={"data": 23})
    return "Check Complete"

if __name__ == "__main__":
    app.run('0.0.0.0', debug=True)

Why This Works Better

  • Flexibility: Automatically adds request context fields (like path, method, and client IP) to every log generated during a request—critical for debugging Flask apps.
  • Reliability: No more issues with LoggerAdapter's dict merging; custom fields passed via extra will always be respected.
  • Valid JSON: The formatter now produces properly formatted JSON, making it easy to parse logs with tools like ELK, Splunk, or even just jq.

Fixing Your Original LoggerAdapter Code (If You Prefer)

If you want to stick with LoggerAdapter, the main fix is to remove Flask's default handlers before adding your own, and clean up the formatter's syntax errors:

# After creating your logger, remove default handlers
for handler in logger.handlers[:]:
    logger.removeHandler(handler)

# Then create your adapter as before
adapter = logging.LoggerAdapter(logger=logger, extra=dict(data_=0))

Also fix the typo in your formatter: change "name":,%(name)s, to "name": "%(name)s", to avoid invalid JSON. This should make the data_ field update correctly when you pass extra=dict(data_=23).

内容的提问来源于stack exchange,提问作者Sociopath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:21:21