如果我使用 celery 作为任务调度程序,如何从 python 应用程序登录到 splunk?

2023-11-29

我有一个在服务器上运行的 python 脚本,该脚本应该由 celery 调度程序每天执行一次。我想将日志直接从脚本发送到 splunk。我正在尝试使用这个splunk_handler图书馆。如果我在本地运行没有 celery 的 splunk_handler ,它似乎可以工作。但如果我与 celery 一起运行它,似乎没有日志到达 splunk_handler。控制台日志:

[SplunkHandler DEBUG] 计时器线程已执行,但没有可发送的有效负载

如何正确设置记录器,以便所有日志都发送到 splunk_handler?

显然,celery 设置了自己的记录器并覆盖了 python 的根记录器。我尝试了几件事,包括从 celery 连接 setup_logging 信号以防止它覆盖记录器或在此信号中设置记录器。

import logging
import os

from splunk_handler import SplunkHandler

这就是我在文件开头设置记录器的方式

logger = logging.getLogger(__name__)
splunk_handler = SplunkHandler(
host=os.getenv('SPLUNK_HTTP_COLLECTOR_URL'),
port=os.getenv('SPLUNK_HTTP_COLLECTOR_PORT'),
token=os.getenv('SPLUNK_TOKEN'),
index=os.getenv('SPLUNK_INDEX'),
debug=True)

splunk_handler.setFormatter(logging.BASIC_FORMAT)
splunk_handler.setLevel(os.getenv('LOGGING_LEVEL', 'DEBUG'))
logger.addHandler(splunk_handler)

Celery 初始化(不确定,如果worker_hijack_root_logger需要设置为False...)

app = Celery('name_of_the_application', broker=CELERY_BROKER_URL)
app.conf.timezone = 'Europe/Berlin'
app.conf.update({
    'worker_hijack_root_logger': False,
})

这里我从 celery 连接到 setup_logging 信号

@setup_logging.connect()
def config_loggers(*args, **kwags):
    pass
    # logger = logging.getLogger(__name__)
    # splunk_handler = SplunkHandler(
    #     host=os.getenv('SPLUNK_HTTP_COLLECTOR_URL'),
    #     port=os.getenv('SPLUNK_HTTP_COLLECTOR_PORT'),
    #     token=os.getenv('SPLUNK_TOKEN'),
    #     index=os.getenv('SPLUNK_INDEX'),
    #     debug=True)
    #
    # splunk_handler.setFormatter(logging.BASIC_FORMAT)
    # splunk_handler.setLevel(os.getenv('LOGGING_LEVEL', 'DEBUG'))
    # logger.addHandler(splunk_handler)

日志语句

logger.info("ARBITRARY LOG MESSAGE")

在 splunk 处理程序上激活调试时(设置为True),splunk 处理程序会记录出没有可用的有效负载,如上面已发布的。有人知道我的代码有什么问题吗?


经过几个小时的找出代码最终可能出现的问题后,我现在得到了令我满意的结果。首先我创建了一个文件loggingsetup.py我用 dictConfig 配置了我的 python 记录器:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': { # Sets up the format of the logging output
        'simple': {
            'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
             'datefmt': '%y %b %d, %H:%M:%S',
            },
        },
    'filters': {
        'filterForSplunk': { # custom loggingFilter, to not have Logs logged to Splunk that have the word celery in the name
            '()': 'loggingsetup.RemoveCeleryLogs', # class on top of this file
            'logsToSkip': 'celery' # word that it is filtered for
        },
    },
    'handlers': {
        'splunk': { # handler for splunk, level Warning. to not have many logs sent to splunk
            'level': 'WARNING',
            'class': 'splunk_logging_handler.SplunkLoggingHandler',
            'url': os.getenv('SPLUNK_HTTP_COLLECTOR_URL'),
            'splunk_key': os.getenv('SPLUNK_TOKEN'),
            'splunk_index': os.getenv('SPLUNK_INDEX'),
            'formatter': 'simple',
            'filters': ['filterForSplunk']
        },
        'console': { 
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout',
            'formatter': 'simple',
        },
    },
    'loggers': { # the logger, root is used
        '': {
            'handlers': ['console', 'splunk'],
            'level': 'DEBUG',
            'propagate': 'False', # does not give logs to other logers
        }
    }
}

对于日志记录过滤器,我必须创建一个继承自logging.Filter 类的类。该类还依赖于文件loggingsetup.py

class RemoveCeleryLogs(logging.Filter): # custom class to filter for celery logs (to not send them to Splunk)
    def __init__(self, logsToSkip=None):
        self.logsToSkip = logsToSkip

    def filter(self, record):
        if self.logsToSkip == None:
            allow = True
        else:
            allow = self.logsToSkip not in record.name
        return allow

之后,您可以像这样配置记录器:

logging.config.dictConfig(loggingsetup.LOGGING)
logger = logging.getLogger('')

因为 celery 重定向了它的日志并且日志加倍,所以我必须更新 app.conf:

app.conf.update({
    'worker_hijack_root_logger': False, # so celery does not set up its loggers
    'worker_redirect_stdouts': False, # so celery does not redirect its logs
})

我面临的下一个问题是,我选择的 Splunk_Logging 库将某些内容与 url 混合在一起。因此,我必须创建自己的 splunk_handler 类,该类继承自logging.Handler 类。这里的重要行如下(来自我的自定义记录器类 splunk_logging_class.py):

auth_header = {'Authorization': 'Splunk {0}'.format(self.splunk_key)}
json_message = {"index": str(self.splunk_index), "event": data}
r = requests.post(self.url, headers=auth_header, json=json_message)

