Fastapi 日志处理
uvicorn 日志处理总结:
一、日志的结构
日志结构如下:
{"version": 1,"disable_existing_loggers": false,"formatters": {},"handlers": {},"loggers": {}
}
loggers 用于定义日志处理最顶层的标识,必须有一个uvicorn,是所有日志处理的父类
handlers用于日志输出目的地配置,如输出到终端、文件等
formatters用于日志具体格式的配置,如时间戳、请求类型、状态码等
二、logger中配置的继承关系
logger中存在继承关系,uvicorn是父类,uvicorn.error是子类 uvicorn也是子类。子类可以继承父类的配置,比如uvicorn.error没有配置handlers,那么就会继承uvicorn的配置。
uvicorn
记录器会处理所有 Uvicorn 生成的日志,包括错误日志。
"uvicorn": {"handlers": ["default", "default_file"],"level": "INFO","propagate": false},"uvicorn.error": {"level": "INFO"},"uvicorn.access": {"handlers": ["access", "access_file"],"level": "INFO","propagate": false}}
三、formatters 中的两种错误日志
formatters 中包含两种日志格式:default 和 access,两者功能不同。这两者是uvicorn默认,也可以自定义其他格式。
- default: 用于记录 Uvicorn 的常规日志,包括服务器启动、停止、错误信息等。
- access:用于记录 HTTP 请求的访问日志,包括客户端 IP、请求方法、请求路径、响应状态码等。
四、错误日志
uvicorn 会在default中将所有的日志都输出,包括错误日志。如果想单独处理错误日志,可以在loggers中定义错误日志记录器uvicorn.error,然后在handlers中指定错误日志的输出目的地,最后使用default格式输出。可以选择将错误日志同时输出到uvicorn和uvicorn.error两个记录器中,也可以选择只输出到uvicor.error记录器中。
uvicorn 日志系统
Uvicorn 的日志配置文件可以使用 JSON、YAML 或 INI 三种格式。以下是对 Uvicorn 日志配置文件的详细解析:
1. 基本结构
Uvicorn 的日志配置文件遵循 Python 的 logging
模块的配置格式,其基本结构如下:
{"version": 1,"disable_existing_loggers": false,"formatters": {},"handlers": {},"loggers": {}
}
2. 配置项详解
2.1 version
- 类型: 整数
- 默认值: 1
- 说明: 指定配置文件的版本,目前 Uvicorn 只支持版本 1。
2.2 disable_existing_loggers
- 类型: 布尔值
- 默认值:
false
- 说明: 是否禁用已存在的日志记录器。如果设置为
true
,则会禁用所有已存在的日志记录器,除非它们在loggers
部分被显式配置。
2.3 formatters
- 类型: 字典
- 说明: 定义日志格式化器,用于格式化日志消息。每个格式化器是一个字典,包含以下键:
()
: 指定格式化器类的路径。fmt
: 日志格式字符串。datefmt
: 日期格式字符串(可选)。style
: 格式化风格,可以是%
、{
或$
(可选)。
例如:
"formatters": {"default": {"()": "uvicorn.logging.DefaultFormatter","fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(message)s","use_colors": null},"access": {"()": "uvicorn.logging.AccessFormatter","fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(client_addr)s - '%(request_line)s' %(status_code)s"}
}
2.4 handlers
- 类型: 字典
- 说明: 定义日志处理器,用于将日志消息输出到不同的目的地。每个处理器是一个字典,包含以下键:
class
: 指定处理器类的路径。formatter
: 指定使用的格式化器名称。stream
: 指定输出流(对于StreamHandler
)。filename
: 指定日志文件路径(对于FileHandler
或TimedRotatingFileHandler
)。when
: 指定日志文件轮转的时间间隔(对于TimedRotatingFileHandler
)。backupCount
: 指定备份文件的数量(对于TimedRotatingFileHandler
)。encoding
: 指定文件编码(可选)。
例如:
"handlers": {"default": {"formatter": "default","class": "logging.StreamHandler","stream": "ext://sys.stderr"},"default_file": {"formatter": "default","class": "logging.handlers.TimedRotatingFileHandler","filename": "./logs/app.log","when": "midnight","encoding": "utf-8","backupCount": 10},"access": {"formatter": "access","class": "logging.StreamHandler","stream": "ext://sys.stdout"},"access_file": {"formatter": "access","class": "logging.handlers.TimedRotatingFileHandler","filename": "./logs/access.log","when": "midnight","encoding": "utf-8","backupCount": 10}
}
2.5 loggers
- 类型: 字典
- 说明: 定义日志记录器,用于控制日志的输出。每个记录器是一个字典,包含以下键:
handlers
: 指定使用的处理器名称列表。level
: 指定日志级别,如INFO
、DEBUG
、ERROR
等。propagate
: 是否将日志消息传递给父记录器。
例如:
"loggers": {"uvicorn": {"handlers": ["default", "default_file"],"level": "INFO","propagate": false},"uvicorn.error": {"level": "INFO"},"uvicorn.access": {"handlers": ["access", "access_file"],"level": "INFO","propagate": false}
}
3. 示例配置文件
以下是一个完整的 Uvicorn 日志配置文件示例,将日志输出到控制台和本地文件:
{"version": 1,"disable_existing_loggers": false,"formatters": {"default": {"()": "uvicorn.logging.DefaultFormatter","fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(message)s","use_colors": null},"access": {"()": "uvicorn.logging.AccessFormatter","fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(client_addr)s - '%(request_line)s' %(status_code)s"}},"handlers": {"default": {"formatter": "default","class": "logging.StreamHandler","stream": "ext://sys.stderr"},"default_file": {"formatter": "default","class": "logging.handlers.TimedRotatingFileHandler","filename": "./logs/app.log","when": "midnight","encoding": "utf-8","backupCount": 10},"access": {"formatter": "access","class": "logging.StreamHandler","stream": "ext://sys.stdout"},"access_file": {"formatter": "access","class": "logging.handlers.TimedRotatingFileHandler","filename": "./logs/access.log","when": "midnight","encoding": "utf-8","backupCount": 10}},"loggers": {"uvicorn": {"handlers": ["default", "default_file"],"level": "INFO","propagate": false},"uvicorn.error": {"level": "INFO"},"uvicorn.access": {"handlers": ["access", "access_file"],"level": "INFO","propagate": false}}
}
4. 使用配置文件
在启动 Uvicorn 时,可以通过 --log-config
参数指定日志配置文件的路径。例如:
uvicorn run:app --host 0.0.0.0 --port 8000 --log-config ./uvicorn_config.json
或者在 Python 代码中使用 uvicorn.run
方法:
import uvicornif __name__ == "__main__":uvicorn.run(app='main:app', host="0.0.0.0", log_config='./uvicorn_config.json', port=8000, loop="asyncio")
希望这些信息对你有所帮助!
default 和 access 日志处理器
在 Uvicorn 中,default
和 access
日志格式化器(formatter)的主要区别在于它们记录的内容和用途:
1. default
格式化器
- 用途: 用于记录 Uvicorn 的常规日志,包括服务器启动、停止、错误信息等。
- 内容: 通常包含日志级别、时间戳、线程名称、日志消息等。
- 示例格式:
"default": {"()": "uvicorn.logging.DefaultFormatter","fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(message)s","use_colors": null
}
这里,%(asctime)s
表示时间戳,%(threadName)s
表示线程名称,%(levelprefix)s
表示日志级别前缀,%(message)s
表示日志消息。
2. access
格式化器
- 用途: 用于记录 HTTP 请求的访问日志,包括客户端 IP、请求方法、请求路径、响应状态码等。
- 内容: 通常包含客户端 IP 地址、请求行、响应状态码等。
- 示例格式:
"access": {"()": "uvicorn.logging.AccessFormatter","fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(client_addr)s - '%(request_line)s' %(status_code)s"
}
这里,%(asctime)s
表示时间戳,%(threadName)s
表示线程名称,%(levelprefix)s
表示日志级别前缀,%(client_addr)s
表示客户端 IP 地址,%(request_line)s
表示请求行(如 GET /path HTTP/1.1
),%(status_code)s
表示响应状态码。
3. 配置示例
以下是一个完整的 Uvicorn 日志配置文件示例,展示了如何配置 default
和 access
日志格式化器,并将它们分别输出到不同的处理器(handlers)和日志记录器(loggers):
{"version": 1,"disable_existing_loggers": false,"formatters": {"default": {"()": "uvicorn.logging.DefaultFormatter","fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(message)s","use_colors": null},"access": {"()": "uvicorn.logging.AccessFormatter","fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(client_addr)s - '%(request_line)s' %(status_code)s"}},"handlers": {"default": {"formatter": "default","class": "logging.StreamHandler","stream": "ext://sys.stderr"},"default_file": {"formatter": "default","class": "logging.handlers.TimedRotatingFileHandler","filename": "./logs/app.log","when": "midnight","encoding": "utf-8","backupCount": 10},"access": {"formatter": "access","class": "logging.StreamHandler","stream": "ext://sys.stdout"},"access_file": {"formatter": "access","class": "logging.handlers.TimedRotatingFileHandler","filename": "./logs/access.log","when": "midnight","encoding": "utf-8","backupCount": 10}},"loggers": {"uvicorn": {"handlers": ["default", "default_file"],"level": "INFO","propagate": false},"uvicorn.error": {"level": "INFO"},"uvicorn.access": {"handlers": ["access", "access_file"],"level": "INFO","propagate": false}}
}
4. 启动 Uvicorn
使用配置文件启动 Uvicorn:
uvicorn run:app --host 0.0.0.0 --port 8000 --log-config ./uvicorn_config.json
或者在 Python 代码中使用 uvicorn.run
方法:
import uvicornif __name__ == "__main__":uvicorn.run(app='main:app', host="0.0.0.0", log_config='./uvicorn_config.json', port=8000, loop="asyncio")
通过上述配置,default
日志将记录 Uvicorn 的常规日志,而 access
日志将记录 HTTP 请求的访问日志,两者分别输出到不同的文件中。
错误日志
在 Uvicorn 的日志配置中,如果 uvicorn.error
日志记录器没有显式配置 handlers
,它将继承父记录器的处理器。默认情况下,uvicorn.error
的父记录器是 uvicorn
,因此它会使用 uvicorn
记录器配置的处理器来记录日志。
默认行为
如果没有显式配置 uvicorn.error
的 handlers
,Uvicorn 会使用 uvicorn
记录器的处理器。例如,如果 uvicorn
记录器配置了控制台输出和文件输出,uvicorn.error
也会使用这些处理器。
示例配置
假设你的日志配置文件如下:
{"version": 1,"disable_existing_loggers": false,"formatters": {"default": {"()": "uvicorn.logging.DefaultFormatter","fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(message)s","use_colors": null}},"handlers": {"default": {"formatter": "default","class": "logging.StreamHandler","stream": "ext://sys.stderr"},"file": {"formatter": "default","class": "logging.handlers.TimedRotatingFileHandler","filename": "./logs/app.log","when": "midnight","encoding": "utf-8","backupCount": 10}},"loggers": {"uvicorn": {"handlers": ["default", "file"],"level": "INFO","propagate": false},"uvicorn.error": {"level": "ERROR","propagate": true},"uvicorn.access": {"handlers": ["default"],"level": "INFO","propagate": false}}
}
解释
uvicorn
** 记录器**:- 配置了两个处理器:
default
(控制台输出)和file
(文件输出)。 - 日志级别为
INFO
。 propagate
设置为false
,表示不将日志消息传递给父记录器。
- 配置了两个处理器:
uvicorn.error
** 记录器**:- 没有显式配置
handlers
,但propagate
设置为true
。 - 日志级别为
ERROR
。 - 由于
propagate
为true
,uvicorn.error
会将日志消息传递给父记录器uvicorn
,因此会使用uvicorn
配置的处理器default
和file
。
- 没有显式配置
结果
- 控制台输出:
uvicorn.error
的日志消息会输出到控制台。
- 文件输出:
uvicorn.error
的日志消息会输出到./logs/app.log
文件中。
总结
如果 uvicorn.error
没有显式配置 handlers
,它会继承父记录器 uvicorn
的处理器。通过设置 propagate
为 true
,可以确保 uvicorn.error
的日志消息被正确记录到控制台和文件中。如果 propagate
为 false
,则 uvicorn.error
不会记录任何日志,除非你显式配置了处理器。
错误日志
如果在 Uvicorn 的日志配置文件中没有显式配置 uvicorn.error
记录器,Uvicorn 仍然会记录错误日志,但具体记录方式取决于 uvicorn
记录器的配置。
默认行为
在默认情况下,uvicorn
记录器会处理所有 Uvicorn 生成的日志,包括错误日志。如果 uvicorn
记录器配置了处理器(handlers),这些处理器将用于记录所有日志,包括错误日志。
示例配置
假设你的日志配置文件如下:
{"version": 1,"disable_existing_loggers": false,"formatters": {"default": {"()": "uvicorn.logging.DefaultFormatter","fmt": "%(asctime)s %(threadName)s %(levelprefix)s %(message)s","use_colors": null}},"handlers": {"default": {"formatter": "default","class": "logging.StreamHandler","stream": "ext://sys.stderr"},"file": {"formatter": "default","class": "logging.handlers.TimedRotatingFileHandler","filename": "./logs/app.log","when": "midnight","encoding": "utf-8","backupCount": 10}},"loggers": {"uvicorn": {"handlers": ["default", "file"],"level": "INFO","propagate": false},"uvicorn.access": {"handlers": ["default"],"level": "INFO","propagate": false}}
}
解释
uvicorn
** 记录器**:- 配置了两个处理器:
default
(控制台输出)和file
(文件输出)。 - 日志级别为
INFO
。 propagate
设置为false
,表示不将日志消息传递给父记录器。
- 配置了两个处理器:
uvicorn.access
** 记录器**:- 配置了
default
处理器(控制台输出)。 - 日志级别为
INFO
。 propagate
设置为false
,表示不将日志消息传递给父记录器。
- 配置了
错误日志记录
- 控制台输出:
- 由于
uvicorn
记录器配置了default
处理器,错误日志会输出到控制台。
- 由于
- 文件输出:
- 由于
uvicorn
记录器配置了file
处理器,错误日志会输出到./logs/app.log
文件中。
- 由于
总结
即使没有显式配置 uvicorn.error
记录器,Uvicorn 仍然会记录错误日志,因为 uvicorn
记录器会处理所有日志,包括错误日志。错误日志将根据 uvicorn
记录器配置的处理器进行输出。
如果你希望更细粒度地控制错误日志的记录方式,可以显式配置 uvicorn.error
记录器,并为其指定特定的处理器。例如:
"uvicorn.error": {"handlers": ["error_file"],"level": "ERROR","propagate": false
}
这样,错误日志将只使用 error_file
处理器进行记录,而不会影响其他日志的记录方式。
handler中输出日志到文件
两种文件输出的配置方式:
"file": {"formatter": "default","class": "logging.handlers.RotatingFileHandler","maxBytes": 209715200,"backupCount": 1,"mode": "w+","filename": "./log/api.log"},"file": {"formatter": "default","class": "logging.handlers.TimedRotatingFileHandler","filename": "app/server/log/api.log","when": "midnight","encoding": "utf-8","backupCount": 10}