在本系列的第一部分中,我们探讨了 AppSignal 如何显着增强 Open edX 平台的稳健性。我们看到了 Open edX 在扩展时面临的挑战,以及 AppSignal 的功能(包括实时性能监控和自动错误跟踪)如何为 DevOps 团队提供重要工具。我们的演练涵盖了 AppSignal 与 Open edX 的初始设置和集成,强调了这个强大的可观察性框架的直接好处。
在第二篇文章中,我们将深入探讨 AppSignal 提供的高级监控功能。这包括将日志从 Open edX 流式传输到 AppSignal、使用 Celery 监控后台工作人员以及跟踪 Redis 查询。我们将演示如何利用这些功能来解决特定的操作挑战,确保我们的学习平台在不同情况下保持故障安全。
读完本文后,您将了解如何充分利用 AppSignal 来维护和提高 Open edX 平台的性能和可靠性。
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.")
脚本的工作原理如下:
重要提示:请确保您没有向端点发送任何个人身份信息。
现在运行此脚本,它应该将错误日志移至 AppSignal:
您还可以创建一个新的触发器,以便在发生错误等特定事件时立即通知您:
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。
回到 AppSignal 中的仪表板,我们应该在 性能 部分看到 Celery 和 Redis 报告,其中 background 作为命名空间。
对于Redis查询,您可以点击慢速查询:
在本节中,我们将重新审视本系列第一部分中概述的初始问题,并应用实用的 AppSignal 监控解决方案,以确保我们的 Open edX 平台保持强大和可靠。这是一个细分。
我们首先评估网站的整体性能。在性能部分的问题列表下,我们可以看到所有访问过的URL的关键指标:
现在让我们根据平均值对所有操作进行排序。任何超过 1 秒的项目都应被视为危险信号:
正如我们所见,Celery 任务重新评分和重置学生的尝试,LMS 请求显示课程内容,并且某些 API 花费的时间超过 1 秒。另外,我们应该注意,这仅适用于一名活跃用户。如果我们有更多的并发用户,响应时间就会增加。我们的第一个解决方案是向服务器添加更多资源(CPU 和内存)并进行另一次性能测试。
识别出平均响应时间超过 1 秒的操作后,考虑性能优化策略,例如:
我们在上一篇文章中讨论了异常检测和主机监控。让我们为以下项目添加触发器:
我们平台的两个非常重要的指标是我们的活跃用户数量和注册人数。让我们看看如何使用 AppSignal 来衡量这些指标。
首先,将increment_counter添加到common/djangoapps/student/views/management.py和openedx/core/djangoapps/user_authn/views/login.py中,以在有新事件时跟踪和增加登录和注册的数量。
现在让我们登录 Open edX 并注册课程。接下来,让我们前往 AppSignal 中的仪表板。单击添加仪表板,然后创建仪表板,并为其指定名称和描述。
点击添加图表,输入活跃用户作为标题,选择添加指标并使用login_count:
您的仪表板应如下所示:
您可以按照相同的步骤使用 enrollment_count 指标添加注册图表。
为了确保我们网站的样式保持一致,让我们为 static/tailwind/css/lms-main-v1.css 添加新的正常运行时间检查,并在 URL 损坏时收到通知:
在仪表板的错误部分,我们可以查看所有错误,为其设置通知,并尽快修复以防止用户受到负面影响。
在本文的监控 Celery 和 Redis 部分中,我们了解了如何使用 AppSignal 检测 Celery 和 Redis。让我们按照相同的步骤启用 AppSignal,以便我们可以看到分级任务。在 lms/djangoapps/grades/tasks.py 文件中,添加以下行:
我们现在应该在性能 -> 下看到一些需要评分的项目。 问题列表。
如您所见,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中文网其他相关文章!