简体   繁体   English

如何在扭曲中设置日志记录级别?

[英]How to set logging level in twisted?

I am using autobahn package with twisted which shows debug message for me every connect to websocket.我正在使用带有twisted 的高速公路包,它在每次连接到websocket 时都会为我显示调试消息。 I tried to switch logging level to info but had no success:我尝试将日志记录级别切换为 info 但没有成功:

import logging
logging.basicConfig(level=logging.INFO)

Is there an easy way to switch log level?有没有简单的方法来切换日志级别?

Updated.更新。

Here is the twisted_service.py:这是twisted_service.py:

from twisted.application import service
from twisted.logger import Logger
import logging
logging.basicConfig(level=logging.INFO)


class WebsocketService(service.Service):
    log = Logger()

    def startService(self):
        service.Service.startService(self)
        self.log.debug('start service')

application = service.Application("ws")

ws_service = WebsocketService()
ws_service.setServiceParent(application)

I run it using twistd script: twistd -noy twisted_service.py And i get a message:我使用twisd脚本运行它: twisd -noy twisted_service.py然后我收到一条消息:

2018-03-03T10:45:22+0500 [ builtin .WebsocketService#debug] start service 2018-03-03T10:45:22+0500 [内置.WebsocketService#debug] 启动服务

logging.basicConfig didn't help. logging.basicConfig 没有帮助。

I found the solution:我找到了解决方案:

import sys
from twisted.application import service
from twisted.logger import LogLevelFilterPredicate, LogLevel
from twisted.logger import textFileLogObserver, FilteringLogObserver


class WebsocketService(service.Service):
    log = Logger()

    def startService(self):
        service.Service.startService(self)
        self.log.debug('start service')

application = service.Application("ws")

ws_service = WebsocketService()
ws_service.setServiceParent(application)

info_predicate = LogLevelFilterPredicate(LogLevel.info)
log_observer = FilteringLogObserver(textFileLogObserver(sys.stdout), predicates=info_predicate)

application.setComponent(ILogObserver, log_observer)

To find all loggers and their corresponding names execute:要查找所有记录器及其对应的名称,请执行:

logging.Logger.manager.loggerDict.keys()

Try to set it explicitly by getting the noisy logger instance:尝试通过获取嘈杂的记录器实例来明确设置它:

import logging

noisyLogger = logging.getLogger("autobahn")  # adjust logger name
# noisyLogger.getEffectiveLevel()  # indicates the current effective level
noisyLogger.setLevel(logging.INFO)

I used kalombo's answer to figure out a solution for my own project, which I'll share the meat of here since I couldn't find much accessible info on this subject, and I still had to figure out a few things.我使用 kalombo 的答案为我自己的项目找出了一个解决方案,我将在这里分享内容,因为我找不到关于这个主题的太多可访问的信息,而且我仍然需要弄清楚一些事情。 This example allows us to log to both stdout and a file, and choose a different log level for each.这个例子允许我们同时记录到标准输出和一个文件,并为每个选择不同的日志级别。

(Thanks also to https://stackoverflow.com/a/46651223/213445 regarding logging to multiple files.) (还要感谢https://stackoverflow.com/a/46651223/213445关于记录到多个文件。)

Here's the breakdown:这是细分:

  • The variable "logtargets" is a list of FilteringLogObserver instances.变量“logtargets”是 FilteringLogObserver 实例的列表。
  • Each FilteringLogObserver wraps a textFileLogObserver, and imposes a LogLevelFilterPredicate.每个 FilteringLogObserver 包装一个 textFileLogObserver,并施加一个 LogLevelFilterPredicate。 We do this once for stdout and once for our "logfile".我们为 stdout 执行一次,为我们的“日志文件”执行一次。
  • The LogLevelFilterPredicate conveys a maximum LogLevel to FilteringLogObserver through its "predicates" argument. LogLevelFilterPredicate 通过其“谓词”参数将最大LogLevel 传达给 FilteringLogObserver。
  • The "predicates" argument to FilteringLogObserver must be iterable , so we wrap LogLevelFilterPredicate in a list when passing it. FilteringLogObserver 的“谓词”参数必须是可迭代的,因此我们在传递它时将 LogLevelFilterPredicate 包装在一个列表中。
  • At the end, we pass our "logtargets" list to globalLogBeginner.beginLoggingTo().最后,我们将“logtargets”列表传递给 globalLogBeginner.beginLoggingTo()。
  • All future Twisted Logger instances will point to both of our log targets.所有未来的 Twisted Logger 实例都将指向我们的两个日志目标。
  • We can have multiple instances of Logger, one for each subsystem of our program, and for each one we give it a single argument, which is the namespace for log lines from that subsystem.我们可以有多个 Logger 实例,一个用于我们程序的每个子系统,并且为每个实例提供一个参数,即来自该子系统的日志行的命名空间。
import sys
from twisted.logger import Logger, LogLevel, LogLevelFilterPredicate, \
    textFileLogObserver, FilteringLogObserver, globalLogBeginner

logfile = open("application.log", 'a')
logtargets = []

# Set up the log observer for stdout.
logtargets.append(
    FilteringLogObserver(
        textFileLogObserver(sys.stdout),
        predicates=[LogLevelFilterPredicate(LogLevel.warn)]
    )
)

# Set up the log observer for our log file. "debug" is the highest possible level.
logtargets.append(
    FilteringLogObserver(
        textFileLogObserver(logfile),
        predicates=[LogLevelFilterPredicate(LogLevel.debug)]
    )
)

# Direct the Twisted Logger to log to both of our observers.
globalLogBeginner.beginLoggingTo(logtargets)

# Start a logger with a namespace for a particular subsystem of our application.
log = Logger("mynamespace")

log.warn("Goes to both outputs.") # Outputs will start with [mynamespace#warn]
log.error("Also go to both outputs; error is higher priority than warn.")
log.debug("Only goes to log file.")
log.info("Also only goes to log file; info is lower priority than warn.")

In this example snippet, I demonstrate a scenario of integrating Twisted logging into another (custom) logging system (the code for which I've omitted).在此示例片段中,我演示了将 Twisted 日志记录集成到另一个(自定义)日志记录系统(我省略了代码)的场景。 In this case, the other logger is managing a file object, stdout/err redirects, file rotations etc. I just wanted to to have Twisted supplement that other system and send it's messages over that effectively.在这种情况下,另一个记录器正在管理一个file对象、stdout/err 重定向、文件轮换等。我只是想让 Twisted补充那个其他系统并有效地发送它的消息。

I additionally show here how to using log level filtering in Twisted, and how to correctly start and stop their logger as needed.我还在此处展示了如何在 Twisted 中使用日志级别过滤,以及如何根据需要正确启动和停止记录器。

As shown in some other answers, you need to create a new "Observer" bound to a log file object, with a "Filter" to restrict the logging level.如其他一些答案所示,您需要创建一个绑定到日志文件对象的新“观察者”,并使用“过滤器”来限制日志记录级别。 If you want to start/stop/restart - then note you once Twisted logging has previously been "started", one needs to redirect that output to a new file (via a new observer), rather than "start" their logging again.如果您想启动/停止/重新启动 - 请注意,一旦 Twisted 日志记录先前已“启动”,则需要将该输出重定向到一个新文件(通过新的观察者),而不是再次“启动”他们的日志记录。 That prevents warnings which otherwise appear in the log if you attempt to "start" Twisted logging more than once.如果您尝试多次“启动” Twisted 日志记录,则可以防止出现在日志中的警告。

I also point out that a call to theLogPublisher.removeObserver , is harmless to call if that observer was already removed (or never added).我还指出,如果该观察者已被删除(或从未添加),则调用theLogPublisher.removeObserver是无害的。 So, holding on to an observer reference after stopping, is in fact desired here for a simple logic flow, despite perhaps wanting to set such to None - even if that might equate to a tiny "waste" of memory in certain contexts.因此,在停止后保持观察者引用实际上是这里需要的简单逻辑流,尽管可能希望将其设置为None - 即使这可能等同于在某些上下文中的微小“浪费”内存。

from twisted.python import log as twistedlog
from twisted.logger import( FilteringLogObserver, textFileLogObserver,
                            LogLevelFilterPredicate, LogLevel )

twistedLogObserver = None

def startTwistedLogging( logFile, level, isStdMsgHdlr=False ):
    global twistedLogObserver
    observer = FilteringLogObserver( textFileLogObserver( logFile ),
                    predicates=[ LogLevelFilterPredicate( level ) ] )
    if twistedLogObserver:
        twistedlog.theLogPublisher.addObserver( observer )
    else: 
        twistedlog.startLoggingWithObserver( observer, setStdout=isStdMsgHdlr )
    twistedLogObserver = observer

def stopTwistedLogging():
    if twistedLogObserver:
        twistedlog.theLogPublisher.removeObserver( twistedLogObserver )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM