首页 > 后端开发 > Python教程 > 使用 AppSignal for Python 进行高级 Open edX 监控

使用 AppSignal for Python 进行高级 Open edX 监控

Susan Sarandon
发布: 2024-11-29 19:54:12
原创
874 人浏览过

在本系列的第一部分中,我们探讨了 AppSignal 如何显着增强 Open edX 平台的稳健性。我们看到了 Open edX 在扩展时面临的挑战,以及 AppSignal 的功能(包括实时性能监控和自动错误跟踪)如何为 DevOps 团队提供重要工具。我们的演练涵盖了 AppSignal 与 Open edX 的初始设置和集成,强调了这个强大的可观察性框架的直接好处。

在第二篇文章中,我们将深入探讨 AppSignal 提供的高级监控功能。这包括将日志从 Open edX 流式传输到 AppSignal、使用 Celery 监控后台工作人员以及跟踪 Redis 查询。我们将演示如何利用这些功能来解决特定的操作挑战,确保我们的学习平台在不同情况下保持故障安全。

读完本文后,您将了解如何充分利用 AppSignal 来维护和提高 Open edX 平台的性能和可靠性。

将日志流式传输到 AppSignal

AppSignal 最强大的功能之一是集中式日志管理。

在 Open edX 中,支持团队通常会报告网站问题,工程师可以立即通过 SSH 连接到服务器来检查 Nginx、Mongo、MySQL 和 Open edX 应用程序日志。

无需通过 SSH 连接到服务器即可保存日志的集中存储位置是一项非常强大的功能。我们还可以根据问题的严重性设置通知。

现在让我们看看如何将日志从 Open edX 流式传输到 AppSignal。

创建源

日志记录部分下,单击管理源并创建一个新源,使用HTTP作为平台,JSON作为格式。创建源后,AppSignal 提供一个端点和 API KEY,我们可以POST我们的日志到。

为了更好地控制日志传输,我们可以编写一个简单的 Python 脚本,从本地 Open edX 读取日志,对其进行预处理,然后将重要的日志移至 AppSignal。例如,我编写了以下脚本,仅将错误日志移动到 AppSignal(跳过信息和警告日志):

import requests
import json
from datetime import datetime
import logging

# Setup logging configuration
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# File to keep track of the last processed line
log_pointer_file = '/root/.local/share/tutor/data/lms/logs/processed.log'
log_file = '/root/.local/share/tutor/data/lms/logs/all.log'

# APpSignal API KEY
api_key = "MY-API-KEY"  # Replace with your actual API key
# URL to post the logs
url = f'https://appsignal-endpoint.net/logs?api_key={api_key}'

def read_last_processed():
    try:
        with open(log_pointer_file, 'r') as file:
            content = file.read().strip()
            last_processed = int(content) if content else 0
            logging.info(f"Last processed line number read: {last_processed}")
            return last_processed
    except (FileNotFoundError, ValueError) as e:
        logging.error(f"Could not read from log pointer file: {e}")
        return 0

def update_last_processed(line_number):
    try:
        with open(log_pointer_file, 'w') as file:
            file.write(str(line_number))
            logging.info(f"Updated last processed to line number: {line_number}")
    except Exception as e:
        logging.error(f"Could not update log pointer file: {e}")

def parse_log_line(line):
    if 'ERROR' in line:
        parts = line.split('ERROR', 1)
        timestamp = parts[0].strip()
        message_parts = parts[1].strip().split(' - ', 1)
        message = message_parts[1] if len(message_parts) > 1 else ''
        attributes_part = message_parts[0].strip('[]').split('] [')
        # Flatten attributes into a dictionary with string keys and values
        attributes = {}
        for attr in attributes_part:
            key_value = attr.split(None, 1)
            if len(key_value) == 2:
                key, value = key_value
                key = key.rstrip(']:').replace(' ', '_').replace('.', '_')  # Replace spaces and dots in keys
                if len(key)  last_processed:
                json_data = parse_log_line(line)
                if json_data:
                    response_code = post_logs(json_data)
                    if response_code == 200:
                        update_last_processed(i)
                    else:
                        logging.warning(f"Failed to post log, HTTP status code: {response_code}")

if __name__ == '__main__':
    logging.info("Starting log processing script.")
    process_logs()
    logging.info("Finished log processing.")
登录后复制
登录后复制

脚本的工作原理如下:

  1. 日志文件管理:Tutor 将所有日志保存在 /root/.local/share/tutor/data/lms/logs/all.log 文件中。该文件包含MySQL、LMS、CMS、Caddy、Celery 和其他服务。该脚本使用指针 /root/.local/share/tutor/data/lms/logs/processed.log 文件来跟踪最后处理的行。这确保每个日志仅处理一次。
  2. 错误过滤:如前所述,我们仅将错误日志发送到 AppSignal。
  3. 数据解析和格式化:解析每个错误日志以提取关键信息,例如时间戳和错误消息。该脚本将此数据格式化为适合传输的 JSON 结构。
  4. 日志传输:使用 HTTP POST 请求将格式化的日志数据发送到 AppSignal。

重要提示:请确保您没有向端点发送任何个人身份信息。

现在运行此脚本,它应该将错误日志移至 AppSignal:

Advanced Open edX Monitoring with AppSignal for Python

您还可以创建一个新的触发器,以便在发生错误等特定事件时立即通知您:

Advanced Open edX Monitoring with AppSignal for Python

使用 AppSignal 监控 Celery 和 Redis

Celery(分布式任务队列)是 Open edX 的重要组件,负责管理后台任务,例如评分、证书生成和批量电子邮件发送。 Redis 通常充当 Celery 的代理,管理任务队列。这两个系统对于异步处理都是必不可少的,并且在高使用率期间可能成为瓶颈。使用 AppSignal 监控这些服务可以提供有关任务执行和队列运行状况的宝贵见解,帮助您抢先解决潜在问题。让我们看看如何监控 Celery 和 Redis。

首先,安装必要的软件包。将以下内容添加到 .local/share/tutor/config.yml 文件中的 OPENEDX_EXTRA_PIP_REQUIREMENTS 变量中:

import requests
import json
from datetime import datetime
import logging

# Setup logging configuration
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# File to keep track of the last processed line
log_pointer_file = '/root/.local/share/tutor/data/lms/logs/processed.log'
log_file = '/root/.local/share/tutor/data/lms/logs/all.log'

# APpSignal API KEY
api_key = "MY-API-KEY"  # Replace with your actual API key
# URL to post the logs
url = f'https://appsignal-endpoint.net/logs?api_key={api_key}'

def read_last_processed():
    try:
        with open(log_pointer_file, 'r') as file:
            content = file.read().strip()
            last_processed = int(content) if content else 0
            logging.info(f"Last processed line number read: {last_processed}")
            return last_processed
    except (FileNotFoundError, ValueError) as e:
        logging.error(f"Could not read from log pointer file: {e}")
        return 0

def update_last_processed(line_number):
    try:
        with open(log_pointer_file, 'w') as file:
            file.write(str(line_number))
            logging.info(f"Updated last processed to line number: {line_number}")
    except Exception as e:
        logging.error(f"Could not update log pointer file: {e}")

def parse_log_line(line):
    if 'ERROR' in line:
        parts = line.split('ERROR', 1)
        timestamp = parts[0].strip()
        message_parts = parts[1].strip().split(' - ', 1)
        message = message_parts[1] if len(message_parts) > 1 else ''
        attributes_part = message_parts[0].strip('[]').split('] [')
        # Flatten attributes into a dictionary with string keys and values
        attributes = {}
        for attr in attributes_part:
            key_value = attr.split(None, 1)
            if len(key_value) == 2:
                key, value = key_value
                key = key.rstrip(']:').replace(' ', '_').replace('.', '_')  # Replace spaces and dots in keys
                if len(key)  last_processed:
                json_data = parse_log_line(line)
                if json_data:
                    response_code = post_logs(json_data)
                    if response_code == 200:
                        update_last_processed(i)
                    else:
                        logging.warning(f"Failed to post log, HTTP status code: {response_code}")

if __name__ == '__main__':
    logging.info("Starting log processing script.")
    process_logs()
    logging.info("Finished log processing.")
登录后复制
登录后复制

它应该如下所示:

- opentelemetry-instrumentation-celery==0.45b0
- opentelemetry-instrumentation-redis==0.45b0
登录后复制

如您所见,我们正在为 Celery 和 Redis 安装 opentelemetry 包。

现在,我们可以使用worker_process_init来检测Celery,以将其指标报告给AppSignal。

Advanced Open edX Monitoring with AppSignal for Python

回到 AppSignal 中的仪表板,我们应该在 性能 部分看到 Celery 和 Redis 报告,其中 background 作为命名空间。

Advanced Open edX Monitoring with AppSignal for Python

对于Redis查询,您可以点击慢速查询

Advanced Open edX Monitoring with AppSignal for Python

实用监控:使用 AppSignal 增强 Open edX

在本节中,我们将重新审视本系列第一部分中概述的初始问题,并应用实用的 AppSignal 监控解决方案,以确保我们的 Open edX 平台保持强大和可靠。这是一个细分。

网站性能改进

