在本系列的第一部分中,我們探討了 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中文網其他相關文章!