我希望我能帮助那些在 python、splunk 和 celery 日志记录方面面临类似问题的人回答这个问题! :)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果我使用 celery 作为任务调度程序,如何从 python 应用程序登录到 splunk? 的相关文章

随机推荐

  • 追溯性地向方法添加Java注释?

    有没有办法修改 class 文件以便向某些方法添加 Java 注释 基本上我想遍历 jar 文件中每个类文件的方法并注释某些方法 请注意 这不是在使用 jar 文件时的运行时 相反 完成后我想用注释修改类文件 我确实可以访问源代码 所以如果
  • 测试 JButton 时,我的 lambda 表达式有效,但 actionPerformed 无效

    我正在按照以下步骤第一次学习如何使用 Java Swingtutorial在YouTube上 我已经到达涵盖按钮的部分 并且一直按照代码进行操作 但是 在尝试测试按钮时 当我使用actionPerformed方法 我的按钮不会打印出这个词
  • Ruby on Rails:将 javascript 数据发送到 ruby​​ 控制器

    我想发送一个 javascript 数组以由我的控制器中的方法处理 我认为我这样做是错误的 我是一个彻底的 RoR jquery 和 ajax 菜鸟 这是我所拥有的 请给我一些指导 div class dataTable style wid
  • HTML5画布的大小和分辨率有什么关系

    有没有一种方法可以创建大尺寸但低分辨率的画布 我用语法声明画布
  • Android:fastScrollEnabled 起初不起作用

    OK I am working on an App that has a page with a listview and a edittext box at top As you type things into the edittext
  • 通过字符串名称动态实例化子组件 - ReactJs

    我有一个包含 React 组件字符串名称的数组 SampleWidget1 它由外部机制填充 在我的 DashboardInterface 组件中 我想使用该数组 渲染其中包含的组件 并将其显示在 DashboardInterface re
  • 分段错误 11 链接 os x 32 位汇编器

    更新 果然 这是最新版本的 nasm 中的一个错误 我 降级 并按照我接受的答案所示修复我的代码后 一切正常 感谢大家 我在 OS X 上的 32 位汇编程序中遇到了一个非常简单的程序的问题 首先 代码 section data hello
  • 未获取所需的 SOAP 请求 XML

    我正在开发一个使用 OCPP 开放充电点协议 的简单 php 客户端 我已经创建了客户端 这是来自我的代码的请求 XML
  • nodejs将gridFS中存储的图像显示为html

    嗨 我是 Nodejs 和 gridFS 的新手 我正在尝试将 gridFS 中存储的图像显示到我的 html 页面 目前 我正在使用这段代码 gfs exist options function err found if err retu
  • 返回一个空的 Observable

    功能more 应该返回一个Observable来自获取请求 export class Collection public more Observable
  • 如何将 QLineEdit 中的文本居中? [复制]

    这个问题在这里已经有答案了 我搜索过但找不到将 QLineEdit 内的文本居中对齐的解决方案 Example https i stack imgur com eps2z png 对齐 Qt 对齐 该属性保存行编辑的对齐方式 这里允许水平和
  • 带 *args 和 **kwargs 的默认参数

    In Python 2 x 我使用 2 7 这是使用默认参数的正确方法 args and kwargs 我发现了一个与该主题相关的问题 但那是为了Python 3 使用 args kwargs 和可选 默认参数调用 Python 函数 在那
  • 当应用程序停用时如何关闭BackgroundWorker线程?

    我创建线程BackgroundWorker 并且在循环中我每次都会检查是否CancellationPending是真是假 就像这样 public MainPage InitializeComponent bw new BackgroundW
  • 支持通配符 (*) 的 System.StringComparer

    我正在寻找一个快速的 NET 类 库 它有一个支持通配符 和区分大小写的 StringComparer 有任何想法吗 您可以将 Regex 与 RegexOptions IgnoreCase 结合使用 然后与 IsMatch 方法进行比较
  • Java的swing print()用法

    java的swing print 是否必须在EDT 事件调度线程 上调用 众所周知 执行需要花费很长的时间 而且在 EDT 上长时间运行的事情是很痛苦的 简短的回答是 不 打印不需要在 EDT 上进行 官方教程中对此进行了介绍 如何打印文本
  • 高质量完整屏幕截图 VB.Net

    我正在尝试向我的程序添加一项功能 以便在用户单击按钮时获取用户屏幕的完整屏幕截图 我让程序截取屏幕截图并打开文件对话框来保存它 保存有效 问题是 无论我如何保存屏幕截图 保存的图像都会出现显着的质量损失 并且文本和内容周围会出现像素化 这是
  • ajax调用后f:viewParam丢失

    我有这个 f viewParam 来设置值并在视图中的 back bean 中进行搜索
  • 如何在 Javascript 中将按钮点击率限制为每分钟一次

    我有一个基于 PHP 的 Web 应用程序 用于监视进程的状态并显示具有该状态的页面 用户可以单击页面上的按钮来更新状态 但是 我的服务器上的处理负载足够重 因此不希望过于频繁地更新状态 因此 我想要一种方法来限制某人每分钟点击 提交 按钮
  • 区域设置 en-EN 是无效的区域性标识符

    我最近从一台装有 Windows 10 和 VS 2017 的计算机转移到一台装有 Windows 8 1 和 VS 2017 的计算机 我正在处理一段代码 其中有这样一行 Thread CurrentThread CurrentUICul
  • 如果我使用 celery 作为任务调度程序,如何从 python 应用程序登录到 splunk?

    我有一个在服务器上运行的 python 脚本 该脚本应该由 celery 调度程序每天执行一次 我想将日志直接从脚本发送到 splunk 我正在尝试使用这个splunk handler图书馆 如果我在本地运行没有 celery 的 splu