我们首先评估网站的整体性能。在性能部分的问题列表下,我们可以看到所有访问过的URL的关键指标:

  • 响应时间:通过测量处理和响应请求所需的时间来直接反映用户体验。影响这一点的因素包括数据库查询和中间件操作。
  • 吞吐量:表示给定时间范围内处理的请求数量。
  • 平均响应时间:提供对特定端点的所有请求的平均响应时间。任何超过 1 秒的平均响应时间都是一个潜在问题,并突出显示需要优化的区域。
  • 90% 响应时间:例如,GET store/ 的 90% 响应时间为 7 毫秒,表明 90% 的请求在 7 毫秒或更短时间内完成。

现在让我们根据平均值对所有操作进行排序。任何超过 1 秒的项目都应被视为危险信号:

Advanced Open edX Monitoring with AppSignal for Python
Advanced Open edX Monitoring with AppSignal for Python

正如我们所见,Celery 任务重新评分和重置学生的尝试,LMS 请求显示课程内容,并且某些 API 花费的时间超过 1 秒。另外,我们应该注意,这仅适用于一名活跃用户。如果我们有更多的并发用户,响应时间就会增加。我们的第一个解决方案是向服务器添加更多资源(CPU 和内存)并进行另一次性能测试。

识别出平均响应时间超过 1 秒的操作后,考虑性能优化策略,例如:

  • 最小化 JavaScript 执行
  • 将 CDN 用于静态内容
  • 实施缓存技术。

服务器资源监控

我们在上一篇文章中讨论了异常检测和主机监控。让我们为以下项目添加触发器:

  • CPU 使用率
  • 磁盘使用情况
  • 内存使用情况
  • 网络流量
  • 错误率

自定义指标

我们平台的两个非常重要的指标是我们的活跃用户数量和注册人数。让我们看看如何使用 AppSignal 来衡量这些指标。

首先,将increment_counter添加到common/djangoapps/student/views/management.py和openedx/core/djangoapps/user_authn/views/login.py中,以在有新事件时跟踪和增加登录和注册的数量。

Advanced Open edX Monitoring with AppSignal for Python

Advanced Open edX Monitoring with AppSignal for Python

现在让我们登录 Open edX 并注册课程。接下来,让我们前往 AppSignal 中的仪表板。单击添加仪表板,然后创建仪表板,并为其指定名称和描述。

点击添加图表,输入活跃用户作为标题,选择添加指标并使用login_count:

Advanced Open edX Monitoring with AppSignal for Python

您的仪表板应如下所示:

Advanced Open edX Monitoring with AppSignal for Python

您可以按照相同的步骤使用 enrollment_count 指标添加注册图表。

确保风格一致

为了确保我们网站的样式保持一致,让我们为 static/tailwind/css/lms-main-v1.css 添加新的正常运行时间检查,并在 URL 损坏时收到通知:

Advanced Open edX Monitoring with AppSignal for Python

Advanced Open edX Monitoring with AppSignal for Python

电子邮件传送和错误处理

在仪表板的错误部分,我们可以查看所有错误,为其设置通知,并尽快修复以防止用户受到负面影响。

评分的后台工作效率

在本文的监控 Celery 和 Redis 部分中,我们了解了如何使用 AppSignal 检测 Celery 和 Redis。让我们按照相同的步骤启用 AppSignal,以便我们可以看到分级任务。在 lms/djangoapps/grades/tasks.py 文件中,添加以下行:

Advanced Open edX Monitoring with AppSignal for Python

我们现在应该在性能 -> 下看到一些需要评分的项目。 问题列表

使用 AppSignal for Python 进行高级 Open edX 监控

如您所见,recalculate_subsection_grade_v3(我们的主要评分 Celery 任务)需要 212 毫秒。对于重新评分,lms.djangoapps.instructor_task.tasks.reset_problem_attempts 和 lms.djangoapps.instructor_task.tasks.rescore_problem 需要 1.77 秒。

总结

在这个由两部分组成的系列中,我们将 AppSignal 与 Open edX 集成以增强其监控功能。我们从基础知识开始 - 设置和了解 AppSignal 的基本功能,包括错误跟踪和性能监控。

在本文中,我们解决了如何有效地将日志从各种 Open edX 服务流式传输到 AppSignal,确保所有相关信息集中且易于访问。我们还监控了 Celery 和 Redis 处理的关键异步任务。

最后,我们解决了一些现实世界的挑战,例如网站响应缓慢、注册量高期间的资源瓶颈,以及样式损坏等意外问题。

现在,您应该全面了解如何利用 AppSignal 来监控并显着提高 Open edX 平台的性能和可靠性。

如果您对 Open edX 有任何疑问或需要进一步帮助,请随时访问 cubite.io 或直接通过 amir@cubite.io 与我联系。

P.S.如果您想在 Python 文章发布后立即阅读,请订阅我们的 Python Wizardry 时事通讯,不错过任何一篇文章!

以上是使用 AppSignal for Python 进行高级 Open edX 监控的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板